forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/soundwire/cadence_master.c
....@@ -8,15 +8,23 @@
88
99 #include <linux/delay.h>
1010 #include <linux/device.h>
11
+#include <linux/debugfs.h>
1112 #include <linux/interrupt.h>
13
+#include <linux/io.h>
1214 #include <linux/module.h>
1315 #include <linux/mod_devicetable.h>
16
+#include <linux/pm_runtime.h>
1417 #include <linux/soundwire/sdw_registers.h>
1518 #include <linux/soundwire/sdw.h>
1619 #include <sound/pcm_params.h>
1720 #include <sound/soc.h>
21
+#include <linux/workqueue.h>
1822 #include "bus.h"
1923 #include "cadence_master.h"
24
+
25
+static int interrupt_mask;
26
+module_param_named(cnds_mcp_int_mask, interrupt_mask, int, 0444);
27
+MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");
2028
2129 #define CDNS_MCP_CONFIG 0x0
2230
....@@ -42,11 +50,15 @@
4250 #define CDNS_MCP_CONTROL_CMD_ACCEPT BIT(1)
4351 #define CDNS_MCP_CONTROL_BLOCK_WAKEUP BIT(0)
4452
45
-
4653 #define CDNS_MCP_CMDCTRL 0x8
54
+
55
+#define CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR BIT(2)
56
+
4757 #define CDNS_MCP_SSPSTAT 0xC
4858 #define CDNS_MCP_FRAME_SHAPE 0x10
4959 #define CDNS_MCP_FRAME_SHAPE_INIT 0x14
60
+#define CDNS_MCP_FRAME_SHAPE_COL_MASK GENMASK(2, 0)
61
+#define CDNS_MCP_FRAME_SHAPE_ROW_MASK GENMASK(7, 3)
5062
5163 #define CDNS_MCP_CONFIG_UPDATE 0x18
5264 #define CDNS_MCP_CONFIG_UPDATE_BIT BIT(0)
....@@ -56,6 +68,7 @@
5668 #define CDNS_MCP_SSP_CTRL1 0x28
5769 #define CDNS_MCP_CLK_CTRL0 0x30
5870 #define CDNS_MCP_CLK_CTRL1 0x38
71
+#define CDNS_MCP_CLK_MCLKD_MASK GENMASK(7, 0)
5972
6073 #define CDNS_MCP_STAT 0x40
6174
....@@ -66,6 +79,7 @@
6679 #define CDNS_MCP_INTMASK 0x48
6780
6881 #define CDNS_MCP_INT_IRQ BIT(31)
82
+#define CDNS_MCP_INT_RESERVED1 GENMASK(30, 17)
6983 #define CDNS_MCP_INT_WAKEUP BIT(16)
7084 #define CDNS_MCP_INT_SLAVE_RSVD BIT(15)
7185 #define CDNS_MCP_INT_SLAVE_ALERT BIT(14)
....@@ -75,9 +89,14 @@
7589 #define CDNS_MCP_INT_DPINT BIT(11)
7690 #define CDNS_MCP_INT_CTRL_CLASH BIT(10)
7791 #define CDNS_MCP_INT_DATA_CLASH BIT(9)
92
+#define CDNS_MCP_INT_PARITY BIT(8)
7893 #define CDNS_MCP_INT_CMD_ERR BIT(7)
94
+#define CDNS_MCP_INT_RESERVED2 GENMASK(6, 4)
95
+#define CDNS_MCP_INT_RX_NE BIT(3)
7996 #define CDNS_MCP_INT_RX_WL BIT(2)
8097 #define CDNS_MCP_INT_TXE BIT(1)
98
+#define CDNS_MCP_INT_TXF BIT(0)
99
+#define CDNS_MCP_INT_RESERVED (CDNS_MCP_INT_RESERVED1 | CDNS_MCP_INT_RESERVED2)
81100
82101 #define CDNS_MCP_INTSET 0x4C
83102
....@@ -114,8 +133,7 @@
114133 #define CDNS_MCP_CMD_SSP_TAG BIT(31)
115134 #define CDNS_MCP_CMD_COMMAND GENMASK(30, 28)
116135 #define CDNS_MCP_CMD_DEV_ADDR GENMASK(27, 24)
117
-#define CDNS_MCP_CMD_REG_ADDR_H GENMASK(23, 16)
118
-#define CDNS_MCP_CMD_REG_ADDR_L GENMASK(15, 8)
136
+#define CDNS_MCP_CMD_REG_ADDR GENMASK(23, 8)
119137 #define CDNS_MCP_CMD_REG_DATA GENMASK(7, 0)
120138
121139 #define CDNS_MCP_CMD_READ 2
....@@ -157,6 +175,7 @@
157175 #define CDNS_DPN_HCTRL_LCTRL GENMASK(10, 8)
158176
159177 #define CDNS_PORTCTRL 0x130
178
+#define CDNS_PORTCTRL_TEST_FAILED BIT(1)
160179 #define CDNS_PORTCTRL_DIRN BIT(7)
161180 #define CDNS_PORTCTRL_BANK_INVERT BIT(8)
162181
....@@ -169,14 +188,7 @@
169188 #define CDNS_PDI_CONFIG_PORT GENMASK(4, 0)
170189
171190 /* Driver defaults */
172
-
173
-#define CDNS_DEFAULT_CLK_DIVIDER 0
174
-#define CDNS_DEFAULT_FRAME_SHAPE 0x30
175
-#define CDNS_DEFAULT_SSP_INTERVAL 0x18
176191 #define CDNS_TX_TIMEOUT 2000
177
-
178
-#define CDNS_PCM_PDI_OFFSET 0x2
179
-#define CDNS_PDM_PDI_OFFSET 0x6
180192
181193 #define CDNS_SCP_RX_FIFOLEVEL 0x2
182194
....@@ -203,32 +215,266 @@
203215 cdns_writel(cdns, offset, tmp);
204216 }
205217
206
-static int cdns_clear_bit(struct sdw_cdns *cdns, int offset, u32 value)
218
+static int cdns_set_wait(struct sdw_cdns *cdns, int offset, u32 mask, u32 value)
207219 {
208220 int timeout = 10;
209221 u32 reg_read;
210222
211
- writel(value, cdns->registers + offset);
212
-
213
- /* Wait for bit to be self cleared */
223
+ /* Wait for bit to be set */
214224 do {
215225 reg_read = readl(cdns->registers + offset);
216
- if ((reg_read & value) == 0)
226
+ if ((reg_read & mask) == value)
217227 return 0;
218228
219229 timeout--;
220
- udelay(50);
230
+ usleep_range(50, 100);
221231 } while (timeout != 0);
222232
223
- return -EAGAIN;
233
+ return -ETIMEDOUT;
224234 }
235
+
236
+static int cdns_clear_bit(struct sdw_cdns *cdns, int offset, u32 value)
237
+{
238
+ writel(value, cdns->registers + offset);
239
+
240
+ /* Wait for bit to be self cleared */
241
+ return cdns_set_wait(cdns, offset, value, 0);
242
+}
243
+
244
+/*
245
+ * all changes to the MCP_CONFIG, MCP_CONTROL, MCP_CMDCTRL and MCP_PHYCTRL
246
+ * need to be confirmed with a write to MCP_CONFIG_UPDATE
247
+ */
248
+static int cdns_config_update(struct sdw_cdns *cdns)
249
+{
250
+ int ret;
251
+
252
+ if (sdw_cdns_is_clock_stop(cdns)) {
253
+ dev_err(cdns->dev, "Cannot program MCP_CONFIG_UPDATE in ClockStopMode\n");
254
+ return -EINVAL;
255
+ }
256
+
257
+ ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
258
+ CDNS_MCP_CONFIG_UPDATE_BIT);
259
+ if (ret < 0)
260
+ dev_err(cdns->dev, "Config update timedout\n");
261
+
262
+ return ret;
263
+}
264
+
265
+/*
266
+ * debugfs
267
+ */
268
+#ifdef CONFIG_DEBUG_FS
269
+
270
+#define RD_BUF (2 * PAGE_SIZE)
271
+
272
+static ssize_t cdns_sprintf(struct sdw_cdns *cdns,
273
+ char *buf, size_t pos, unsigned int reg)
274
+{
275
+ return scnprintf(buf + pos, RD_BUF - pos,
276
+ "%4x\t%8x\n", reg, cdns_readl(cdns, reg));
277
+}
278
+
279
+static int cdns_reg_show(struct seq_file *s, void *data)
280
+{
281
+ struct sdw_cdns *cdns = s->private;
282
+ char *buf;
283
+ ssize_t ret;
284
+ int num_ports;
285
+ int i, j;
286
+
287
+ buf = kzalloc(RD_BUF, GFP_KERNEL);
288
+ if (!buf)
289
+ return -ENOMEM;
290
+
291
+ ret = scnprintf(buf, RD_BUF, "Register Value\n");
292
+ ret += scnprintf(buf + ret, RD_BUF - ret, "\nMCP Registers\n");
293
+ /* 8 MCP registers */
294
+ for (i = CDNS_MCP_CONFIG; i <= CDNS_MCP_PHYCTRL; i += sizeof(u32))
295
+ ret += cdns_sprintf(cdns, buf, ret, i);
296
+
297
+ ret += scnprintf(buf + ret, RD_BUF - ret,
298
+ "\nStatus & Intr Registers\n");
299
+ /* 13 Status & Intr registers (offsets 0x70 and 0x74 not defined) */
300
+ for (i = CDNS_MCP_STAT; i <= CDNS_MCP_FIFOSTAT; i += sizeof(u32))
301
+ ret += cdns_sprintf(cdns, buf, ret, i);
302
+
303
+ ret += scnprintf(buf + ret, RD_BUF - ret,
304
+ "\nSSP & Clk ctrl Registers\n");
305
+ ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL0);
306
+ ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL1);
307
+ ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL0);
308
+ ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL1);
309
+
310
+ ret += scnprintf(buf + ret, RD_BUF - ret,
311
+ "\nDPn B0 Registers\n");
312
+
313
+ num_ports = cdns->num_ports;
314
+
315
+ for (i = 0; i < num_ports; i++) {
316
+ ret += scnprintf(buf + ret, RD_BUF - ret,
317
+ "\nDP-%d\n", i);
318
+ for (j = CDNS_DPN_B0_CONFIG(i);
319
+ j < CDNS_DPN_B0_ASYNC_CTRL(i); j += sizeof(u32))
320
+ ret += cdns_sprintf(cdns, buf, ret, j);
321
+ }
322
+
323
+ ret += scnprintf(buf + ret, RD_BUF - ret,
324
+ "\nDPn B1 Registers\n");
325
+ for (i = 0; i < num_ports; i++) {
326
+ ret += scnprintf(buf + ret, RD_BUF - ret,
327
+ "\nDP-%d\n", i);
328
+
329
+ for (j = CDNS_DPN_B1_CONFIG(i);
330
+ j < CDNS_DPN_B1_ASYNC_CTRL(i); j += sizeof(u32))
331
+ ret += cdns_sprintf(cdns, buf, ret, j);
332
+ }
333
+
334
+ ret += scnprintf(buf + ret, RD_BUF - ret,
335
+ "\nDPn Control Registers\n");
336
+ for (i = 0; i < num_ports; i++)
337
+ ret += cdns_sprintf(cdns, buf, ret,
338
+ CDNS_PORTCTRL + i * CDNS_PORT_OFFSET);
339
+
340
+ ret += scnprintf(buf + ret, RD_BUF - ret,
341
+ "\nPDIn Config Registers\n");
342
+
343
+ /* number of PDI and ports is interchangeable */
344
+ for (i = 0; i < num_ports; i++)
345
+ ret += cdns_sprintf(cdns, buf, ret, CDNS_PDI_CONFIG(i));
346
+
347
+ seq_printf(s, "%s", buf);
348
+ kfree(buf);
349
+
350
+ return 0;
351
+}
352
+DEFINE_SHOW_ATTRIBUTE(cdns_reg);
353
+
354
+static int cdns_hw_reset(void *data, u64 value)
355
+{
356
+ struct sdw_cdns *cdns = data;
357
+ int ret;
358
+
359
+ if (value != 1)
360
+ return -EINVAL;
361
+
362
+ /* Userspace changed the hardware state behind the kernel's back */
363
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
364
+
365
+ ret = sdw_cdns_exit_reset(cdns);
366
+
367
+ dev_dbg(cdns->dev, "link hw_reset done: %d\n", ret);
368
+
369
+ return ret;
370
+}
371
+
372
+DEFINE_DEBUGFS_ATTRIBUTE(cdns_hw_reset_fops, NULL, cdns_hw_reset, "%llu\n");
373
+
374
+static int cdns_parity_error_injection(void *data, u64 value)
375
+{
376
+ struct sdw_cdns *cdns = data;
377
+ struct sdw_bus *bus;
378
+ int ret;
379
+
380
+ if (value != 1)
381
+ return -EINVAL;
382
+
383
+ bus = &cdns->bus;
384
+
385
+ /*
386
+ * Resume Master device. If this results in a bus reset, the
387
+ * Slave devices will re-attach and be re-enumerated.
388
+ */
389
+ ret = pm_runtime_get_sync(bus->dev);
390
+ if (ret < 0 && ret != -EACCES) {
391
+ dev_err_ratelimited(cdns->dev,
392
+ "pm_runtime_get_sync failed in %s, ret %d\n",
393
+ __func__, ret);
394
+ pm_runtime_put_noidle(bus->dev);
395
+ return ret;
396
+ }
397
+
398
+ /*
399
+ * wait long enough for Slave(s) to be in steady state. This
400
+ * does not need to be super precise.
401
+ */
402
+ msleep(200);
403
+
404
+ /*
405
+ * Take the bus lock here to make sure that any bus transactions
406
+ * will be queued while we inject a parity error on a dummy read
407
+ */
408
+ mutex_lock(&bus->bus_lock);
409
+
410
+ /* program hardware to inject parity error */
411
+ cdns_updatel(cdns, CDNS_MCP_CMDCTRL,
412
+ CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR,
413
+ CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR);
414
+
415
+ /* commit changes */
416
+ cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
417
+ CDNS_MCP_CONFIG_UPDATE_BIT,
418
+ CDNS_MCP_CONFIG_UPDATE_BIT);
419
+
420
+ /* do a broadcast dummy read to avoid bus clashes */
421
+ ret = sdw_bread_no_pm_unlocked(&cdns->bus, 0xf, SDW_SCP_DEVID_0);
422
+ dev_info(cdns->dev, "parity error injection, read: %d\n", ret);
423
+
424
+ /* program hardware to disable parity error */
425
+ cdns_updatel(cdns, CDNS_MCP_CMDCTRL,
426
+ CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR,
427
+ 0);
428
+
429
+ /* commit changes */
430
+ cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
431
+ CDNS_MCP_CONFIG_UPDATE_BIT,
432
+ CDNS_MCP_CONFIG_UPDATE_BIT);
433
+
434
+ /* Continue bus operation with parity error injection disabled */
435
+ mutex_unlock(&bus->bus_lock);
436
+
437
+ /* Userspace changed the hardware state behind the kernel's back */
438
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
439
+
440
+ /*
441
+ * allow Master device to enter pm_runtime suspend. This may
442
+ * also result in Slave devices suspending.
443
+ */
444
+ pm_runtime_mark_last_busy(bus->dev);
445
+ pm_runtime_put_autosuspend(bus->dev);
446
+
447
+ return 0;
448
+}
449
+
450
+DEFINE_DEBUGFS_ATTRIBUTE(cdns_parity_error_fops, NULL,
451
+ cdns_parity_error_injection, "%llu\n");
452
+
453
+/**
454
+ * sdw_cdns_debugfs_init() - Cadence debugfs init
455
+ * @cdns: Cadence instance
456
+ * @root: debugfs root
457
+ */
458
+void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
459
+{
460
+ debugfs_create_file("cdns-registers", 0400, root, cdns, &cdns_reg_fops);
461
+
462
+ debugfs_create_file("cdns-hw-reset", 0200, root, cdns,
463
+ &cdns_hw_reset_fops);
464
+
465
+ debugfs_create_file("cdns-parity-error-injection", 0200, root, cdns,
466
+ &cdns_parity_error_fops);
467
+}
468
+EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
469
+
470
+#endif /* CONFIG_DEBUG_FS */
225471
226472 /*
227473 * IO Calls
228474 */
229
-static enum sdw_command_response cdns_fill_msg_resp(
230
- struct sdw_cdns *cdns,
231
- struct sdw_msg *msg, int count, int offset)
475
+static enum sdw_command_response
476
+cdns_fill_msg_resp(struct sdw_cdns *cdns,
477
+ struct sdw_msg *msg, int count, int offset)
232478 {
233479 int nack = 0, no_ack = 0;
234480 int i;
....@@ -237,33 +483,37 @@
237483 for (i = 0; i < count; i++) {
238484 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) {
239485 no_ack = 1;
240
- dev_dbg(cdns->dev, "Msg Ack not received\n");
241
- if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
242
- nack = 1;
243
- dev_err(cdns->dev, "Msg NACK received\n");
244
- }
486
+ dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n");
487
+ }
488
+ if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
489
+ nack = 1;
490
+ dev_err_ratelimited(cdns->dev, "Msg NACK received\n");
245491 }
246492 }
247493
248494 if (nack) {
249
- dev_err(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num);
495
+ dev_err_ratelimited(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num);
250496 return SDW_CMD_FAIL;
251
- } else if (no_ack) {
252
- dev_dbg(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num);
497
+ }
498
+
499
+ if (no_ack) {
500
+ dev_dbg_ratelimited(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num);
253501 return SDW_CMD_IGNORED;
254502 }
255503
256
- /* fill response */
257
- for (i = 0; i < count; i++)
258
- msg->buf[i + offset] = cdns->response_buf[i] >>
259
- SDW_REG_SHIFT(CDNS_MCP_RESP_RDATA);
504
+ if (msg->flags == SDW_MSG_FLAG_READ) {
505
+ /* fill response */
506
+ for (i = 0; i < count; i++)
507
+ msg->buf[i + offset] = FIELD_GET(CDNS_MCP_RESP_RDATA,
508
+ cdns->response_buf[i]);
509
+ }
260510
261511 return SDW_CMD_OK;
262512 }
263513
264514 static enum sdw_command_response
265515 _cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd,
266
- int offset, int count, bool defer)
516
+ int offset, int count, bool defer)
267517 {
268518 unsigned long time;
269519 u32 base, i, data;
....@@ -279,14 +529,15 @@
279529 addr = msg->addr;
280530
281531 for (i = 0; i < count; i++) {
282
- data = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR);
283
- data |= cmd << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND);
284
- data |= addr++ << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
532
+ data = FIELD_PREP(CDNS_MCP_CMD_DEV_ADDR, msg->dev_num);
533
+ data |= FIELD_PREP(CDNS_MCP_CMD_COMMAND, cmd);
534
+ data |= FIELD_PREP(CDNS_MCP_CMD_REG_ADDR, addr);
535
+ addr++;
285536
286537 if (msg->flags == SDW_MSG_FLAG_WRITE)
287538 data |= msg->buf[i + offset];
288539
289
- data |= msg->ssp_sync << SDW_REG_SHIFT(CDNS_MCP_CMD_SSP_TAG);
540
+ data |= FIELD_PREP(CDNS_MCP_CMD_SSP_TAG, msg->ssp_sync);
290541 cdns_writel(cdns, base, data);
291542 base += CDNS_MCP_CMD_WORD_LEN;
292543 }
....@@ -296,9 +547,10 @@
296547
297548 /* wait for timeout or response */
298549 time = wait_for_completion_timeout(&cdns->tx_complete,
299
- msecs_to_jiffies(CDNS_TX_TIMEOUT));
550
+ msecs_to_jiffies(CDNS_TX_TIMEOUT));
300551 if (!time) {
301
- dev_err(cdns->dev, "IO transfer timed out\n");
552
+ dev_err(cdns->dev, "IO transfer timed out, cmd %d device %d addr %x len %d\n",
553
+ cmd, msg->dev_num, msg->addr, msg->len);
302554 msg->len = 0;
303555 return SDW_CMD_TIMEOUT;
304556 }
....@@ -306,8 +558,8 @@
306558 return cdns_fill_msg_resp(cdns, msg, count, offset);
307559 }
308560
309
-static enum sdw_command_response cdns_program_scp_addr(
310
- struct sdw_cdns *cdns, struct sdw_msg *msg)
561
+static enum sdw_command_response
562
+cdns_program_scp_addr(struct sdw_cdns *cdns, struct sdw_msg *msg)
311563 {
312564 int nack = 0, no_ack = 0;
313565 unsigned long time;
....@@ -320,12 +572,12 @@
320572 cdns->msg_count = CDNS_SCP_RX_FIFOLEVEL;
321573 }
322574
323
- data[0] = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR);
324
- data[0] |= 0x3 << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND);
575
+ data[0] = FIELD_PREP(CDNS_MCP_CMD_DEV_ADDR, msg->dev_num);
576
+ data[0] |= FIELD_PREP(CDNS_MCP_CMD_COMMAND, 0x3);
325577 data[1] = data[0];
326578
327
- data[0] |= SDW_SCP_ADDRPAGE1 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
328
- data[1] |= SDW_SCP_ADDRPAGE2 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
579
+ data[0] |= FIELD_PREP(CDNS_MCP_CMD_REG_ADDR, SDW_SCP_ADDRPAGE1);
580
+ data[1] |= FIELD_PREP(CDNS_MCP_CMD_REG_ADDR, SDW_SCP_ADDRPAGE2);
329581
330582 data[0] |= msg->addr_page1;
331583 data[1] |= msg->addr_page2;
....@@ -336,7 +588,7 @@
336588 cdns_writel(cdns, base, data[1]);
337589
338590 time = wait_for_completion_timeout(&cdns->tx_complete,
339
- msecs_to_jiffies(CDNS_TX_TIMEOUT));
591
+ msecs_to_jiffies(CDNS_TX_TIMEOUT));
340592 if (!time) {
341593 dev_err(cdns->dev, "SCP Msg trf timed out\n");
342594 msg->len = 0;
....@@ -347,22 +599,24 @@
347599 for (i = 0; i < 2; i++) {
348600 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) {
349601 no_ack = 1;
350
- dev_err(cdns->dev, "Program SCP Ack not received");
602
+ dev_err(cdns->dev, "Program SCP Ack not received\n");
351603 if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
352604 nack = 1;
353
- dev_err(cdns->dev, "Program SCP NACK received");
605
+ dev_err(cdns->dev, "Program SCP NACK received\n");
354606 }
355607 }
356608 }
357609
358610 /* For NACK, NO ack, don't return err if we are in Broadcast mode */
359611 if (nack) {
360
- dev_err(cdns->dev,
361
- "SCP_addrpage NACKed for Slave %d", msg->dev_num);
612
+ dev_err_ratelimited(cdns->dev,
613
+ "SCP_addrpage NACKed for Slave %d\n", msg->dev_num);
362614 return SDW_CMD_FAIL;
363
- } else if (no_ack) {
364
- dev_dbg(cdns->dev,
365
- "SCP_addrpage ignored for Slave %d", msg->dev_num);
615
+ }
616
+
617
+ if (no_ack) {
618
+ dev_dbg_ratelimited(cdns->dev,
619
+ "SCP_addrpage ignored for Slave %d\n", msg->dev_num);
366620 return SDW_CMD_IGNORED;
367621 }
368622
....@@ -410,7 +664,7 @@
410664
411665 for (i = 0; i < msg->len / CDNS_MCP_CMD_LEN; i++) {
412666 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN,
413
- CDNS_MCP_CMD_LEN, false);
667
+ CDNS_MCP_CMD_LEN, false);
414668 if (ret < 0)
415669 goto exit;
416670 }
....@@ -419,7 +673,7 @@
419673 goto exit;
420674
421675 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN,
422
- msg->len % CDNS_MCP_CMD_LEN, false);
676
+ msg->len % CDNS_MCP_CMD_LEN, false);
423677
424678 exit:
425679 return ret;
....@@ -428,7 +682,7 @@
428682
429683 enum sdw_command_response
430684 cdns_xfer_msg_defer(struct sdw_bus *bus,
431
- struct sdw_msg *msg, struct sdw_defer *defer)
685
+ struct sdw_msg *msg, struct sdw_defer *defer)
432686 {
433687 struct sdw_cdns *cdns = bus_to_cdns(bus);
434688 int cmd = 0, ret;
....@@ -483,11 +737,12 @@
483737 }
484738
485739 static int cdns_update_slave_status(struct sdw_cdns *cdns,
486
- u32 slave0, u32 slave1)
740
+ u32 slave0, u32 slave1)
487741 {
488742 enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
489743 bool is_slave = false;
490
- u64 slave, mask;
744
+ u64 slave;
745
+ u32 mask;
491746 int i, set_status;
492747
493748 /* combine the two status */
....@@ -525,13 +780,36 @@
525780
526781 /* first check if Slave reported multiple status */
527782 if (set_status > 1) {
528
- dev_warn(cdns->dev,
529
- "Slave reported multiple Status: %d\n",
530
- status[i]);
531
- /*
532
- * TODO: we need to reread the status here by
533
- * issuing a PING cmd
534
- */
783
+ u32 val;
784
+
785
+ dev_warn_ratelimited(cdns->dev,
786
+ "Slave %d reported multiple Status: %d\n",
787
+ i, mask);
788
+
789
+ /* check latest status extracted from PING commands */
790
+ val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
791
+ val >>= (i * 2);
792
+
793
+ switch (val & 0x3) {
794
+ case 0:
795
+ status[i] = SDW_SLAVE_UNATTACHED;
796
+ break;
797
+ case 1:
798
+ status[i] = SDW_SLAVE_ATTACHED;
799
+ break;
800
+ case 2:
801
+ status[i] = SDW_SLAVE_ALERT;
802
+ break;
803
+ case 3:
804
+ default:
805
+ status[i] = SDW_SLAVE_RESERVED;
806
+ break;
807
+ }
808
+
809
+ dev_warn_ratelimited(cdns->dev,
810
+ "Slave %d status updated to %d\n",
811
+ i, status[i]);
812
+
535813 }
536814 }
537815
....@@ -558,6 +836,10 @@
558836
559837 int_status = cdns_readl(cdns, CDNS_MCP_INTSTAT);
560838
839
+ /* check for reserved values read as zero */
840
+ if (int_status & CDNS_MCP_INT_RESERVED)
841
+ return IRQ_NONE;
842
+
561843 if (!(int_status & CDNS_MCP_INT_IRQ))
562844 return IRQ_NONE;
563845
....@@ -566,18 +848,22 @@
566848
567849 if (cdns->defer) {
568850 cdns_fill_msg_resp(cdns, cdns->defer->msg,
569
- cdns->defer->length, 0);
851
+ cdns->defer->length, 0);
570852 complete(&cdns->defer->complete);
571853 cdns->defer = NULL;
572
- } else
854
+ } else {
573855 complete(&cdns->tx_complete);
856
+ }
857
+ }
858
+
859
+ if (int_status & CDNS_MCP_INT_PARITY) {
860
+ /* Parity error detected by Master */
861
+ dev_err_ratelimited(cdns->dev, "Parity error\n");
574862 }
575863
576864 if (int_status & CDNS_MCP_INT_CTRL_CLASH) {
577
-
578865 /* Slave is driving bit slot during control word */
579866 dev_err_ratelimited(cdns->dev, "Bus clash for control word\n");
580
- int_status |= CDNS_MCP_INT_CTRL_CLASH;
581867 }
582868
583869 if (int_status & CDNS_MCP_INT_DATA_CLASH) {
....@@ -586,16 +872,37 @@
586872 * ownership of data bits or Slave gone bonkers
587873 */
588874 dev_err_ratelimited(cdns->dev, "Bus clash for data word\n");
589
- int_status |= CDNS_MCP_INT_DATA_CLASH;
875
+ }
876
+
877
+ if (cdns->bus.params.m_data_mode != SDW_PORT_DATA_MODE_NORMAL &&
878
+ int_status & CDNS_MCP_INT_DPINT) {
879
+ u32 port_intstat;
880
+
881
+ /* just log which ports report an error */
882
+ port_intstat = cdns_readl(cdns, CDNS_MCP_PORT_INTSTAT);
883
+ dev_err_ratelimited(cdns->dev, "DP interrupt: PortIntStat %8x\n",
884
+ port_intstat);
885
+
886
+ /* clear status w/ write1 */
887
+ cdns_writel(cdns, CDNS_MCP_PORT_INTSTAT, port_intstat);
590888 }
591889
592890 if (int_status & CDNS_MCP_INT_SLAVE_MASK) {
593891 /* Mask the Slave interrupt and wake thread */
594892 cdns_updatel(cdns, CDNS_MCP_INTMASK,
595
- CDNS_MCP_INT_SLAVE_MASK, 0);
893
+ CDNS_MCP_INT_SLAVE_MASK, 0);
596894
597895 int_status &= ~CDNS_MCP_INT_SLAVE_MASK;
598
- ret = IRQ_WAKE_THREAD;
896
+
897
+ /*
898
+ * Deal with possible race condition between interrupt
899
+ * handling and disabling interrupts on suspend.
900
+ *
901
+ * If the master is in the process of disabling
902
+ * interrupts, don't schedule a workqueue
903
+ */
904
+ if (cdns->interrupt_enabled)
905
+ schedule_work(&cdns->work);
599906 }
600907
601908 cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);
....@@ -604,16 +911,18 @@
604911 EXPORT_SYMBOL(sdw_cdns_irq);
605912
606913 /**
607
- * sdw_cdns_thread() - Cadence irq thread handler
608
- * @irq: irq number
609
- * @dev_id: irq context
914
+ * To update slave status in a work since we will need to handle
915
+ * other interrupts eg. CDNS_MCP_INT_RX_WL during the update slave
916
+ * process.
917
+ * @work: cdns worker thread
610918 */
611
-irqreturn_t sdw_cdns_thread(int irq, void *dev_id)
919
+static void cdns_update_slave_status_work(struct work_struct *work)
612920 {
613
- struct sdw_cdns *cdns = dev_id;
921
+ struct sdw_cdns *cdns =
922
+ container_of(work, struct sdw_cdns, work);
614923 u32 slave0, slave1;
615924
616
- dev_dbg(cdns->dev, "Slave status change\n");
925
+ dev_dbg_ratelimited(cdns->dev, "Slave status change\n");
617926
618927 slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
619928 slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
....@@ -625,55 +934,134 @@
625934 /* clear and unmask Slave interrupt now */
626935 cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK);
627936 cdns_updatel(cdns, CDNS_MCP_INTMASK,
628
- CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK);
937
+ CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK);
629938
630
- return IRQ_HANDLED;
631939 }
632
-EXPORT_SYMBOL(sdw_cdns_thread);
633940
634941 /*
635942 * init routines
636943 */
637
-static int _cdns_enable_interrupt(struct sdw_cdns *cdns)
944
+
945
+/**
946
+ * sdw_cdns_exit_reset() - Program reset parameters and start bus operations
947
+ * @cdns: Cadence instance
948
+ */
949
+int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
950
+{
951
+ /* program maximum length reset to be safe */
952
+ cdns_updatel(cdns, CDNS_MCP_CONTROL,
953
+ CDNS_MCP_CONTROL_RST_DELAY,
954
+ CDNS_MCP_CONTROL_RST_DELAY);
955
+
956
+ /* use hardware generated reset */
957
+ cdns_updatel(cdns, CDNS_MCP_CONTROL,
958
+ CDNS_MCP_CONTROL_HW_RST,
959
+ CDNS_MCP_CONTROL_HW_RST);
960
+
961
+ /* commit changes */
962
+ cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE,
963
+ CDNS_MCP_CONFIG_UPDATE_BIT,
964
+ CDNS_MCP_CONFIG_UPDATE_BIT);
965
+
966
+ /* don't wait here */
967
+ return 0;
968
+
969
+}
970
+EXPORT_SYMBOL(sdw_cdns_exit_reset);
971
+
972
+/**
973
+ * sdw_cdns_enable_slave_interrupt() - Enable SDW slave interrupts
974
+ * @cdns: Cadence instance
975
+ * @state: boolean for true/false
976
+ */
977
+static void cdns_enable_slave_interrupts(struct sdw_cdns *cdns, bool state)
638978 {
639979 u32 mask;
640980
641
- cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,
642
- CDNS_MCP_SLAVE_INTMASK0_MASK);
643
- cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
644
- CDNS_MCP_SLAVE_INTMASK1_MASK);
981
+ mask = cdns_readl(cdns, CDNS_MCP_INTMASK);
982
+ if (state)
983
+ mask |= CDNS_MCP_INT_SLAVE_MASK;
984
+ else
985
+ mask &= ~CDNS_MCP_INT_SLAVE_MASK;
645986
646
- mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
647
- CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH |
648
- CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
649
- CDNS_MCP_INT_RX_WL | CDNS_MCP_INT_IRQ | CDNS_MCP_INT_DPINT;
987
+ cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
988
+}
650989
990
+/**
991
+ * sdw_cdns_enable_interrupt() - Enable SDW interrupts
992
+ * @cdns: Cadence instance
993
+ * @state: True if we are trying to enable interrupt.
994
+ */
995
+int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state)
996
+{
997
+ u32 slave_intmask0 = 0;
998
+ u32 slave_intmask1 = 0;
999
+ u32 mask = 0;
1000
+
1001
+ if (!state)
1002
+ goto update_masks;
1003
+
1004
+ slave_intmask0 = CDNS_MCP_SLAVE_INTMASK0_MASK;
1005
+ slave_intmask1 = CDNS_MCP_SLAVE_INTMASK1_MASK;
1006
+
1007
+ /* enable detection of all slave state changes */
1008
+ mask = CDNS_MCP_INT_SLAVE_MASK;
1009
+
1010
+ /* enable detection of bus issues */
1011
+ mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
1012
+ CDNS_MCP_INT_PARITY;
1013
+
1014
+ /* port interrupt limited to test modes for now */
1015
+ if (cdns->bus.params.m_data_mode != SDW_PORT_DATA_MODE_NORMAL)
1016
+ mask |= CDNS_MCP_INT_DPINT;
1017
+
1018
+ /* enable detection of RX fifo level */
1019
+ mask |= CDNS_MCP_INT_RX_WL;
1020
+
1021
+ /*
1022
+ * CDNS_MCP_INT_IRQ needs to be set otherwise all previous
1023
+ * settings are irrelevant
1024
+ */
1025
+ mask |= CDNS_MCP_INT_IRQ;
1026
+
1027
+ if (interrupt_mask) /* parameter override */
1028
+ mask = interrupt_mask;
1029
+
1030
+update_masks:
1031
+ /* clear slave interrupt status before enabling interrupt */
1032
+ if (state) {
1033
+ u32 slave_state;
1034
+
1035
+ slave_state = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
1036
+ cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave_state);
1037
+ slave_state = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
1038
+ cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave_state);
1039
+ }
1040
+ cdns->interrupt_enabled = state;
1041
+
1042
+ /*
1043
+ * Complete any on-going status updates before updating masks,
1044
+ * and cancel queued status updates.
1045
+ *
1046
+ * There could be a race with a new interrupt thrown before
1047
+ * the 3 mask updates below are complete, so in the interrupt
1048
+ * we use the 'interrupt_enabled' status to prevent new work
1049
+ * from being queued.
1050
+ */
1051
+ if (!state)
1052
+ cancel_work_sync(&cdns->work);
1053
+
1054
+ cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0, slave_intmask0);
1055
+ cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1, slave_intmask1);
6511056 cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
6521057
6531058 return 0;
6541059 }
655
-
656
-/**
657
- * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
658
- * @cdns: Cadence instance
659
- */
660
-int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
661
-{
662
- int ret;
663
-
664
- _cdns_enable_interrupt(cdns);
665
- ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
666
- CDNS_MCP_CONFIG_UPDATE_BIT);
667
- if (ret < 0)
668
- dev_err(cdns->dev, "Config update timedout");
669
-
670
- return ret;
671
-}
6721060 EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
6731061
6741062 static int cdns_allocate_pdi(struct sdw_cdns *cdns,
675
- struct sdw_cdns_pdi **stream,
676
- u32 num, u32 pdi_offset)
1063
+ struct sdw_cdns_pdi **stream,
1064
+ u32 num, u32 pdi_offset)
6771065 {
6781066 struct sdw_cdns_pdi *pdi;
6791067 int i;
....@@ -687,7 +1075,6 @@
6871075
6881076 for (i = 0; i < num; i++) {
6891077 pdi[i].num = i + pdi_offset;
690
- pdi[i].assigned = false;
6911078 }
6921079
6931080 *stream = pdi;
....@@ -701,10 +1088,11 @@
7011088 * @config: Stream configurations
7021089 */
7031090 int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
704
- struct sdw_cdns_stream_config config)
1091
+ struct sdw_cdns_stream_config config)
7051092 {
7061093 struct sdw_cdns_streams *stream;
707
- int offset, i, ret;
1094
+ int offset;
1095
+ int ret;
7081096
7091097 cdns->pcm.num_bd = config.pcm_bd;
7101098 cdns->pcm.num_in = config.pcm_in;
....@@ -716,9 +1104,8 @@
7161104 /* Allocate PDIs for PCMs */
7171105 stream = &cdns->pcm;
7181106
719
- /* First two PDIs are reserved for bulk transfers */
720
- stream->num_bd -= CDNS_PCM_PDI_OFFSET;
721
- offset = CDNS_PCM_PDI_OFFSET;
1107
+ /* we allocate PDI0 and PDI1 which are used for Bulk */
1108
+ offset = 0;
7221109
7231110 ret = cdns_allocate_pdi(cdns, &stream->bd,
7241111 stream->num_bd, offset);
....@@ -745,7 +1132,6 @@
7451132
7461133 /* Allocate PDIs for PDMs */
7471134 stream = &cdns->pdm;
748
- offset = CDNS_PDM_PDI_OFFSET;
7491135 ret = cdns_allocate_pdi(cdns, &stream->bd,
7501136 stream->num_bd, offset);
7511137 if (ret)
....@@ -762,6 +1148,7 @@
7621148
7631149 ret = cdns_allocate_pdi(cdns, &stream->out,
7641150 stream->num_out, offset);
1151
+
7651152 if (ret)
7661153 return ret;
7671154
....@@ -769,21 +1156,54 @@
7691156 stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
7701157 cdns->num_ports += stream->num_pdi;
7711158
772
- cdns->ports = devm_kcalloc(cdns->dev, cdns->num_ports,
773
- sizeof(*cdns->ports), GFP_KERNEL);
774
- if (!cdns->ports) {
775
- ret = -ENOMEM;
776
- return ret;
777
- }
778
-
779
- for (i = 0; i < cdns->num_ports; i++) {
780
- cdns->ports[i].assigned = false;
781
- cdns->ports[i].num = i + 1; /* Port 0 reserved for bulk */
782
- }
783
-
7841159 return 0;
7851160 }
7861161 EXPORT_SYMBOL(sdw_cdns_pdi_init);
1162
+
1163
+static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols)
1164
+{
1165
+ u32 val;
1166
+ int c;
1167
+ int r;
1168
+
1169
+ r = sdw_find_row_index(n_rows);
1170
+ c = sdw_find_col_index(n_cols);
1171
+
1172
+ val = FIELD_PREP(CDNS_MCP_FRAME_SHAPE_ROW_MASK, r);
1173
+ val |= FIELD_PREP(CDNS_MCP_FRAME_SHAPE_COL_MASK, c);
1174
+
1175
+ return val;
1176
+}
1177
+
1178
+static void cdns_init_clock_ctrl(struct sdw_cdns *cdns)
1179
+{
1180
+ struct sdw_bus *bus = &cdns->bus;
1181
+ struct sdw_master_prop *prop = &bus->prop;
1182
+ u32 val;
1183
+ u32 ssp_interval;
1184
+ int divider;
1185
+
1186
+ /* Set clock divider */
1187
+ divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
1188
+
1189
+ cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0,
1190
+ CDNS_MCP_CLK_MCLKD_MASK, divider);
1191
+ cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1,
1192
+ CDNS_MCP_CLK_MCLKD_MASK, divider);
1193
+
1194
+ /*
1195
+ * Frame shape changes after initialization have to be done
1196
+ * with the bank switch mechanism
1197
+ */
1198
+ val = cdns_set_initial_frame_shape(prop->default_row,
1199
+ prop->default_col);
1200
+ cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, val);
1201
+
1202
+ /* Set SSP interval to default value */
1203
+ ssp_interval = prop->default_frame_rate / SDW_CADENCE_GSYNC_HZ;
1204
+ cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, ssp_interval);
1205
+ cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval);
1206
+}
7871207
7881208 /**
7891209 * sdw_cdns_init() - Cadence initialization
....@@ -792,88 +1212,80 @@
7921212 int sdw_cdns_init(struct sdw_cdns *cdns)
7931213 {
7941214 u32 val;
795
- int ret;
7961215
797
- /* Exit clock stop */
798
- ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
799
- CDNS_MCP_CONTROL_CLK_STOP_CLR);
800
- if (ret < 0) {
801
- dev_err(cdns->dev, "Couldn't exit from clock stop\n");
802
- return ret;
803
- }
1216
+ cdns_init_clock_ctrl(cdns);
8041217
805
- /* Set clock divider */
806
- val = cdns_readl(cdns, CDNS_MCP_CLK_CTRL0);
807
- val |= CDNS_DEFAULT_CLK_DIVIDER;
808
- cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
1218
+ /* reset msg_count to default value of FIFOLEVEL */
1219
+ cdns->msg_count = cdns_readl(cdns, CDNS_MCP_FIFOLEVEL);
8091220
810
- /* Set the default frame shape */
811
- cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, CDNS_DEFAULT_FRAME_SHAPE);
812
-
813
- /* Set SSP interval to default value */
814
- cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);
815
- cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, CDNS_DEFAULT_SSP_INTERVAL);
1221
+ /* flush command FIFOs */
1222
+ cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_RST,
1223
+ CDNS_MCP_CONTROL_CMD_RST);
8161224
8171225 /* Set cmd accept mode */
8181226 cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT,
819
- CDNS_MCP_CONTROL_CMD_ACCEPT);
1227
+ CDNS_MCP_CONTROL_CMD_ACCEPT);
8201228
8211229 /* Configure mcp config */
8221230 val = cdns_readl(cdns, CDNS_MCP_CONFIG);
8231231
824
- /* Set Max cmd retry to 15 */
825
- val |= CDNS_MCP_CONFIG_MCMD_RETRY;
826
-
827
- /* Set frame delay between PREQ and ping frame to 15 frames */
828
- val |= 0xF << SDW_REG_SHIFT(CDNS_MCP_CONFIG_MPREQ_DELAY);
829
-
830
- /* Disable auto bus release */
831
- val &= ~CDNS_MCP_CONFIG_BUS_REL;
832
-
833
- /* Disable sniffer mode */
834
- val &= ~CDNS_MCP_CONFIG_SNIFFER;
1232
+ /* enable bus operations with clock and data */
1233
+ val &= ~CDNS_MCP_CONFIG_OP;
1234
+ val |= CDNS_MCP_CONFIG_OP_NORMAL;
8351235
8361236 /* Set cmd mode for Tx and Rx cmds */
8371237 val &= ~CDNS_MCP_CONFIG_CMD;
8381238
839
- /* Set operation to normal */
840
- val &= ~CDNS_MCP_CONFIG_OP;
841
- val |= CDNS_MCP_CONFIG_OP_NORMAL;
1239
+ /* Disable sniffer mode */
1240
+ val &= ~CDNS_MCP_CONFIG_SNIFFER;
1241
+
1242
+ /* Disable auto bus release */
1243
+ val &= ~CDNS_MCP_CONFIG_BUS_REL;
1244
+
1245
+ if (cdns->bus.multi_link)
1246
+ /* Set Multi-master mode to take gsync into account */
1247
+ val |= CDNS_MCP_CONFIG_MMASTER;
1248
+
1249
+ /* leave frame delay to hardware default of 0x1F */
1250
+
1251
+ /* leave command retry to hardware default of 0 */
8421252
8431253 cdns_writel(cdns, CDNS_MCP_CONFIG, val);
8441254
1255
+ /* changes will be committed later */
8451256 return 0;
8461257 }
8471258 EXPORT_SYMBOL(sdw_cdns_init);
8481259
8491260 int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params)
8501261 {
1262
+ struct sdw_master_prop *prop = &bus->prop;
8511263 struct sdw_cdns *cdns = bus_to_cdns(bus);
852
- int mcp_clkctrl_off, mcp_clkctrl;
1264
+ int mcp_clkctrl_off;
8531265 int divider;
8541266
8551267 if (!params->curr_dr_freq) {
856
- dev_err(cdns->dev, "NULL curr_dr_freq");
1268
+ dev_err(cdns->dev, "NULL curr_dr_freq\n");
8571269 return -EINVAL;
8581270 }
8591271
860
- divider = (params->max_dr_freq / params->curr_dr_freq) - 1;
1272
+ divider = prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR /
1273
+ params->curr_dr_freq;
1274
+ divider--; /* divider is 1/(N+1) */
8611275
8621276 if (params->next_bank)
8631277 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL1;
8641278 else
8651279 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0;
8661280
867
- mcp_clkctrl = cdns_readl(cdns, mcp_clkctrl_off);
868
- mcp_clkctrl |= divider;
869
- cdns_writel(cdns, mcp_clkctrl_off, mcp_clkctrl);
1281
+ cdns_updatel(cdns, mcp_clkctrl_off, CDNS_MCP_CLK_MCLKD_MASK, divider);
8701282
8711283 return 0;
8721284 }
8731285 EXPORT_SYMBOL(cdns_bus_conf);
8741286
8751287 static int cdns_port_params(struct sdw_bus *bus,
876
- struct sdw_port_params *p_params, unsigned int bank)
1288
+ struct sdw_port_params *p_params, unsigned int bank)
8771289 {
8781290 struct sdw_cdns *cdns = bus_to_cdns(bus);
8791291 int dpn_config = 0, dpn_config_off;
....@@ -885,12 +1297,9 @@
8851297
8861298 dpn_config = cdns_readl(cdns, dpn_config_off);
8871299
888
- dpn_config |= ((p_params->bps - 1) <<
889
- SDW_REG_SHIFT(CDNS_DPN_CONFIG_WL));
890
- dpn_config |= (p_params->flow_mode <<
891
- SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_FLOW));
892
- dpn_config |= (p_params->data_mode <<
893
- SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_DAT));
1300
+ u32p_replace_bits(&dpn_config, (p_params->bps - 1), CDNS_DPN_CONFIG_WL);
1301
+ u32p_replace_bits(&dpn_config, p_params->flow_mode, CDNS_DPN_CONFIG_PORT_FLOW);
1302
+ u32p_replace_bits(&dpn_config, p_params->data_mode, CDNS_DPN_CONFIG_PORT_DAT);
8941303
8951304 cdns_writel(cdns, dpn_config_off, dpn_config);
8961305
....@@ -898,8 +1307,8 @@
8981307 }
8991308
9001309 static int cdns_transport_params(struct sdw_bus *bus,
901
- struct sdw_transport_params *t_params,
902
- enum sdw_reg_bank bank)
1310
+ struct sdw_transport_params *t_params,
1311
+ enum sdw_reg_bank bank)
9031312 {
9041313 struct sdw_cdns *cdns = bus_to_cdns(bus);
9051314 int dpn_offsetctrl = 0, dpn_offsetctrl_off;
....@@ -926,24 +1335,17 @@
9261335 }
9271336
9281337 dpn_config = cdns_readl(cdns, dpn_config_off);
929
-
930
- dpn_config |= (t_params->blk_grp_ctrl <<
931
- SDW_REG_SHIFT(CDNS_DPN_CONFIG_BGC));
932
- dpn_config |= (t_params->blk_pkg_mode <<
933
- SDW_REG_SHIFT(CDNS_DPN_CONFIG_BPM));
1338
+ u32p_replace_bits(&dpn_config, t_params->blk_grp_ctrl, CDNS_DPN_CONFIG_BGC);
1339
+ u32p_replace_bits(&dpn_config, t_params->blk_pkg_mode, CDNS_DPN_CONFIG_BPM);
9341340 cdns_writel(cdns, dpn_config_off, dpn_config);
9351341
936
- dpn_offsetctrl |= (t_params->offset1 <<
937
- SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_1));
938
- dpn_offsetctrl |= (t_params->offset2 <<
939
- SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_2));
1342
+ u32p_replace_bits(&dpn_offsetctrl, t_params->offset1, CDNS_DPN_OFFSET_CTRL_1);
1343
+ u32p_replace_bits(&dpn_offsetctrl, t_params->offset2, CDNS_DPN_OFFSET_CTRL_2);
9401344 cdns_writel(cdns, dpn_offsetctrl_off, dpn_offsetctrl);
9411345
942
- dpn_hctrl |= (t_params->hstart <<
943
- SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTART));
944
- dpn_hctrl |= (t_params->hstop << SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTOP));
945
- dpn_hctrl |= (t_params->lane_ctrl <<
946
- SDW_REG_SHIFT(CDNS_DPN_HCTRL_LCTRL));
1346
+ u32p_replace_bits(&dpn_hctrl, t_params->hstart, CDNS_DPN_HCTRL_HSTART);
1347
+ u32p_replace_bits(&dpn_hctrl, t_params->hstop, CDNS_DPN_HCTRL_HSTOP);
1348
+ u32p_replace_bits(&dpn_hctrl, t_params->lane_ctrl, CDNS_DPN_HCTRL_LCTRL);
9471349
9481350 cdns_writel(cdns, dpn_hctrl_off, dpn_hctrl);
9491351 cdns_writel(cdns, dpn_samplectrl_off, (t_params->sample_interval - 1));
....@@ -952,7 +1354,7 @@
9521354 }
9531355
9541356 static int cdns_port_enable(struct sdw_bus *bus,
955
- struct sdw_enable_ch *enable_ch, unsigned int bank)
1357
+ struct sdw_enable_ch *enable_ch, unsigned int bank)
9561358 {
9571359 struct sdw_cdns *cdns = bus_to_cdns(bus);
9581360 int dpn_chnen_off, ch_mask;
....@@ -975,6 +1377,168 @@
9751377 };
9761378
9771379 /**
1380
+ * sdw_cdns_is_clock_stop: Check clock status
1381
+ *
1382
+ * @cdns: Cadence instance
1383
+ */
1384
+bool sdw_cdns_is_clock_stop(struct sdw_cdns *cdns)
1385
+{
1386
+ return !!(cdns_readl(cdns, CDNS_MCP_STAT) & CDNS_MCP_STAT_CLK_STOP);
1387
+}
1388
+EXPORT_SYMBOL(sdw_cdns_is_clock_stop);
1389
+
1390
+/**
1391
+ * sdw_cdns_clock_stop: Cadence clock stop configuration routine
1392
+ *
1393
+ * @cdns: Cadence instance
1394
+ * @block_wake: prevent wakes if required by the platform
1395
+ */
1396
+int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
1397
+{
1398
+ bool slave_present = false;
1399
+ struct sdw_slave *slave;
1400
+ int ret;
1401
+
1402
+ /* Check suspend status */
1403
+ if (sdw_cdns_is_clock_stop(cdns)) {
1404
+ dev_dbg(cdns->dev, "Clock is already stopped\n");
1405
+ return 0;
1406
+ }
1407
+
1408
+ /*
1409
+ * Before entering clock stop we mask the Slave
1410
+ * interrupts. This helps avoid having to deal with e.g. a
1411
+ * Slave becoming UNATTACHED while the clock is being stopped
1412
+ */
1413
+ cdns_enable_slave_interrupts(cdns, false);
1414
+
1415
+ /*
1416
+ * For specific platforms, it is required to be able to put
1417
+ * master into a state in which it ignores wake-up trials
1418
+ * in clock stop state
1419
+ */
1420
+ if (block_wake)
1421
+ cdns_updatel(cdns, CDNS_MCP_CONTROL,
1422
+ CDNS_MCP_CONTROL_BLOCK_WAKEUP,
1423
+ CDNS_MCP_CONTROL_BLOCK_WAKEUP);
1424
+
1425
+ list_for_each_entry(slave, &cdns->bus.slaves, node) {
1426
+ if (slave->status == SDW_SLAVE_ATTACHED ||
1427
+ slave->status == SDW_SLAVE_ALERT) {
1428
+ slave_present = true;
1429
+ break;
1430
+ }
1431
+ }
1432
+
1433
+ /*
1434
+ * This CMD_ACCEPT should be used when there are no devices
1435
+ * attached on the link when entering clock stop mode. If this is
1436
+ * not set and there is a broadcast write then the command ignored
1437
+ * will be treated as a failure
1438
+ */
1439
+ if (!slave_present)
1440
+ cdns_updatel(cdns, CDNS_MCP_CONTROL,
1441
+ CDNS_MCP_CONTROL_CMD_ACCEPT,
1442
+ CDNS_MCP_CONTROL_CMD_ACCEPT);
1443
+ else
1444
+ cdns_updatel(cdns, CDNS_MCP_CONTROL,
1445
+ CDNS_MCP_CONTROL_CMD_ACCEPT, 0);
1446
+
1447
+ /* commit changes */
1448
+ ret = cdns_config_update(cdns);
1449
+ if (ret < 0) {
1450
+ dev_err(cdns->dev, "%s: config_update failed\n", __func__);
1451
+ return ret;
1452
+ }
1453
+
1454
+ /* Prepare slaves for clock stop */
1455
+ if (slave_present) {
1456
+ ret = sdw_bus_prep_clk_stop(&cdns->bus);
1457
+ if (ret < 0 && ret != -ENODATA) {
1458
+ dev_err(cdns->dev, "prepare clock stop failed %d\n", ret);
1459
+ return ret;
1460
+ }
1461
+ }
1462
+
1463
+ /*
1464
+ * Enter clock stop mode and only report errors if there are
1465
+ * Slave devices present (ALERT or ATTACHED)
1466
+ */
1467
+ ret = sdw_bus_clk_stop(&cdns->bus);
1468
+ if (ret < 0 && slave_present && ret != -ENODATA) {
1469
+ dev_err(cdns->dev, "bus clock stop failed %d", ret);
1470
+ return ret;
1471
+ }
1472
+
1473
+ ret = cdns_set_wait(cdns, CDNS_MCP_STAT,
1474
+ CDNS_MCP_STAT_CLK_STOP,
1475
+ CDNS_MCP_STAT_CLK_STOP);
1476
+ if (ret < 0)
1477
+ dev_err(cdns->dev, "Clock stop failed %d\n", ret);
1478
+
1479
+ return ret;
1480
+}
1481
+EXPORT_SYMBOL(sdw_cdns_clock_stop);
1482
+
1483
+/**
1484
+ * sdw_cdns_clock_restart: Cadence PM clock restart configuration routine
1485
+ *
1486
+ * @cdns: Cadence instance
1487
+ * @bus_reset: context may be lost while in low power modes and the bus
1488
+ * may require a Severe Reset and re-enumeration after a wake.
1489
+ */
1490
+int sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset)
1491
+{
1492
+ int ret;
1493
+
1494
+ /* unmask Slave interrupts that were masked when stopping the clock */
1495
+ cdns_enable_slave_interrupts(cdns, true);
1496
+
1497
+ ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
1498
+ CDNS_MCP_CONTROL_CLK_STOP_CLR);
1499
+ if (ret < 0) {
1500
+ dev_err(cdns->dev, "Couldn't exit from clock stop\n");
1501
+ return ret;
1502
+ }
1503
+
1504
+ ret = cdns_set_wait(cdns, CDNS_MCP_STAT, CDNS_MCP_STAT_CLK_STOP, 0);
1505
+ if (ret < 0) {
1506
+ dev_err(cdns->dev, "clock stop exit failed %d\n", ret);
1507
+ return ret;
1508
+ }
1509
+
1510
+ cdns_updatel(cdns, CDNS_MCP_CONTROL,
1511
+ CDNS_MCP_CONTROL_BLOCK_WAKEUP, 0);
1512
+
1513
+ /*
1514
+ * clear CMD_ACCEPT so that the command ignored
1515
+ * will be treated as a failure during a broadcast write
1516
+ */
1517
+ cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT, 0);
1518
+
1519
+ if (!bus_reset) {
1520
+
1521
+ /* enable bus operations with clock and data */
1522
+ cdns_updatel(cdns, CDNS_MCP_CONFIG,
1523
+ CDNS_MCP_CONFIG_OP,
1524
+ CDNS_MCP_CONFIG_OP_NORMAL);
1525
+
1526
+ ret = cdns_config_update(cdns);
1527
+ if (ret < 0) {
1528
+ dev_err(cdns->dev, "%s: config_update failed\n", __func__);
1529
+ return ret;
1530
+ }
1531
+
1532
+ ret = sdw_bus_exit_clk_stop(&cdns->bus);
1533
+ if (ret < 0)
1534
+ dev_err(cdns->dev, "bus failed to exit clock stop %d\n", ret);
1535
+ }
1536
+
1537
+ return ret;
1538
+}
1539
+EXPORT_SYMBOL(sdw_cdns_clock_restart);
1540
+
1541
+/**
9781542 * sdw_cdns_probe() - Cadence probe routine
9791543 * @cdns: Cadence instance
9801544 */
....@@ -983,35 +1547,60 @@
9831547 init_completion(&cdns->tx_complete);
9841548 cdns->bus.port_ops = &cdns_port_ops;
9851549
1550
+ INIT_WORK(&cdns->work, cdns_update_slave_status_work);
9861551 return 0;
9871552 }
9881553 EXPORT_SYMBOL(sdw_cdns_probe);
9891554
9901555 int cdns_set_sdw_stream(struct snd_soc_dai *dai,
991
- void *stream, bool pcm, int direction)
1556
+ void *stream, bool pcm, int direction)
9921557 {
9931558 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
9941559 struct sdw_cdns_dma_data *dma;
9951560
996
- dma = kzalloc(sizeof(*dma), GFP_KERNEL);
997
- if (!dma)
998
- return -ENOMEM;
1561
+ if (stream) {
1562
+ /* first paranoia check */
1563
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1564
+ dma = dai->playback_dma_data;
1565
+ else
1566
+ dma = dai->capture_dma_data;
9991567
1000
- if (pcm)
1001
- dma->stream_type = SDW_STREAM_PCM;
1002
- else
1003
- dma->stream_type = SDW_STREAM_PDM;
1568
+ if (dma) {
1569
+ dev_err(dai->dev,
1570
+ "dma_data already allocated for dai %s\n",
1571
+ dai->name);
1572
+ return -EINVAL;
1573
+ }
10041574
1005
- dma->bus = &cdns->bus;
1006
- dma->link_id = cdns->instance;
1575
+ /* allocate and set dma info */
1576
+ dma = kzalloc(sizeof(*dma), GFP_KERNEL);
1577
+ if (!dma)
1578
+ return -ENOMEM;
10071579
1008
- dma->stream = stream;
1580
+ if (pcm)
1581
+ dma->stream_type = SDW_STREAM_PCM;
1582
+ else
1583
+ dma->stream_type = SDW_STREAM_PDM;
10091584
1010
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1011
- dai->playback_dma_data = dma;
1012
- else
1013
- dai->capture_dma_data = dma;
1585
+ dma->bus = &cdns->bus;
1586
+ dma->link_id = cdns->instance;
10141587
1588
+ dma->stream = stream;
1589
+
1590
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1591
+ dai->playback_dma_data = dma;
1592
+ else
1593
+ dai->capture_dma_data = dma;
1594
+ } else {
1595
+ /* for NULL stream we release allocated dma_data */
1596
+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
1597
+ kfree(dai->playback_dma_data);
1598
+ dai->playback_dma_data = NULL;
1599
+ } else {
1600
+ kfree(dai->capture_dma_data);
1601
+ dai->capture_dma_data = NULL;
1602
+ }
1603
+ }
10151604 return 0;
10161605 }
10171606 EXPORT_SYMBOL(cdns_set_sdw_stream);
....@@ -1020,22 +1609,25 @@
10201609 * cdns_find_pdi() - Find a free PDI
10211610 *
10221611 * @cdns: Cadence instance
1612
+ * @offset: Starting offset
10231613 * @num: Number of PDIs
10241614 * @pdi: PDI instances
1615
+ * @dai_id: DAI id
10251616 *
1026
- * Find and return a free PDI for a given PDI array
1617
+ * Find a PDI for a given PDI array. The PDI num and dai_id are
1618
+ * expected to match, return NULL otherwise.
10271619 */
10281620 static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns,
1029
- unsigned int num, struct sdw_cdns_pdi *pdi)
1621
+ unsigned int offset,
1622
+ unsigned int num,
1623
+ struct sdw_cdns_pdi *pdi,
1624
+ int dai_id)
10301625 {
10311626 int i;
10321627
1033
- for (i = 0; i < num; i++) {
1034
- if (pdi[i].assigned == true)
1035
- continue;
1036
- pdi[i].assigned = true;
1037
- return &pdi[i];
1038
- }
1628
+ for (i = offset; i < offset + num; i++)
1629
+ if (pdi[i].num == dai_id)
1630
+ return &pdi[i];
10391631
10401632 return NULL;
10411633 }
....@@ -1044,141 +1636,70 @@
10441636 * sdw_cdns_config_stream: Configure a stream
10451637 *
10461638 * @cdns: Cadence instance
1047
- * @port: Cadence data port
10481639 * @ch: Channel count
10491640 * @dir: Data direction
10501641 * @pdi: PDI to be used
10511642 */
10521643 void sdw_cdns_config_stream(struct sdw_cdns *cdns,
1053
- struct sdw_cdns_port *port,
1054
- u32 ch, u32 dir, struct sdw_cdns_pdi *pdi)
1644
+ u32 ch, u32 dir, struct sdw_cdns_pdi *pdi)
10551645 {
10561646 u32 offset, val = 0;
10571647
1058
- if (dir == SDW_DATA_DIR_RX)
1648
+ if (dir == SDW_DATA_DIR_RX) {
10591649 val = CDNS_PORTCTRL_DIRN;
10601650
1061
- offset = CDNS_PORTCTRL + port->num * CDNS_PORT_OFFSET;
1062
- cdns_updatel(cdns, offset, CDNS_PORTCTRL_DIRN, val);
1651
+ if (cdns->bus.params.m_data_mode != SDW_PORT_DATA_MODE_NORMAL)
1652
+ val |= CDNS_PORTCTRL_TEST_FAILED;
1653
+ }
1654
+ offset = CDNS_PORTCTRL + pdi->num * CDNS_PORT_OFFSET;
1655
+ cdns_updatel(cdns, offset,
1656
+ CDNS_PORTCTRL_DIRN | CDNS_PORTCTRL_TEST_FAILED,
1657
+ val);
10631658
1064
- val = port->num;
1065
- val |= ((1 << ch) - 1) << SDW_REG_SHIFT(CDNS_PDI_CONFIG_CHANNEL);
1659
+ val = pdi->num;
1660
+ val |= CDNS_PDI_CONFIG_SOFT_RESET;
1661
+ val |= FIELD_PREP(CDNS_PDI_CONFIG_CHANNEL, (1 << ch) - 1);
10661662 cdns_writel(cdns, CDNS_PDI_CONFIG(pdi->num), val);
10671663 }
10681664 EXPORT_SYMBOL(sdw_cdns_config_stream);
10691665
10701666 /**
1071
- * cdns_get_num_pdi() - Get number of PDIs required
1072
- *
1073
- * @cdns: Cadence instance
1074
- * @pdi: PDI to be used
1075
- * @num: Number of PDIs
1076
- * @ch_count: Channel count
1077
- */
1078
-static int cdns_get_num_pdi(struct sdw_cdns *cdns,
1079
- struct sdw_cdns_pdi *pdi,
1080
- unsigned int num, u32 ch_count)
1081
-{
1082
- int i, pdis = 0;
1083
-
1084
- for (i = 0; i < num; i++) {
1085
- if (pdi[i].assigned == true)
1086
- continue;
1087
-
1088
- if (pdi[i].ch_count < ch_count)
1089
- ch_count -= pdi[i].ch_count;
1090
- else
1091
- ch_count = 0;
1092
-
1093
- pdis++;
1094
-
1095
- if (!ch_count)
1096
- break;
1097
- }
1098
-
1099
- if (ch_count)
1100
- return 0;
1101
-
1102
- return pdis;
1103
-}
1104
-
1105
-/**
1106
- * sdw_cdns_get_stream() - Get stream information
1667
+ * sdw_cdns_alloc_pdi() - Allocate a PDI
11071668 *
11081669 * @cdns: Cadence instance
11091670 * @stream: Stream to be allocated
11101671 * @ch: Channel count
11111672 * @dir: Data direction
1673
+ * @dai_id: DAI id
11121674 */
1113
-int sdw_cdns_get_stream(struct sdw_cdns *cdns,
1114
- struct sdw_cdns_streams *stream,
1115
- u32 ch, u32 dir)
1116
-{
1117
- int pdis = 0;
1118
-
1119
- if (dir == SDW_DATA_DIR_RX)
1120
- pdis = cdns_get_num_pdi(cdns, stream->in, stream->num_in, ch);
1121
- else
1122
- pdis = cdns_get_num_pdi(cdns, stream->out, stream->num_out, ch);
1123
-
1124
- /* check if we found PDI, else find in bi-directional */
1125
- if (!pdis)
1126
- pdis = cdns_get_num_pdi(cdns, stream->bd, stream->num_bd, ch);
1127
-
1128
- return pdis;
1129
-}
1130
-EXPORT_SYMBOL(sdw_cdns_get_stream);
1131
-
1132
-/**
1133
- * sdw_cdns_alloc_stream() - Allocate a stream
1134
- *
1135
- * @cdns: Cadence instance
1136
- * @stream: Stream to be allocated
1137
- * @port: Cadence data port
1138
- * @ch: Channel count
1139
- * @dir: Data direction
1140
- */
1141
-int sdw_cdns_alloc_stream(struct sdw_cdns *cdns,
1142
- struct sdw_cdns_streams *stream,
1143
- struct sdw_cdns_port *port, u32 ch, u32 dir)
1675
+struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
1676
+ struct sdw_cdns_streams *stream,
1677
+ u32 ch, u32 dir, int dai_id)
11441678 {
11451679 struct sdw_cdns_pdi *pdi = NULL;
11461680
11471681 if (dir == SDW_DATA_DIR_RX)
1148
- pdi = cdns_find_pdi(cdns, stream->num_in, stream->in);
1682
+ pdi = cdns_find_pdi(cdns, 0, stream->num_in, stream->in,
1683
+ dai_id);
11491684 else
1150
- pdi = cdns_find_pdi(cdns, stream->num_out, stream->out);
1685
+ pdi = cdns_find_pdi(cdns, 0, stream->num_out, stream->out,
1686
+ dai_id);
11511687
11521688 /* check if we found a PDI, else find in bi-directional */
11531689 if (!pdi)
1154
- pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd);
1690
+ pdi = cdns_find_pdi(cdns, 2, stream->num_bd, stream->bd,
1691
+ dai_id);
11551692
1156
- if (!pdi)
1157
- return -EIO;
1693
+ if (pdi) {
1694
+ pdi->l_ch_num = 0;
1695
+ pdi->h_ch_num = ch - 1;
1696
+ pdi->dir = dir;
1697
+ pdi->ch_count = ch;
1698
+ }
11581699
1159
- port->pdi = pdi;
1160
- pdi->l_ch_num = 0;
1161
- pdi->h_ch_num = ch - 1;
1162
- pdi->dir = dir;
1163
- pdi->ch_count = ch;
1164
-
1165
- return 0;
1700
+ return pdi;
11661701 }
1167
-EXPORT_SYMBOL(sdw_cdns_alloc_stream);
1168
-
1169
-void sdw_cdns_shutdown(struct snd_pcm_substream *substream,
1170
- struct snd_soc_dai *dai)
1171
-{
1172
- struct sdw_cdns_dma_data *dma;
1173
-
1174
- dma = snd_soc_dai_get_dma_data(dai, substream);
1175
- if (!dma)
1176
- return;
1177
-
1178
- snd_soc_dai_set_dma_data(dai, substream, NULL);
1179
- kfree(dma);
1180
-}
1181
-EXPORT_SYMBOL(sdw_cdns_shutdown);
1702
+EXPORT_SYMBOL(sdw_cdns_alloc_pdi);
11821703
11831704 MODULE_LICENSE("Dual BSD/GPL");
11841705 MODULE_DESCRIPTION("Cadence Soundwire Library");