Message ID | 20210226155814.27536-2-srinivas.kandagatla@linaro.org |
---|---|
State | New |
Headers | show |
Series | soundwire: qcom: various improvements | expand |
Thanks Pierre for reviewing the patches! On 26/02/2021 16:45, Pierre-Louis Bossart wrote: > > > On 2/26/21 9:58 AM, Srinivas Kandagatla wrote: >> Some of the transport parameters derived from device tree >> are not fully parsed by the driver. >> >> This patch adds support to parse those missing parameters. >> >> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> >> --- >> drivers/soundwire/qcom.c | 99 ++++++++++++++++++++++++++++++++++++++-- >> 1 file changed, 95 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c >> index 6d22df01f354..fee7465c72c2 100644 >> --- a/drivers/soundwire/qcom.c >> +++ b/drivers/soundwire/qcom.c >> @@ -54,7 +54,13 @@ >> #define SWRM_MCP_SLV_STATUS 0x1090 >> #define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0) >> #define SWRM_DP_PORT_CTRL_BANK(n, m) (0x1124 + 0x100 * (n - 1) + >> 0x40 * m) >> +#define SWRM_DP_PORT_CTRL_2_BANK(n, m) (0x1128 + 0x100 * (n - 1) + >> 0x40 * m) >> +#define SWRM_DP_BLOCK_CTRL_1(n) (0x112C + 0x100 * (n - 1)) >> +#define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + >> 0x40 * m) >> +#define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + >> 0x40 * m) >> #define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) >> + 0x40 * m) >> +#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1)) >> + >> #define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18 >> #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 >> #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 >> @@ -73,12 +79,20 @@ >> #define QCOM_SDW_MAX_PORTS 14 >> #define DEFAULT_CLK_FREQ 9600000 >> #define SWRM_MAX_DAIS 0xF >> +#define SWR_INVALID_PARAM 0xFF >> +#define SWR_HSTOP_MAX_VAL 0xF >> +#define SWR_HSTART_MIN_VAL 0x0 >> struct qcom_swrm_port_config { >> u8 si; >> u8 off1; >> u8 off2; >> u8 bp_mode; >> + u8 hstart; >> + u8 hstop; >> + u8 word_length; >> + u8 blk_group_count; >> + u8 lane_control; >> }; >> struct qcom_swrm_ctrl { >> @@ -396,7 +410,13 @@ static int qcom_swrm_port_params(struct sdw_bus >> *bus, >> struct sdw_port_params *p_params, >> unsigned int bank) >> { >> - /* TBD */ >> + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); >> + >> + if (p_params->bps != SWR_INVALID_PARAM) > > this is odd. sdw_port_params is a structure in > include/linux/soundwire/sdw.h, but here you are comparing the value with > a private qualcomm-defined value. > > The Word length of the port is limited by the standard (64), so your > choice of 0xFF for SWR_INVALID_PARAM is legit, but it should be a > 'public' define. > Am not sure if this really make sense to add it as a public define! This is more of how the parameters are marked as not applicable for some ports while passing these values from device tree. But I agree with your comments, now I have modified the code to look at the qcom_swrm_port_config instead of checking the "struct sdw_port_params" or "struct sdw_transport_params" which should make this INVALID flag not relevant to these data-structures anymore! >> + return ctrl->reg_write(ctrl, >> + SWRM_DP_BLOCK_CTRL_1(p_params->num), >> + p_params->bps - 1); >> + >> return 0; >> } >> @@ -415,10 +435,32 @@ static int qcom_swrm_transport_params(struct >> sdw_bus *bus, >> ret = ctrl->reg_write(ctrl, reg, value); >> - if (!ret && params->blk_pkg_mode) { >> - reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank); >> + if (params->lane_ctrl != SWR_INVALID_PARAM) { >> + reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank); >> + value = params->lane_ctrl; >> + ret = ctrl->reg_write(ctrl, reg, value); >> + } >> - ret = ctrl->reg_write(ctrl, reg, 1); >> + if (params->blk_grp_ctrl != SWR_INVALID_PARAM) { >> + reg = SWRM_DP_BLOCK_CTRL2_BANK(params->port_num, bank); >> + value = params->blk_grp_ctrl; >> + ret = ctrl->reg_write(ctrl, reg, value); >> + } >> + >> + if (params->hstart != SWR_INVALID_PARAM >> + && params->hstop != SWR_INVALID_PARAM) { >> + reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank); >> + value = (params->hstop << 4) | params->hstart; >> + ret = ctrl->reg_write(ctrl, reg, value); >> + } else { >> + reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank); >> + value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL; >> + ret = ctrl->reg_write(ctrl, reg, value); >> + } >> + >> + if (params->blk_pkg_mode != SWR_INVALID_PARAM) { >> + reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank); >> + ret = ctrl->reg_write(ctrl, reg, params->blk_pkg_mode); >> } > > same comments here, you should define a public define for all those > parameters. > >> return ret; >> @@ -470,6 +512,17 @@ static int qcom_swrm_compute_params(struct >> sdw_bus *bus) >> p_rt->transport_params.offset1 = pcfg->off1; >> p_rt->transport_params.offset2 = pcfg->off2; >> p_rt->transport_params.blk_pkg_mode = pcfg->bp_mode; >> + p_rt->transport_params.blk_grp_ctrl = pcfg->blk_group_count; >> + p_rt->transport_params.hstart = pcfg->hstart; >> + p_rt->transport_params.hstop = pcfg->hstop; >> + p_rt->transport_params.lane_ctrl = pcfg->lane_control; >> + if (pcfg->word_length != SWR_INVALID_PARAM) { >> + sdw_fill_port_params(&p_rt->port_params, >> + p_rt->num, pcfg->word_length + 1, >> + SDW_PORT_FLOW_MODE_ISOCH, >> + SDW_PORT_DATA_MODE_NORMAL); >> + } >> + >> } >> list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { >> @@ -481,6 +534,18 @@ static int qcom_swrm_compute_params(struct >> sdw_bus *bus) >> p_rt->transport_params.offset1 = pcfg->off1; >> p_rt->transport_params.offset2 = pcfg->off2; >> p_rt->transport_params.blk_pkg_mode = pcfg->bp_mode; >> + p_rt->transport_params.blk_grp_ctrl = >> pcfg->blk_group_count; >> + >> + p_rt->transport_params.hstart = pcfg->hstart; >> + p_rt->transport_params.hstop = pcfg->hstop; >> + p_rt->transport_params.lane_ctrl = pcfg->lane_control; >> + if (pcfg->word_length != SWR_INVALID_PARAM) { >> + sdw_fill_port_params(&p_rt->port_params, >> + p_rt->num, >> + pcfg->word_length + 1, >> + SDW_PORT_FLOW_MODE_ISOCH, >> + SDW_PORT_DATA_MODE_NORMAL); >> + } >> i++; >> } >> } >> @@ -728,6 +793,11 @@ static int qcom_swrm_get_port_config(struct >> qcom_swrm_ctrl *ctrl) >> u8 off2[QCOM_SDW_MAX_PORTS]; >> u8 si[QCOM_SDW_MAX_PORTS]; >> u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, }; >> + u8 hstart[QCOM_SDW_MAX_PORTS]; >> + u8 hstop[QCOM_SDW_MAX_PORTS]; >> + u8 word_length[QCOM_SDW_MAX_PORTS]; >> + u8 blk_group_count[QCOM_SDW_MAX_PORTS]; >> + u8 lane_control[QCOM_SDW_MAX_PORTS]; >> int i, ret, nports, val; >> ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); >> @@ -772,11 +842,32 @@ static int qcom_swrm_get_port_config(struct >> qcom_swrm_ctrl *ctrl) >> ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode", >> bp_mode, nports); >> + >> + memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); >> + of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports); >> + >> + memset(hstop, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); >> + of_property_read_u8_array(np, "qcom,ports-hstop", hstop, nports); >> + >> + memset(word_length, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); >> + of_property_read_u8_array(np, "qcom,ports-word-length", >> word_length, nports); >> + >> + memset(blk_group_count, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); >> + of_property_read_u8_array(np, "qcom,ports-block-group-count", >> blk_group_count, nports); >> + >> + memset(lane_control, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); >> + of_property_read_u8_array(np, "qcom,ports-lane-control", >> lane_control, nports); >> + >> for (i = 0; i < nports; i++) { >> ctrl->pconfig[i].si = si[i]; >> ctrl->pconfig[i].off1 = off1[i]; >> ctrl->pconfig[i].off2 = off2[i]; >> ctrl->pconfig[i].bp_mode = bp_mode[i]; >> + ctrl->pconfig[i].hstart = hstart[i]; >> + ctrl->pconfig[i].hstop = hstop[i]; >> + ctrl->pconfig[i].word_length = word_length[i]; >> + ctrl->pconfig[i].blk_group_count = blk_group_count[i]; >> + ctrl->pconfig[i].lane_control = lane_control[i]; >> } > > I don't get why you test the values parsed from DT before writing the > registers. Why do test them here? if some values are incorrect it's much > better to provide an error log instead of writing a partially valid > setup to hardware, no? from DT we pass parameters for all the master ports, however some of these parameters are not really applicable for some of the ports! so the way we handle this is by marking them as 0xFF which means these values are not applicable for those ports! Having said that I think I should probably redefine SWR_INVALID_PARAM to QCOM_SWR_PARAM_NA or something on those lines! --srini >> return 0; >>
>>> for (i = 0; i < nports; i++) { >>> ctrl->pconfig[i].si = si[i]; >>> ctrl->pconfig[i].off1 = off1[i]; >>> ctrl->pconfig[i].off2 = off2[i]; >>> ctrl->pconfig[i].bp_mode = bp_mode[i]; >>> + ctrl->pconfig[i].hstart = hstart[i]; >>> + ctrl->pconfig[i].hstop = hstop[i]; >>> + ctrl->pconfig[i].word_length = word_length[i]; >>> + ctrl->pconfig[i].blk_group_count = blk_group_count[i]; >>> + ctrl->pconfig[i].lane_control = lane_control[i]; >>> } >> >> I don't get why you test the values parsed from DT before writing the >> registers. Why do test them here? if some values are incorrect it's >> much better to provide an error log instead of writing a partially >> valid setup to hardware, no? > > from DT we pass parameters for all the master ports, however some of > these parameters are not really applicable for some of the ports! so the > way we handle this is by marking them as 0xFF which means these values > are not applicable for those ports! Having said that I think I should > probably redefine SWR_INVALID_PARAM to QCOM_SWR_PARAM_NA or something on > those lines! Humm, do you have an example here? It's a bit odd to define DT properties that may or may not be valid. If this is intentional and desired, this should still be captured somehow, e.g. in the bindings documentation or in the code with a comment, no?
On 02/03/2021 14:29, Pierre-Louis Bossart wrote: > >>>> for (i = 0; i < nports; i++) { >>>> ctrl->pconfig[i].si = si[i]; >>>> ctrl->pconfig[i].off1 = off1[i]; >>>> ctrl->pconfig[i].off2 = off2[i]; >>>> ctrl->pconfig[i].bp_mode = bp_mode[i]; >>>> + ctrl->pconfig[i].hstart = hstart[i]; >>>> + ctrl->pconfig[i].hstop = hstop[i]; >>>> + ctrl->pconfig[i].word_length = word_length[i]; >>>> + ctrl->pconfig[i].blk_group_count = blk_group_count[i]; >>>> + ctrl->pconfig[i].lane_control = lane_control[i]; >>>> } >>> >>> I don't get why you test the values parsed from DT before writing the >>> registers. Why do test them here? if some values are incorrect it's >>> much better to provide an error log instead of writing a partially >>> valid setup to hardware, no? >> >> from DT we pass parameters for all the master ports, however some of >> these parameters are not really applicable for some of the ports! so >> the way we handle this is by marking them as 0xFF which means these >> values are not applicable for those ports! Having said that I think I >> should probably redefine SWR_INVALID_PARAM to QCOM_SWR_PARAM_NA or >> something on those lines! > > Humm, do you have an example here? It's a bit odd to define DT In DT we describe parameters for each port in an array so, parameters for ports that are not applicable/available for that platform can be marked with 0xFF. Most importantly, Some of these registers are only implemented based on the data ports. Ex: GROUP_CONTROL register is only implemented for data ports that support Group Count other than 0. Like wise for HSTART/STOP for Full Data ports only! So avoiding reading/writing to registers by passing invalid/not-applicable value 0xFF made more sense! Here are some examples of controller instances on SM8250 SoC. soundwire-controller@3230000 { reg = <0 0x3230000 0 0x2000>; compatible = "qcom,soundwire-v1.5.1"; interrupts-extended = <&intc GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>, <&pdc 109 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "core", "wakeup"; qcom,clock-stop-mode0; clocks = <&txmacro>; clock-names = "iface"; qcom,din-ports = <5>; qcom,dout-ports = <0>; qcom,ports-sinterval-low = /bits/ 8 <0xFF 0x01 0x01 0x03 0x03>; qcom,ports-offset1 = /bits/ 8 <0xFF 0x01 0x00 0x02 0x00>; qcom,ports-offset2 = /bits/ 8 <0xFF 0x00 0x00 0x00 0x00>; qcom,ports-block-pack-mode = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>; qcom,ports-hstart = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>; qcom,ports-hstop = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>; qcom,ports-word-length = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>; qcom,ports-block-group-count = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>; qcom,ports-lane-control = /bits/ 8 <0xFF 0x00 0x01 0x00 0x01>; qcom,port-offset = <1>; #sound-dai-cells = <1>; #address-cells = <2>; #size-cells = <0>; }; soundwire-controller@3210000 { reg = <0 0x3210000 0 0x2000>; compatible = "qcom,soundwire-v1.5.1"; interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rxmacro>; clock-names = "iface"; qcom,clock-stop-mode0; qcom,din-ports = <0>; qcom,dout-ports = <5>; qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1F 0x1F 0x07 0x00>; qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0B 0x01 0x00>; qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0B 0x00 0x00>; qcom,ports-hstart = /bits/ 8 <0xFF 0x03 0xFF 0xFF 0xFF>; qcom,ports-hstop = /bits/ 8 <0xFF 0x06 0xFF 0xFF 0xFF>; qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xFF 0xFF>; qcom,ports-block-pack-mode = /bits/ 8 <0xFF 0x00 0x01 0xFF 0xFF>; qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; qcom,ports-block-group-count = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0x00>; #sound-dai-cells = <1>; #address-cells = <2>; #size-cells = <0>; }; > properties that may or may not be valid. If this is intentional and > desired, this should still be captured somehow, e.g. in the bindings > documentation or in the code with a comment, no? Yes, I agree with you on this, I should document this in bindings! --srini
> soundwire-controller@3210000 { > reg = <0 0x3210000 0 0x2000>; > compatible = "qcom,soundwire-v1.5.1"; > interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>; > clocks = <&rxmacro>; > clock-names = "iface"; > qcom,clock-stop-mode0; > qcom,din-ports = <0>; > qcom,dout-ports = <5>; > > qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1F 0x1F 0x07 0x00>; > qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0B 0x01 0x00>; > qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0B 0x00 0x00>; > qcom,ports-hstart = /bits/ 8 <0xFF 0x03 0xFF 0xFF 0xFF>; > qcom,ports-hstop = /bits/ 8 <0xFF 0x06 0xFF 0xFF 0xFF>; > qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xFF 0xFF>; > qcom,ports-block-pack-mode = /bits/ 8 <0xFF 0x00 0x01 0xFF 0xFF>; > qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>; > qcom,ports-block-group-count = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0x00>; > > #sound-dai-cells = <1>; > #address-cells = <2>; > #size-cells = <0>; > }; >> properties that may or may not be valid. If this is intentional and >> desired, this should still be captured somehow, e.g. in the bindings >> documentation or in the code with a comment, no? > > Yes, I agree with you on this, I should document this in bindings! thanks for the explanations, it'd be useful indeed to document what this magic 0xFF value means.
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 6d22df01f354..fee7465c72c2 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -54,7 +54,13 @@ #define SWRM_MCP_SLV_STATUS 0x1090 #define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0) #define SWRM_DP_PORT_CTRL_BANK(n, m) (0x1124 + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DP_PORT_CTRL_2_BANK(n, m) (0x1128 + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DP_BLOCK_CTRL_1(n) (0x112C + 0x100 * (n - 1)) +#define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m) #define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m) +#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1)) + #define SWRM_DP_PORT_CTRL_EN_CHAN_SHFT 0x18 #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT 0x10 #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 @@ -73,12 +79,20 @@ #define QCOM_SDW_MAX_PORTS 14 #define DEFAULT_CLK_FREQ 9600000 #define SWRM_MAX_DAIS 0xF +#define SWR_INVALID_PARAM 0xFF +#define SWR_HSTOP_MAX_VAL 0xF +#define SWR_HSTART_MIN_VAL 0x0 struct qcom_swrm_port_config { u8 si; u8 off1; u8 off2; u8 bp_mode; + u8 hstart; + u8 hstop; + u8 word_length; + u8 blk_group_count; + u8 lane_control; }; struct qcom_swrm_ctrl { @@ -396,7 +410,13 @@ static int qcom_swrm_port_params(struct sdw_bus *bus, struct sdw_port_params *p_params, unsigned int bank) { - /* TBD */ + struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + + if (p_params->bps != SWR_INVALID_PARAM) + return ctrl->reg_write(ctrl, + SWRM_DP_BLOCK_CTRL_1(p_params->num), + p_params->bps - 1); + return 0; } @@ -415,10 +435,32 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus, ret = ctrl->reg_write(ctrl, reg, value); - if (!ret && params->blk_pkg_mode) { - reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank); + if (params->lane_ctrl != SWR_INVALID_PARAM) { + reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank); + value = params->lane_ctrl; + ret = ctrl->reg_write(ctrl, reg, value); + } - ret = ctrl->reg_write(ctrl, reg, 1); + if (params->blk_grp_ctrl != SWR_INVALID_PARAM) { + reg = SWRM_DP_BLOCK_CTRL2_BANK(params->port_num, bank); + value = params->blk_grp_ctrl; + ret = ctrl->reg_write(ctrl, reg, value); + } + + if (params->hstart != SWR_INVALID_PARAM + && params->hstop != SWR_INVALID_PARAM) { + reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank); + value = (params->hstop << 4) | params->hstart; + ret = ctrl->reg_write(ctrl, reg, value); + } else { + reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank); + value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL; + ret = ctrl->reg_write(ctrl, reg, value); + } + + if (params->blk_pkg_mode != SWR_INVALID_PARAM) { + reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank); + ret = ctrl->reg_write(ctrl, reg, params->blk_pkg_mode); } return ret; @@ -470,6 +512,17 @@ static int qcom_swrm_compute_params(struct sdw_bus *bus) p_rt->transport_params.offset1 = pcfg->off1; p_rt->transport_params.offset2 = pcfg->off2; p_rt->transport_params.blk_pkg_mode = pcfg->bp_mode; + p_rt->transport_params.blk_grp_ctrl = pcfg->blk_group_count; + p_rt->transport_params.hstart = pcfg->hstart; + p_rt->transport_params.hstop = pcfg->hstop; + p_rt->transport_params.lane_ctrl = pcfg->lane_control; + if (pcfg->word_length != SWR_INVALID_PARAM) { + sdw_fill_port_params(&p_rt->port_params, + p_rt->num, pcfg->word_length + 1, + SDW_PORT_FLOW_MODE_ISOCH, + SDW_PORT_DATA_MODE_NORMAL); + } + } list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { @@ -481,6 +534,18 @@ static int qcom_swrm_compute_params(struct sdw_bus *bus) p_rt->transport_params.offset1 = pcfg->off1; p_rt->transport_params.offset2 = pcfg->off2; p_rt->transport_params.blk_pkg_mode = pcfg->bp_mode; + p_rt->transport_params.blk_grp_ctrl = pcfg->blk_group_count; + + p_rt->transport_params.hstart = pcfg->hstart; + p_rt->transport_params.hstop = pcfg->hstop; + p_rt->transport_params.lane_ctrl = pcfg->lane_control; + if (pcfg->word_length != SWR_INVALID_PARAM) { + sdw_fill_port_params(&p_rt->port_params, + p_rt->num, + pcfg->word_length + 1, + SDW_PORT_FLOW_MODE_ISOCH, + SDW_PORT_DATA_MODE_NORMAL); + } i++; } } @@ -728,6 +793,11 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) u8 off2[QCOM_SDW_MAX_PORTS]; u8 si[QCOM_SDW_MAX_PORTS]; u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, }; + u8 hstart[QCOM_SDW_MAX_PORTS]; + u8 hstop[QCOM_SDW_MAX_PORTS]; + u8 word_length[QCOM_SDW_MAX_PORTS]; + u8 blk_group_count[QCOM_SDW_MAX_PORTS]; + u8 lane_control[QCOM_SDW_MAX_PORTS]; int i, ret, nports, val; ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); @@ -772,11 +842,32 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode", bp_mode, nports); + + memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); + of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports); + + memset(hstop, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); + of_property_read_u8_array(np, "qcom,ports-hstop", hstop, nports); + + memset(word_length, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); + of_property_read_u8_array(np, "qcom,ports-word-length", word_length, nports); + + memset(blk_group_count, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); + of_property_read_u8_array(np, "qcom,ports-block-group-count", blk_group_count, nports); + + memset(lane_control, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); + of_property_read_u8_array(np, "qcom,ports-lane-control", lane_control, nports); + for (i = 0; i < nports; i++) { ctrl->pconfig[i].si = si[i]; ctrl->pconfig[i].off1 = off1[i]; ctrl->pconfig[i].off2 = off2[i]; ctrl->pconfig[i].bp_mode = bp_mode[i]; + ctrl->pconfig[i].hstart = hstart[i]; + ctrl->pconfig[i].hstop = hstop[i]; + ctrl->pconfig[i].word_length = word_length[i]; + ctrl->pconfig[i].blk_group_count = blk_group_count[i]; + ctrl->pconfig[i].lane_control = lane_control[i]; } return 0;
Some of the transport parameters derived from device tree are not fully parsed by the driver. This patch adds support to parse those missing parameters. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> --- drivers/soundwire/qcom.c | 99 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 4 deletions(-)