soundwire: add override addr ops
authorVinod Koul <vkoul@kernel.org>
Tue, 2 Mar 2021 07:51:03 +0000 (15:51 +0800)
committerVinod Koul <vkoul@kernel.org>
Mon, 22 Mar 2021 12:03:10 +0000 (17:33 +0530)
Platform firmware may have incorrect _ADR values causing the driver
probes to fail. Add the override_ops, which when configured will allow
for quirks based on DMI etc to override the addr values.

Co-developed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Link: https://lore.kernel.org/r/20210302075105.11515-2-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/slave.c
include/linux/soundwire/sdw.h

index 180f38b..112b219 100644 (file)
@@ -95,7 +95,7 @@ static bool find_slave(struct sdw_bus *bus,
                       struct acpi_device *adev,
                       struct sdw_slave_id *id)
 {
-       unsigned long long addr;
+       u64 addr;
        unsigned int link_id;
        acpi_status status;
 
@@ -108,6 +108,12 @@ static bool find_slave(struct sdw_bus *bus,
                return false;
        }
 
+       if (bus->ops->override_adr)
+               addr = bus->ops->override_adr(bus, addr);
+
+       if (!addr)
+               return false;
+
        /* Extract link id from ADR, Bit 51 to 48 (included) */
        link_id = SDW_DISCO_LINK_ID(addr);
 
index d08039d..f0a3895 100644 (file)
@@ -804,6 +804,7 @@ struct sdw_defer {
 /**
  * struct sdw_master_ops - Master driver ops
  * @read_prop: Read Master properties
+ * @override_adr: Override value read from firmware (quirk for buggy firmware)
  * @xfer_msg: Transfer message callback
  * @xfer_msg_defer: Defer version of transfer message callback
  * @reset_page_addr: Reset the SCP page address registers
@@ -813,7 +814,8 @@ struct sdw_defer {
  */
 struct sdw_master_ops {
        int (*read_prop)(struct sdw_bus *bus);
-
+       u64 (*override_adr)
+                       (struct sdw_bus *bus, u64 addr);
        enum sdw_command_response (*xfer_msg)
                        (struct sdw_bus *bus, struct sdw_msg *msg);
        enum sdw_command_response (*xfer_msg_defer)