soundwire: debugfs: add interface for BPT/BRA transfers

Add code to show what codec drivers will need to do to enable BPT/BRA
transfers. The only difference is to set the 'command_type' file to
'1'. A zero-value will rely on regular read/write commands in Column0.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Tested-by: shumingf@realtek.com
Link: https://lore.kernel.org/r/20250227140615.8147-16-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by Pierre-Louis Bossart and committed by Vinod Koul bb5cb09e 3394e2b1

+70 -18
+70 -18
drivers/soundwire/debugfs.c
··· 136 } 137 DEFINE_SHOW_ATTRIBUTE(sdw_slave_reg); 138 139 - #define MAX_CMD_BYTES 256 140 141 static int cmd; 142 static u32 start_addr; 143 static size_t num_bytes; 144 static u8 read_buffer[MAX_CMD_BYTES]; ··· 162 } 163 DEFINE_DEBUGFS_ATTRIBUTE(set_command_fops, NULL, 164 set_command, "%llu\n"); 165 166 static int set_start_address(void *data, u64 value) 167 { ··· 217 DEFINE_DEBUGFS_ATTRIBUTE(set_num_bytes_fops, NULL, 218 set_num_bytes, "%llu\n"); 219 220 static int cmd_go(void *data, u64 value) 221 { 222 struct sdw_slave *slave = data; 223 int ret; 224 225 if (value != 1) ··· 255 return ret; 256 } 257 258 - /* Userspace changed the hardware state behind the kernel's back */ 259 - add_taint(TAINT_USER, LOCKDEP_STILL_OK); 260 - 261 - dev_dbg(&slave->dev, "starting command\n"); 262 - 263 if (cmd == 0) { 264 - const struct firmware *fw; 265 - 266 ret = request_firmware(&fw, firmware_file, &slave->dev); 267 if (ret < 0) { 268 dev_err(&slave->dev, "firmware %s not found\n", firmware_file); 269 goto out; 270 } 271 - 272 - if (fw->size != num_bytes) { 273 dev_err(&slave->dev, 274 - "firmware %s: unexpected size %zd, desired %zd\n", 275 firmware_file, fw->size, num_bytes); 276 - release_firmware(fw); 277 goto out; 278 } 279 - 280 - ret = sdw_nwrite_no_pm(slave, start_addr, num_bytes, fw->data); 281 - release_firmware(fw); 282 - } else { 283 - ret = sdw_nread_no_pm(slave, start_addr, num_bytes, read_buffer); 284 } 285 286 - dev_dbg(&slave->dev, "command completed %d\n", ret); 287 288 out: 289 pm_runtime_mark_last_busy(&slave->dev); 290 pm_runtime_put(&slave->dev); 291 292 return ret; 293 } ··· 342 343 /* interface to send arbitrary commands */ 344 debugfs_create_file("command", 0200, d, slave, &set_command_fops); 345 debugfs_create_file("start_address", 0200, d, slave, &set_start_address_fops); 346 debugfs_create_file("num_bytes", 0200, d, slave, &set_num_bytes_fops); 347 debugfs_create_file("go", 0200, d, slave, &cmd_go_fops);
··· 136 } 137 DEFINE_SHOW_ATTRIBUTE(sdw_slave_reg); 138 139 + #define MAX_CMD_BYTES (1024 * 1024) 140 141 static int cmd; 142 + static int cmd_type; 143 static u32 start_addr; 144 static size_t num_bytes; 145 static u8 read_buffer[MAX_CMD_BYTES]; ··· 161 } 162 DEFINE_DEBUGFS_ATTRIBUTE(set_command_fops, NULL, 163 set_command, "%llu\n"); 164 + 165 + static int set_command_type(void *data, u64 value) 166 + { 167 + struct sdw_slave *slave = data; 168 + 169 + if (value > 1) 170 + return -EINVAL; 171 + 172 + /* Userspace changed the hardware state behind the kernel's back */ 173 + add_taint(TAINT_USER, LOCKDEP_STILL_OK); 174 + 175 + dev_dbg(&slave->dev, "command type: %s\n", value ? "BRA" : "Column0"); 176 + 177 + cmd_type = (int)value; 178 + 179 + return 0; 180 + } 181 + DEFINE_DEBUGFS_ATTRIBUTE(set_command_type_fops, NULL, 182 + set_command_type, "%llu\n"); 183 184 static int set_start_address(void *data, u64 value) 185 { ··· 197 DEFINE_DEBUGFS_ATTRIBUTE(set_num_bytes_fops, NULL, 198 set_num_bytes, "%llu\n"); 199 200 + static int do_bpt_sequence(struct sdw_slave *slave, bool write, u8 *buffer) 201 + { 202 + struct sdw_bpt_msg msg = {0}; 203 + 204 + msg.addr = start_addr; 205 + msg.len = num_bytes; 206 + msg.dev_num = slave->dev_num; 207 + if (write) 208 + msg.flags = SDW_MSG_FLAG_WRITE; 209 + else 210 + msg.flags = SDW_MSG_FLAG_READ; 211 + msg.buf = buffer; 212 + 213 + return sdw_bpt_send_sync(slave->bus, slave, &msg); 214 + } 215 + 216 static int cmd_go(void *data, u64 value) 217 { 218 + const struct firmware *fw = NULL; 219 struct sdw_slave *slave = data; 220 + ktime_t start_t; 221 + ktime_t finish_t; 222 int ret; 223 224 if (value != 1) ··· 216 return ret; 217 } 218 219 if (cmd == 0) { 220 ret = request_firmware(&fw, firmware_file, &slave->dev); 221 if (ret < 0) { 222 dev_err(&slave->dev, "firmware %s not found\n", firmware_file); 223 goto out; 224 } 225 + if (fw->size < num_bytes) { 226 dev_err(&slave->dev, 227 + "firmware %s: firmware size %zd, desired %zd\n", 228 firmware_file, fw->size, num_bytes); 229 goto out; 230 } 231 } 232 233 + /* Userspace changed the hardware state behind the kernel's back */ 234 + add_taint(TAINT_USER, LOCKDEP_STILL_OK); 235 + 236 + dev_dbg(&slave->dev, "starting command\n"); 237 + start_t = ktime_get(); 238 + 239 + if (cmd == 0) { 240 + if (cmd_type) 241 + ret = do_bpt_sequence(slave, true, (u8 *)fw->data); 242 + else 243 + ret = sdw_nwrite_no_pm(slave, start_addr, num_bytes, fw->data); 244 + } else { 245 + memset(read_buffer, 0, sizeof(read_buffer)); 246 + 247 + if (cmd_type) 248 + ret = do_bpt_sequence(slave, false, read_buffer); 249 + else 250 + ret = sdw_nread_no_pm(slave, start_addr, num_bytes, read_buffer); 251 + } 252 + 253 + finish_t = ktime_get(); 254 255 out: 256 + if (fw) 257 + release_firmware(fw); 258 + 259 pm_runtime_mark_last_busy(&slave->dev); 260 pm_runtime_put(&slave->dev); 261 + 262 + dev_dbg(&slave->dev, "command completed, num_byte %zu status %d, time %lld ms\n", 263 + num_bytes, ret, div_u64(finish_t - start_t, NSEC_PER_MSEC)); 264 265 return ret; 266 } ··· 291 292 /* interface to send arbitrary commands */ 293 debugfs_create_file("command", 0200, d, slave, &set_command_fops); 294 + debugfs_create_file("command_type", 0200, d, slave, &set_command_type_fops); 295 debugfs_create_file("start_address", 0200, d, slave, &set_start_address_fops); 296 debugfs_create_file("num_bytes", 0200, d, slave, &set_num_bytes_fops); 297 debugfs_create_file("go", 0200, d, slave, &cmd_go_fops);