]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Soundwire: add sdw_slave_get_scale_index helper
authorBard Liao <yung-chuan.liao@linux.intel.com>
Wed, 18 Dec 2024 08:01:47 +0000 (16:01 +0800)
committerVinod Koul <vkoul@kernel.org>
Mon, 23 Dec 2024 06:30:33 +0000 (12:00 +0530)
Currently, we only set peripheral frequency when the peripheral is
initialized. However, curr_dr_freq may change to get required bandwidth.
For example, curr_dr_freq may increase from 4.8MHz to 9.6MHz when the
4th stream is opened. Add a helper to get the scale index so that we can
get the scale index and program it.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20241218080155.102405-7-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/bus.c
include/linux/soundwire/sdw.h

index d1dc62c34f1cf319ffe7d038e6744b2963da1b4a..215630d602adf9c1a8cd6c1651a558e14abb0d62 100644 (file)
@@ -1276,23 +1276,12 @@ int sdw_configure_dpn_intr(struct sdw_slave *slave,
        return ret;
 }
 
-static int sdw_slave_set_frequency(struct sdw_slave *slave)
+int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base)
 {
        u32 mclk_freq = slave->bus->prop.mclk_freq;
        u32 curr_freq = slave->bus->params.curr_dr_freq >> 1;
        unsigned int scale;
        u8 scale_index;
-       u8 base;
-       int ret;
-
-       /*
-        * frequency base and scale registers are required for SDCA
-        * devices. They may also be used for 1.2+/non-SDCA devices.
-        * Driver can set the property, we will need a DisCo property
-        * to discover this case from platform firmware.
-        */
-       if (!slave->id.class_id && !slave->prop.clock_reg_supported)
-               return 0;
 
        if (!mclk_freq) {
                dev_err(&slave->dev,
@@ -1311,19 +1300,19 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
         */
        if (!(19200000 % mclk_freq)) {
                mclk_freq = 19200000;
-               base = SDW_SCP_BASE_CLOCK_19200000_HZ;
+               *base = SDW_SCP_BASE_CLOCK_19200000_HZ;
        } else if (!(22579200 % mclk_freq)) {
                mclk_freq = 22579200;
-               base = SDW_SCP_BASE_CLOCK_22579200_HZ;
+               *base = SDW_SCP_BASE_CLOCK_22579200_HZ;
        } else if (!(24576000 % mclk_freq)) {
                mclk_freq = 24576000;
-               base = SDW_SCP_BASE_CLOCK_24576000_HZ;
+               *base = SDW_SCP_BASE_CLOCK_24576000_HZ;
        } else if (!(32000000 % mclk_freq)) {
                mclk_freq = 32000000;
-               base = SDW_SCP_BASE_CLOCK_32000000_HZ;
+               *base = SDW_SCP_BASE_CLOCK_32000000_HZ;
        } else if (!(96000000 % mclk_freq)) {
                mclk_freq = 24000000;
-               base = SDW_SCP_BASE_CLOCK_24000000_HZ;
+               *base = SDW_SCP_BASE_CLOCK_24000000_HZ;
        } else {
                dev_err(&slave->dev,
                        "Unsupported clock base, mclk %d\n",
@@ -1354,6 +1343,34 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
        }
        scale_index++;
 
+       dev_dbg(&slave->dev,
+               "Configured bus base %d, scale %d, mclk %d, curr_freq %d\n",
+               *base, scale_index, mclk_freq, curr_freq);
+
+       return scale_index;
+}
+EXPORT_SYMBOL(sdw_slave_get_scale_index);
+
+static int sdw_slave_set_frequency(struct sdw_slave *slave)
+{
+       int scale_index;
+       u8 base;
+       int ret;
+
+       /*
+        * frequency base and scale registers are required for SDCA
+        * devices. They may also be used for 1.2+/non-SDCA devices.
+        * Driver can set the property directly, for now there's no
+        * DisCo property to discover support for the scaling registers
+        * from platform firmware.
+        */
+       if (!slave->id.class_id && !slave->prop.clock_reg_supported)
+               return 0;
+
+       scale_index = sdw_slave_get_scale_index(slave, &base);
+       if (scale_index < 0)
+               return scale_index;
+
        ret = sdw_write_no_pm(slave, SDW_SCP_BUS_CLOCK_BASE, base);
        if (ret < 0) {
                dev_err(&slave->dev,
@@ -1373,10 +1390,6 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)
                dev_err(&slave->dev,
                        "SDW_SCP_BUSCLOCK_SCALE_B1 write failed:%d\n", ret);
 
-       dev_dbg(&slave->dev,
-               "Configured bus base %d, scale %d, mclk %d, curr_freq %d\n",
-               base, scale_index, mclk_freq, curr_freq);
-
        return ret;
 }
 
index ae38ac848d383cb9da22adda727acc0b3bc43a49..05a85e2bd96d092cbb93f5ae9ce38d6b3ff89d1b 100644 (file)
@@ -1052,6 +1052,8 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
 int sdw_stream_remove_slave(struct sdw_slave *slave,
                            struct sdw_stream_runtime *stream);
 
+int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base);
+
 /* messaging and data APIs */
 int sdw_read(struct sdw_slave *slave, u32 addr);
 int sdw_write(struct sdw_slave *slave, u32 addr, u8 value);