diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-07-05 08:15:08 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-07-05 08:15:08 +0200 |
commit | 2f4281f4dce12440727ab770683cfb83eab62a26 (patch) | |
tree | 722ae855b46858fcd0ba08b61a08ae04891d0116 /drivers/soundwire | |
parent | 996cdfaf538f159f822f2619d55449c587b86cb6 (diff) | |
parent | 2aeac95d1a4cc85aae57ab842d5c3340df0f817f (diff) | |
download | lwn-2f4281f4dce12440727ab770683cfb83eab62a26.tar.gz lwn-2f4281f4dce12440727ab770683cfb83eab62a26.zip |
Merge tag 'soundwire-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire into char-misc-next
Vinod writes:
soundwire updates for v5.3-rc1
Updates for 5.3 include:
- module_sdw_driver macro for drivers
- Documentation updates for code-blocks
- Improvement from Pierre on intel and cadence driver
- Clarification of DisCo properties and updates
* tag 'soundwire-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
soundwire: add module_sdw_driver helper macro
docs: soundwire: locking: fix tags for a code-block
soundwire: intel_init: add checks on link numbers
soundwire: fix typo in comments
soundwire: Intel: add log for number of PCM and PDM PDIs
soundwire: cadence_master: check the number of bidir PDIs
soundwire: cadence_master: log Slave status mask on errors
soundwire: cadence_master: use rate_limited dynamic debug
soundwire: rename/clarify MIPI DisCo properties
soundwire: clarify comment
soundwire: mipi-disco: fix clock stop modes
soundwire: rename 'freq' fields
soundwire: mipi-disco: remove master_count property for masters
soundwire: remove master data port properties
soundwire: add port-related definitions
soundwire: mipi_disco: fix master/link error
soundwire: intel: filter SoundWire controller device search
soundwire: cdns: Fix compilation error on arm64
Diffstat (limited to 'drivers/soundwire')
-rw-r--r-- | drivers/soundwire/bus.c | 6 | ||||
-rw-r--r-- | drivers/soundwire/cadence_master.c | 30 | ||||
-rw-r--r-- | drivers/soundwire/intel.c | 17 | ||||
-rw-r--r-- | drivers/soundwire/intel.h | 2 | ||||
-rw-r--r-- | drivers/soundwire/intel_init.c | 25 | ||||
-rw-r--r-- | drivers/soundwire/mipi_disco.c | 35 | ||||
-rw-r--r-- | drivers/soundwire/stream.c | 8 |
7 files changed, 79 insertions, 44 deletions
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index aac35fc3cf22..fe745830a261 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -87,7 +87,7 @@ int sdw_add_bus_master(struct sdw_bus *bus) /* * Initialize clock values based on Master properties. The max - * frequency is read from max_freq property. Current assumption + * frequency is read from max_clk_freq property. Current assumption * is that the bus will start at highest clock frequency when * powered on. * @@ -95,7 +95,7 @@ int sdw_add_bus_master(struct sdw_bus *bus) * to start with bank 0 (Table 40 of Spec) */ prop = &bus->prop; - bus->params.max_dr_freq = prop->max_freq * SDW_DOUBLE_RATE_FACTOR; + bus->params.max_dr_freq = prop->max_clk_freq * SDW_DOUBLE_RATE_FACTOR; bus->params.curr_dr_freq = bus->params.max_dr_freq; bus->params.curr_bank = SDW_BANK0; bus->params.next_bank = SDW_BANK1; @@ -648,7 +648,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave) return 0; /* Enable DP0 interrupts */ - val = prop->dp0_prop->device_interrupts; + val = prop->dp0_prop->imp_def_interrupts; val |= SDW_DP0_INT_PORT_READY | SDW_DP0_INT_BRA_FAILURE; ret = sdw_update(slave, SDW_DP0_INTMASK, val, val); diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 682789bb8ab3..ff4badc9b3de 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -9,6 +9,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw_registers.h> @@ -236,19 +237,19 @@ cdns_fill_msg_resp(struct sdw_cdns *cdns, for (i = 0; i < count; i++) { if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) { no_ack = 1; - dev_dbg(cdns->dev, "Msg Ack not received\n"); + dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n"); if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { nack = 1; - dev_err(cdns->dev, "Msg NACK received\n"); + dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); } } } if (nack) { - dev_err(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num); + dev_err_ratelimited(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num); return SDW_CMD_FAIL; } else if (no_ack) { - dev_dbg(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num); + dev_dbg_ratelimited(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num); return SDW_CMD_IGNORED; } @@ -356,12 +357,12 @@ cdns_program_scp_addr(struct sdw_cdns *cdns, struct sdw_msg *msg) /* For NACK, NO ack, don't return err if we are in Broadcast mode */ if (nack) { - dev_err(cdns->dev, - "SCP_addrpage NACKed for Slave %d\n", msg->dev_num); + dev_err_ratelimited(cdns->dev, + "SCP_addrpage NACKed for Slave %d\n", msg->dev_num); return SDW_CMD_FAIL; } else if (no_ack) { - dev_dbg(cdns->dev, - "SCP_addrpage ignored for Slave %d\n", msg->dev_num); + dev_dbg_ratelimited(cdns->dev, + "SCP_addrpage ignored for Slave %d\n", msg->dev_num); return SDW_CMD_IGNORED; } @@ -486,7 +487,8 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, { enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; bool is_slave = false; - u64 slave, mask; + u64 slave; + u32 mask; int i, set_status; /* combine the two status */ @@ -524,9 +526,9 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, /* first check if Slave reported multiple status */ if (set_status > 1) { - dev_warn(cdns->dev, - "Slave reported multiple Status: %d\n", - status[i]); + dev_warn_ratelimited(cdns->dev, + "Slave reported multiple Status: %d\n", + mask); /* * TODO: we need to reread the status here by * issuing a PING cmd @@ -612,7 +614,7 @@ irqreturn_t sdw_cdns_thread(int irq, void *dev_id) struct sdw_cdns *cdns = dev_id; u32 slave0, slave1; - dev_dbg(cdns->dev, "Slave status change\n"); + dev_dbg_ratelimited(cdns->dev, "Slave status change\n"); slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0); slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1); @@ -716,6 +718,8 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns, stream = &cdns->pcm; /* First two PDIs are reserved for bulk transfers */ + if (stream->num_bd < CDNS_PCM_PDI_OFFSET) + return -EINVAL; stream->num_bd -= CDNS_PCM_PDI_OFFSET; offset = CDNS_PCM_PDI_OFFSET; diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 60293a00a14e..317873bc0555 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -263,6 +263,9 @@ static void intel_pdi_init(struct sdw_intel *sdw, config->pcm_out = (pcm_cap & SDW_SHIM_PCMSCAP_OSS) >> SDW_REG_SHIFT(SDW_SHIM_PCMSCAP_OSS); + dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n", + config->pcm_bd, config->pcm_in, config->pcm_out); + /* PDM Stream Capability */ pdm_cap = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id)); @@ -272,6 +275,9 @@ static void intel_pdi_init(struct sdw_intel *sdw, SDW_REG_SHIFT(SDW_SHIM_PDMSCAP_ISS); config->pdm_out = (pdm_cap & SDW_SHIM_PDMSCAP_OSS) >> SDW_REG_SHIFT(SDW_SHIM_PDMSCAP_OSS); + + dev_dbg(sdw->cdns.dev, "PDM cap bd:%d in:%d out:%d\n", + config->pdm_bd, config->pdm_in, config->pdm_out); } static int @@ -796,13 +802,14 @@ static int intel_prop_read(struct sdw_bus *bus) sdw_master_read_prop(bus); /* BIOS is not giving some values correctly. So, lets override them */ - bus->prop.num_freq = 1; - bus->prop.freq = devm_kcalloc(bus->dev, bus->prop.num_freq, - sizeof(*bus->prop.freq), GFP_KERNEL); - if (!bus->prop.freq) + bus->prop.num_clk_freq = 1; + bus->prop.clk_freq = devm_kcalloc(bus->dev, bus->prop.num_clk_freq, + sizeof(*bus->prop.clk_freq), + GFP_KERNEL); + if (!bus->prop.clk_freq) return -ENOMEM; - bus->prop.freq[0] = bus->prop.max_freq; + bus->prop.clk_freq[0] = bus->prop.max_clk_freq; bus->prop.err_threshold = 5; return 0; diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h index 71050e5f643d..d923b6262330 100644 --- a/drivers/soundwire/intel.h +++ b/drivers/soundwire/intel.h @@ -5,7 +5,7 @@ #define __SDW_INTEL_LOCAL_H /** - * struct sdw_intel_res - Soundwire link resources + * struct sdw_intel_link_res - Soundwire link resources * @registers: Link IO registers base * @shim: Audio shim pointer * @alh: ALH (Audio Link Hub) pointer diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c index d3d6b54c5791..70637a0383d2 100644 --- a/drivers/soundwire/intel_init.c +++ b/drivers/soundwire/intel_init.c @@ -14,6 +14,7 @@ #include <linux/soundwire/sdw_intel.h> #include "intel.h" +#define SDW_LINK_TYPE 4 /* from Intel ACPI documentation */ #define SDW_MAX_LINKS 4 #define SDW_SHIM_LCAP 0x0 #define SDW_SHIM_BASE 0x2C000 @@ -80,6 +81,7 @@ static struct sdw_intel_ctx /* Check SNDWLCAP.LCOUNT */ caps = ioread32(res->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP); + caps &= GENMASK(2, 0); /* Check HW supported vs property value and use min of two */ count = min_t(u8, caps, count); @@ -89,6 +91,9 @@ static struct sdw_intel_ctx dev_err(&adev->dev, "Link count %d exceeds max %d\n", count, SDW_MAX_LINKS); return NULL; + } else if (!count) { + dev_warn(&adev->dev, "No SoundWire links detected\n"); + return NULL; } dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count); @@ -150,6 +155,12 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, { struct sdw_intel_res *res = cdata; struct acpi_device *adev; + acpi_status status; + u64 adr; + + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) + return AE_OK; /* keep going */ if (acpi_bus_get_device(handle, &adev)) { pr_err("%s: Couldn't find ACPI handle\n", __func__); @@ -157,7 +168,19 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, } res->handle = handle; - return AE_OK; + + /* + * On some Intel platforms, multiple children of the HDAS + * device can be found, but only one of them is the SoundWire + * controller. The SNDW device is always exposed with + * Name(_ADR, 0x40000000), with bits 31..28 representing the + * SoundWire link so filter accordingly + */ + if ((adr & GENMASK(31, 28)) >> 28 != SDW_LINK_TYPE) + return AE_OK; /* keep going */ + + /* device found, stop namespace walk */ + return AE_CTRL_TERMINATE; } /** diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index c1f51d6a23d2..79fee1b21ab6 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -40,7 +40,7 @@ int sdw_master_read_prop(struct sdw_bus *bus) /* Find master handle */ snprintf(name, sizeof(name), - "mipi-sdw-master-%d-subproperties", bus->link_id); + "mipi-sdw-link-%d-subproperties", bus->link_id); link = device_get_named_child_node(bus->dev, name); if (!link) { @@ -50,39 +50,40 @@ int sdw_master_read_prop(struct sdw_bus *bus) if (fwnode_property_read_bool(link, "mipi-sdw-clock-stop-mode0-supported")) - prop->clk_stop_mode = SDW_CLK_STOP_MODE0; + prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0); if (fwnode_property_read_bool(link, "mipi-sdw-clock-stop-mode1-supported")) - prop->clk_stop_mode |= SDW_CLK_STOP_MODE1; + prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1); fwnode_property_read_u32(link, "mipi-sdw-max-clock-frequency", - &prop->max_freq); + &prop->max_clk_freq); nval = fwnode_property_read_u32_array(link, "mipi-sdw-clock-frequencies-supported", NULL, 0); if (nval > 0) { - prop->num_freq = nval; - prop->freq = devm_kcalloc(bus->dev, prop->num_freq, - sizeof(*prop->freq), GFP_KERNEL); - if (!prop->freq) + prop->num_clk_freq = nval; + prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq, + sizeof(*prop->clk_freq), + GFP_KERNEL); + if (!prop->clk_freq) return -ENOMEM; fwnode_property_read_u32_array(link, "mipi-sdw-clock-frequencies-supported", - prop->freq, prop->num_freq); + prop->clk_freq, prop->num_clk_freq); } /* * Check the frequencies supported. If FW doesn't provide max * freq, then populate here by checking values. */ - if (!prop->max_freq && prop->freq) { - prop->max_freq = prop->freq[0]; - for (i = 1; i < prop->num_freq; i++) { - if (prop->freq[i] > prop->max_freq) - prop->max_freq = prop->freq[i]; + if (!prop->max_clk_freq && prop->clk_freq) { + prop->max_clk_freq = prop->clk_freq[0]; + for (i = 1; i < prop->num_clk_freq; i++) { + if (prop->clk_freq[i] > prop->max_clk_freq) + prop->max_clk_freq = prop->clk_freq[i]; } } @@ -149,13 +150,13 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave, dp0->words, dp0->num_words); } - dp0->flow_controlled = fwnode_property_read_bool(port, + dp0->BRA_flow_controlled = fwnode_property_read_bool(port, "mipi-sdw-bra-flow-controlled"); dp0->simple_ch_prep_sm = fwnode_property_read_bool(port, "mipi-sdw-simplified-channel-prepare-sm"); - dp0->device_interrupts = fwnode_property_read_bool(port, + dp0->imp_def_interrupts = fwnode_property_read_bool(port, "mipi-sdw-imp-def-dp0-interrupts-supported"); return 0; @@ -224,7 +225,7 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, fwnode_property_read_u32(node, "mipi-sdw-imp-def-dpn-interrupts-supported", - &dpn[i].device_interrupts); + &dpn[i].imp_def_interrupts); fwnode_property_read_u32(node, "mipi-sdw-min-channel-number", &dpn[i].min_ch); diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 1d5294b8783b..a0476755a459 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -439,7 +439,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, prep_ch.bank = bus->params.next_bank; - if (dpn_prop->device_interrupts || !dpn_prop->simple_ch_prep_sm) + if (dpn_prop->imp_def_interrupts || !dpn_prop->simple_ch_prep_sm) intr = true; /* @@ -449,7 +449,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, */ if (prep && intr) { ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep, - dpn_prop->device_interrupts); + dpn_prop->imp_def_interrupts); if (ret < 0) return ret; } @@ -493,7 +493,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, /* Disable interrupt after Port de-prepare */ if (!prep && intr) ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep, - dpn_prop->device_interrupts); + dpn_prop->imp_def_interrupts); return ret; } @@ -1473,7 +1473,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream) memcpy(¶ms, &bus->params, sizeof(params)); /* TODO: Support Asynchronous mode */ - if ((prop->max_freq % stream->params.rate) != 0) { + if ((prop->max_clk_freq % stream->params.rate) != 0) { dev_err(bus->dev, "Async mode not supported\n"); return -EINVAL; } |