]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/soundwire/cadence_master.c
3338269397dda91497618edc2c667034030cfc77
[linux.git] / drivers / soundwire / cadence_master.c
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 // Copyright(c) 2015-17 Intel Corporation.
3
4 /*
5  * Cadence SoundWire Master module
6  * Used by Master driver
7  */
8
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/interrupt.h>
12 #include <linux/io.h>
13 #include <linux/module.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/soundwire/sdw_registers.h>
16 #include <linux/soundwire/sdw.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
19 #include "bus.h"
20 #include "cadence_master.h"
21
22 static int interrupt_mask;
23 module_param_named(cnds_mcp_int_mask, interrupt_mask, int, 0444);
24 MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");
25
26 #define CDNS_MCP_CONFIG                         0x0
27
28 #define CDNS_MCP_CONFIG_MCMD_RETRY              GENMASK(27, 24)
29 #define CDNS_MCP_CONFIG_MPREQ_DELAY             GENMASK(20, 16)
30 #define CDNS_MCP_CONFIG_MMASTER                 BIT(7)
31 #define CDNS_MCP_CONFIG_BUS_REL                 BIT(6)
32 #define CDNS_MCP_CONFIG_SNIFFER                 BIT(5)
33 #define CDNS_MCP_CONFIG_SSPMOD                  BIT(4)
34 #define CDNS_MCP_CONFIG_CMD                     BIT(3)
35 #define CDNS_MCP_CONFIG_OP                      GENMASK(2, 0)
36 #define CDNS_MCP_CONFIG_OP_NORMAL               0
37
38 #define CDNS_MCP_CONTROL                        0x4
39
40 #define CDNS_MCP_CONTROL_RST_DELAY              GENMASK(10, 8)
41 #define CDNS_MCP_CONTROL_CMD_RST                BIT(7)
42 #define CDNS_MCP_CONTROL_SOFT_RST               BIT(6)
43 #define CDNS_MCP_CONTROL_SW_RST                 BIT(5)
44 #define CDNS_MCP_CONTROL_HW_RST                 BIT(4)
45 #define CDNS_MCP_CONTROL_CLK_PAUSE              BIT(3)
46 #define CDNS_MCP_CONTROL_CLK_STOP_CLR           BIT(2)
47 #define CDNS_MCP_CONTROL_CMD_ACCEPT             BIT(1)
48 #define CDNS_MCP_CONTROL_BLOCK_WAKEUP           BIT(0)
49
50 #define CDNS_MCP_CMDCTRL                        0x8
51 #define CDNS_MCP_SSPSTAT                        0xC
52 #define CDNS_MCP_FRAME_SHAPE                    0x10
53 #define CDNS_MCP_FRAME_SHAPE_INIT               0x14
54 #define CDNS_MCP_FRAME_SHAPE_COL_MASK           GENMASK(2, 0)
55 #define CDNS_MCP_FRAME_SHAPE_ROW_OFFSET         3
56
57 #define CDNS_MCP_CONFIG_UPDATE                  0x18
58 #define CDNS_MCP_CONFIG_UPDATE_BIT              BIT(0)
59
60 #define CDNS_MCP_PHYCTRL                        0x1C
61 #define CDNS_MCP_SSP_CTRL0                      0x20
62 #define CDNS_MCP_SSP_CTRL1                      0x28
63 #define CDNS_MCP_CLK_CTRL0                      0x30
64 #define CDNS_MCP_CLK_CTRL1                      0x38
65 #define CDNS_MCP_CLK_MCLKD_MASK         GENMASK(7, 0)
66
67 #define CDNS_MCP_STAT                           0x40
68
69 #define CDNS_MCP_STAT_ACTIVE_BANK               BIT(20)
70 #define CDNS_MCP_STAT_CLK_STOP                  BIT(16)
71
72 #define CDNS_MCP_INTSTAT                        0x44
73 #define CDNS_MCP_INTMASK                        0x48
74
75 #define CDNS_MCP_INT_IRQ                        BIT(31)
76 #define CDNS_MCP_INT_WAKEUP                     BIT(16)
77 #define CDNS_MCP_INT_SLAVE_RSVD                 BIT(15)
78 #define CDNS_MCP_INT_SLAVE_ALERT                BIT(14)
79 #define CDNS_MCP_INT_SLAVE_ATTACH               BIT(13)
80 #define CDNS_MCP_INT_SLAVE_NATTACH              BIT(12)
81 #define CDNS_MCP_INT_SLAVE_MASK                 GENMASK(15, 12)
82 #define CDNS_MCP_INT_DPINT                      BIT(11)
83 #define CDNS_MCP_INT_CTRL_CLASH                 BIT(10)
84 #define CDNS_MCP_INT_DATA_CLASH                 BIT(9)
85 #define CDNS_MCP_INT_PARITY                     BIT(8)
86 #define CDNS_MCP_INT_CMD_ERR                    BIT(7)
87 #define CDNS_MCP_INT_RX_NE                      BIT(3)
88 #define CDNS_MCP_INT_RX_WL                      BIT(2)
89 #define CDNS_MCP_INT_TXE                        BIT(1)
90 #define CDNS_MCP_INT_TXF                        BIT(0)
91
92 #define CDNS_MCP_INTSET                         0x4C
93
94 #define CDNS_SDW_SLAVE_STAT                     0x50
95 #define CDNS_MCP_SLAVE_STAT_MASK                BIT(1, 0)
96
97 #define CDNS_MCP_SLAVE_INTSTAT0                 0x54
98 #define CDNS_MCP_SLAVE_INTSTAT1                 0x58
99 #define CDNS_MCP_SLAVE_INTSTAT_NPRESENT         BIT(0)
100 #define CDNS_MCP_SLAVE_INTSTAT_ATTACHED         BIT(1)
101 #define CDNS_MCP_SLAVE_INTSTAT_ALERT            BIT(2)
102 #define CDNS_MCP_SLAVE_INTSTAT_RESERVED         BIT(3)
103 #define CDNS_MCP_SLAVE_STATUS_BITS              GENMASK(3, 0)
104 #define CDNS_MCP_SLAVE_STATUS_NUM               4
105
106 #define CDNS_MCP_SLAVE_INTMASK0                 0x5C
107 #define CDNS_MCP_SLAVE_INTMASK1                 0x60
108
109 #define CDNS_MCP_SLAVE_INTMASK0_MASK            GENMASK(30, 0)
110 #define CDNS_MCP_SLAVE_INTMASK1_MASK            GENMASK(16, 0)
111
112 #define CDNS_MCP_PORT_INTSTAT                   0x64
113 #define CDNS_MCP_PDI_STAT                       0x6C
114
115 #define CDNS_MCP_FIFOLEVEL                      0x78
116 #define CDNS_MCP_FIFOSTAT                       0x7C
117 #define CDNS_MCP_RX_FIFO_AVAIL                  GENMASK(5, 0)
118
119 #define CDNS_MCP_CMD_BASE                       0x80
120 #define CDNS_MCP_RESP_BASE                      0x80
121 #define CDNS_MCP_CMD_LEN                        0x20
122 #define CDNS_MCP_CMD_WORD_LEN                   0x4
123
124 #define CDNS_MCP_CMD_SSP_TAG                    BIT(31)
125 #define CDNS_MCP_CMD_COMMAND                    GENMASK(30, 28)
126 #define CDNS_MCP_CMD_DEV_ADDR                   GENMASK(27, 24)
127 #define CDNS_MCP_CMD_REG_ADDR_H                 GENMASK(23, 16)
128 #define CDNS_MCP_CMD_REG_ADDR_L                 GENMASK(15, 8)
129 #define CDNS_MCP_CMD_REG_DATA                   GENMASK(7, 0)
130
131 #define CDNS_MCP_CMD_READ                       2
132 #define CDNS_MCP_CMD_WRITE                      3
133
134 #define CDNS_MCP_RESP_RDATA                     GENMASK(15, 8)
135 #define CDNS_MCP_RESP_ACK                       BIT(0)
136 #define CDNS_MCP_RESP_NACK                      BIT(1)
137
138 #define CDNS_DP_SIZE                            128
139
140 #define CDNS_DPN_B0_CONFIG(n)                   (0x100 + CDNS_DP_SIZE * (n))
141 #define CDNS_DPN_B0_CH_EN(n)                    (0x104 + CDNS_DP_SIZE * (n))
142 #define CDNS_DPN_B0_SAMPLE_CTRL(n)              (0x108 + CDNS_DP_SIZE * (n))
143 #define CDNS_DPN_B0_OFFSET_CTRL(n)              (0x10C + CDNS_DP_SIZE * (n))
144 #define CDNS_DPN_B0_HCTRL(n)                    (0x110 + CDNS_DP_SIZE * (n))
145 #define CDNS_DPN_B0_ASYNC_CTRL(n)               (0x114 + CDNS_DP_SIZE * (n))
146
147 #define CDNS_DPN_B1_CONFIG(n)                   (0x118 + CDNS_DP_SIZE * (n))
148 #define CDNS_DPN_B1_CH_EN(n)                    (0x11C + CDNS_DP_SIZE * (n))
149 #define CDNS_DPN_B1_SAMPLE_CTRL(n)              (0x120 + CDNS_DP_SIZE * (n))
150 #define CDNS_DPN_B1_OFFSET_CTRL(n)              (0x124 + CDNS_DP_SIZE * (n))
151 #define CDNS_DPN_B1_HCTRL(n)                    (0x128 + CDNS_DP_SIZE * (n))
152 #define CDNS_DPN_B1_ASYNC_CTRL(n)               (0x12C + CDNS_DP_SIZE * (n))
153
154 #define CDNS_DPN_CONFIG_BPM                     BIT(18)
155 #define CDNS_DPN_CONFIG_BGC                     GENMASK(17, 16)
156 #define CDNS_DPN_CONFIG_WL                      GENMASK(12, 8)
157 #define CDNS_DPN_CONFIG_PORT_DAT                GENMASK(3, 2)
158 #define CDNS_DPN_CONFIG_PORT_FLOW               GENMASK(1, 0)
159
160 #define CDNS_DPN_SAMPLE_CTRL_SI                 GENMASK(15, 0)
161
162 #define CDNS_DPN_OFFSET_CTRL_1                  GENMASK(7, 0)
163 #define CDNS_DPN_OFFSET_CTRL_2                  GENMASK(15, 8)
164
165 #define CDNS_DPN_HCTRL_HSTOP                    GENMASK(3, 0)
166 #define CDNS_DPN_HCTRL_HSTART                   GENMASK(7, 4)
167 #define CDNS_DPN_HCTRL_LCTRL                    GENMASK(10, 8)
168
169 #define CDNS_PORTCTRL                           0x130
170 #define CDNS_PORTCTRL_DIRN                      BIT(7)
171 #define CDNS_PORTCTRL_BANK_INVERT               BIT(8)
172
173 #define CDNS_PORT_OFFSET                        0x80
174
175 #define CDNS_PDI_CONFIG(n)                      (0x1100 + (n) * 16)
176
177 #define CDNS_PDI_CONFIG_SOFT_RESET              BIT(24)
178 #define CDNS_PDI_CONFIG_CHANNEL                 GENMASK(15, 8)
179 #define CDNS_PDI_CONFIG_PORT                    GENMASK(4, 0)
180
181 /* Driver defaults */
182 #define CDNS_DEFAULT_SSP_INTERVAL               0x18
183 #define CDNS_TX_TIMEOUT                         2000
184
185 #define CDNS_PCM_PDI_OFFSET                     0x2
186 #define CDNS_PDM_PDI_OFFSET                     0x6
187
188 #define CDNS_SCP_RX_FIFOLEVEL                   0x2
189
190 /*
191  * register accessor helpers
192  */
193 static inline u32 cdns_readl(struct sdw_cdns *cdns, int offset)
194 {
195         return readl(cdns->registers + offset);
196 }
197
198 static inline void cdns_writel(struct sdw_cdns *cdns, int offset, u32 value)
199 {
200         writel(value, cdns->registers + offset);
201 }
202
203 static inline void cdns_updatel(struct sdw_cdns *cdns,
204                                 int offset, u32 mask, u32 val)
205 {
206         u32 tmp;
207
208         tmp = cdns_readl(cdns, offset);
209         tmp = (tmp & ~mask) | val;
210         cdns_writel(cdns, offset, tmp);
211 }
212
213 static int cdns_clear_bit(struct sdw_cdns *cdns, int offset, u32 value)
214 {
215         int timeout = 10;
216         u32 reg_read;
217
218         writel(value, cdns->registers + offset);
219
220         /* Wait for bit to be self cleared */
221         do {
222                 reg_read = readl(cdns->registers + offset);
223                 if ((reg_read & value) == 0)
224                         return 0;
225
226                 timeout--;
227                 udelay(50);
228         } while (timeout != 0);
229
230         return -EAGAIN;
231 }
232
233 /*
234  * IO Calls
235  */
236 static enum sdw_command_response
237 cdns_fill_msg_resp(struct sdw_cdns *cdns,
238                    struct sdw_msg *msg, int count, int offset)
239 {
240         int nack = 0, no_ack = 0;
241         int i;
242
243         /* check message response */
244         for (i = 0; i < count; i++) {
245                 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) {
246                         no_ack = 1;
247                         dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n");
248                         if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
249                                 nack = 1;
250                                 dev_err_ratelimited(cdns->dev, "Msg NACK received\n");
251                         }
252                 }
253         }
254
255         if (nack) {
256                 dev_err_ratelimited(cdns->dev, "Msg NACKed for Slave %d\n", msg->dev_num);
257                 return SDW_CMD_FAIL;
258         } else if (no_ack) {
259                 dev_dbg_ratelimited(cdns->dev, "Msg ignored for Slave %d\n", msg->dev_num);
260                 return SDW_CMD_IGNORED;
261         }
262
263         /* fill response */
264         for (i = 0; i < count; i++)
265                 msg->buf[i + offset] = cdns->response_buf[i] >>
266                                 SDW_REG_SHIFT(CDNS_MCP_RESP_RDATA);
267
268         return SDW_CMD_OK;
269 }
270
271 static enum sdw_command_response
272 _cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd,
273                int offset, int count, bool defer)
274 {
275         unsigned long time;
276         u32 base, i, data;
277         u16 addr;
278
279         /* Program the watermark level for RX FIFO */
280         if (cdns->msg_count != count) {
281                 cdns_writel(cdns, CDNS_MCP_FIFOLEVEL, count);
282                 cdns->msg_count = count;
283         }
284
285         base = CDNS_MCP_CMD_BASE;
286         addr = msg->addr;
287
288         for (i = 0; i < count; i++) {
289                 data = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR);
290                 data |= cmd << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND);
291                 data |= addr++  << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
292
293                 if (msg->flags == SDW_MSG_FLAG_WRITE)
294                         data |= msg->buf[i + offset];
295
296                 data |= msg->ssp_sync << SDW_REG_SHIFT(CDNS_MCP_CMD_SSP_TAG);
297                 cdns_writel(cdns, base, data);
298                 base += CDNS_MCP_CMD_WORD_LEN;
299         }
300
301         if (defer)
302                 return SDW_CMD_OK;
303
304         /* wait for timeout or response */
305         time = wait_for_completion_timeout(&cdns->tx_complete,
306                                            msecs_to_jiffies(CDNS_TX_TIMEOUT));
307         if (!time) {
308                 dev_err(cdns->dev, "IO transfer timed out\n");
309                 msg->len = 0;
310                 return SDW_CMD_TIMEOUT;
311         }
312
313         return cdns_fill_msg_resp(cdns, msg, count, offset);
314 }
315
316 static enum sdw_command_response
317 cdns_program_scp_addr(struct sdw_cdns *cdns, struct sdw_msg *msg)
318 {
319         int nack = 0, no_ack = 0;
320         unsigned long time;
321         u32 data[2], base;
322         int i;
323
324         /* Program the watermark level for RX FIFO */
325         if (cdns->msg_count != CDNS_SCP_RX_FIFOLEVEL) {
326                 cdns_writel(cdns, CDNS_MCP_FIFOLEVEL, CDNS_SCP_RX_FIFOLEVEL);
327                 cdns->msg_count = CDNS_SCP_RX_FIFOLEVEL;
328         }
329
330         data[0] = msg->dev_num << SDW_REG_SHIFT(CDNS_MCP_CMD_DEV_ADDR);
331         data[0] |= 0x3 << SDW_REG_SHIFT(CDNS_MCP_CMD_COMMAND);
332         data[1] = data[0];
333
334         data[0] |= SDW_SCP_ADDRPAGE1 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
335         data[1] |= SDW_SCP_ADDRPAGE2 << SDW_REG_SHIFT(CDNS_MCP_CMD_REG_ADDR_L);
336
337         data[0] |= msg->addr_page1;
338         data[1] |= msg->addr_page2;
339
340         base = CDNS_MCP_CMD_BASE;
341         cdns_writel(cdns, base, data[0]);
342         base += CDNS_MCP_CMD_WORD_LEN;
343         cdns_writel(cdns, base, data[1]);
344
345         time = wait_for_completion_timeout(&cdns->tx_complete,
346                                            msecs_to_jiffies(CDNS_TX_TIMEOUT));
347         if (!time) {
348                 dev_err(cdns->dev, "SCP Msg trf timed out\n");
349                 msg->len = 0;
350                 return SDW_CMD_TIMEOUT;
351         }
352
353         /* check response the writes */
354         for (i = 0; i < 2; i++) {
355                 if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) {
356                         no_ack = 1;
357                         dev_err(cdns->dev, "Program SCP Ack not received\n");
358                         if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) {
359                                 nack = 1;
360                                 dev_err(cdns->dev, "Program SCP NACK received\n");
361                         }
362                 }
363         }
364
365         /* For NACK, NO ack, don't return err if we are in Broadcast mode */
366         if (nack) {
367                 dev_err_ratelimited(cdns->dev,
368                                     "SCP_addrpage NACKed for Slave %d\n", msg->dev_num);
369                 return SDW_CMD_FAIL;
370         } else if (no_ack) {
371                 dev_dbg_ratelimited(cdns->dev,
372                                     "SCP_addrpage ignored for Slave %d\n", msg->dev_num);
373                 return SDW_CMD_IGNORED;
374         }
375
376         return SDW_CMD_OK;
377 }
378
379 static int cdns_prep_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int *cmd)
380 {
381         int ret;
382
383         if (msg->page) {
384                 ret = cdns_program_scp_addr(cdns, msg);
385                 if (ret) {
386                         msg->len = 0;
387                         return ret;
388                 }
389         }
390
391         switch (msg->flags) {
392         case SDW_MSG_FLAG_READ:
393                 *cmd = CDNS_MCP_CMD_READ;
394                 break;
395
396         case SDW_MSG_FLAG_WRITE:
397                 *cmd = CDNS_MCP_CMD_WRITE;
398                 break;
399
400         default:
401                 dev_err(cdns->dev, "Invalid msg cmd: %d\n", msg->flags);
402                 return -EINVAL;
403         }
404
405         return 0;
406 }
407
408 enum sdw_command_response
409 cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg)
410 {
411         struct sdw_cdns *cdns = bus_to_cdns(bus);
412         int cmd = 0, ret, i;
413
414         ret = cdns_prep_msg(cdns, msg, &cmd);
415         if (ret)
416                 return SDW_CMD_FAIL_OTHER;
417
418         for (i = 0; i < msg->len / CDNS_MCP_CMD_LEN; i++) {
419                 ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN,
420                                      CDNS_MCP_CMD_LEN, false);
421                 if (ret < 0)
422                         goto exit;
423         }
424
425         if (!(msg->len % CDNS_MCP_CMD_LEN))
426                 goto exit;
427
428         ret = _cdns_xfer_msg(cdns, msg, cmd, i * CDNS_MCP_CMD_LEN,
429                              msg->len % CDNS_MCP_CMD_LEN, false);
430
431 exit:
432         return ret;
433 }
434 EXPORT_SYMBOL(cdns_xfer_msg);
435
436 enum sdw_command_response
437 cdns_xfer_msg_defer(struct sdw_bus *bus,
438                     struct sdw_msg *msg, struct sdw_defer *defer)
439 {
440         struct sdw_cdns *cdns = bus_to_cdns(bus);
441         int cmd = 0, ret;
442
443         /* for defer only 1 message is supported */
444         if (msg->len > 1)
445                 return -ENOTSUPP;
446
447         ret = cdns_prep_msg(cdns, msg, &cmd);
448         if (ret)
449                 return SDW_CMD_FAIL_OTHER;
450
451         cdns->defer = defer;
452         cdns->defer->length = msg->len;
453
454         return _cdns_xfer_msg(cdns, msg, cmd, 0, msg->len, true);
455 }
456 EXPORT_SYMBOL(cdns_xfer_msg_defer);
457
458 enum sdw_command_response
459 cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num)
460 {
461         struct sdw_cdns *cdns = bus_to_cdns(bus);
462         struct sdw_msg msg;
463
464         /* Create dummy message with valid device number */
465         memset(&msg, 0, sizeof(msg));
466         msg.dev_num = dev_num;
467
468         return cdns_program_scp_addr(cdns, &msg);
469 }
470 EXPORT_SYMBOL(cdns_reset_page_addr);
471
472 /*
473  * IRQ handling
474  */
475
476 static void cdns_read_response(struct sdw_cdns *cdns)
477 {
478         u32 num_resp, cmd_base;
479         int i;
480
481         num_resp = cdns_readl(cdns, CDNS_MCP_FIFOSTAT);
482         num_resp &= CDNS_MCP_RX_FIFO_AVAIL;
483
484         cmd_base = CDNS_MCP_CMD_BASE;
485
486         for (i = 0; i < num_resp; i++) {
487                 cdns->response_buf[i] = cdns_readl(cdns, cmd_base);
488                 cmd_base += CDNS_MCP_CMD_WORD_LEN;
489         }
490 }
491
492 static int cdns_update_slave_status(struct sdw_cdns *cdns,
493                                     u32 slave0, u32 slave1)
494 {
495         enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
496         bool is_slave = false;
497         u64 slave;
498         u32 mask;
499         int i, set_status;
500
501         /* combine the two status */
502         slave = ((u64)slave1 << 32) | slave0;
503         memset(status, 0, sizeof(status));
504
505         for (i = 0; i <= SDW_MAX_DEVICES; i++) {
506                 mask = (slave >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) &
507                                 CDNS_MCP_SLAVE_STATUS_BITS;
508                 if (!mask)
509                         continue;
510
511                 is_slave = true;
512                 set_status = 0;
513
514                 if (mask & CDNS_MCP_SLAVE_INTSTAT_RESERVED) {
515                         status[i] = SDW_SLAVE_RESERVED;
516                         set_status++;
517                 }
518
519                 if (mask & CDNS_MCP_SLAVE_INTSTAT_ATTACHED) {
520                         status[i] = SDW_SLAVE_ATTACHED;
521                         set_status++;
522                 }
523
524                 if (mask & CDNS_MCP_SLAVE_INTSTAT_ALERT) {
525                         status[i] = SDW_SLAVE_ALERT;
526                         set_status++;
527                 }
528
529                 if (mask & CDNS_MCP_SLAVE_INTSTAT_NPRESENT) {
530                         status[i] = SDW_SLAVE_UNATTACHED;
531                         set_status++;
532                 }
533
534                 /* first check if Slave reported multiple status */
535                 if (set_status > 1) {
536                         dev_warn_ratelimited(cdns->dev,
537                                              "Slave reported multiple Status: %d\n",
538                                              mask);
539                         /*
540                          * TODO: we need to reread the status here by
541                          * issuing a PING cmd
542                          */
543                 }
544         }
545
546         if (is_slave)
547                 return sdw_handle_slave_status(&cdns->bus, status);
548
549         return 0;
550 }
551
552 /**
553  * sdw_cdns_irq() - Cadence interrupt handler
554  * @irq: irq number
555  * @dev_id: irq context
556  */
557 irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
558 {
559         struct sdw_cdns *cdns = dev_id;
560         u32 int_status;
561         int ret = IRQ_HANDLED;
562
563         /* Check if the link is up */
564         if (!cdns->link_up)
565                 return IRQ_NONE;
566
567         int_status = cdns_readl(cdns, CDNS_MCP_INTSTAT);
568
569         if (!(int_status & CDNS_MCP_INT_IRQ))
570                 return IRQ_NONE;
571
572         if (int_status & CDNS_MCP_INT_RX_WL) {
573                 cdns_read_response(cdns);
574
575                 if (cdns->defer) {
576                         cdns_fill_msg_resp(cdns, cdns->defer->msg,
577                                            cdns->defer->length, 0);
578                         complete(&cdns->defer->complete);
579                         cdns->defer = NULL;
580                 } else {
581                         complete(&cdns->tx_complete);
582                 }
583         }
584
585         if (int_status & CDNS_MCP_INT_PARITY) {
586                 /* Parity error detected by Master */
587                 dev_err_ratelimited(cdns->dev, "Parity error\n");
588         }
589
590         if (int_status & CDNS_MCP_INT_CTRL_CLASH) {
591                 /* Slave is driving bit slot during control word */
592                 dev_err_ratelimited(cdns->dev, "Bus clash for control word\n");
593         }
594
595         if (int_status & CDNS_MCP_INT_DATA_CLASH) {
596                 /*
597                  * Multiple slaves trying to drive bit slot, or issue with
598                  * ownership of data bits or Slave gone bonkers
599                  */
600                 dev_err_ratelimited(cdns->dev, "Bus clash for data word\n");
601         }
602
603         if (int_status & CDNS_MCP_INT_SLAVE_MASK) {
604                 /* Mask the Slave interrupt and wake thread */
605                 cdns_updatel(cdns, CDNS_MCP_INTMASK,
606                              CDNS_MCP_INT_SLAVE_MASK, 0);
607
608                 int_status &= ~CDNS_MCP_INT_SLAVE_MASK;
609                 ret = IRQ_WAKE_THREAD;
610         }
611
612         cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);
613         return ret;
614 }
615 EXPORT_SYMBOL(sdw_cdns_irq);
616
617 /**
618  * sdw_cdns_thread() - Cadence irq thread handler
619  * @irq: irq number
620  * @dev_id: irq context
621  */
622 irqreturn_t sdw_cdns_thread(int irq, void *dev_id)
623 {
624         struct sdw_cdns *cdns = dev_id;
625         u32 slave0, slave1;
626
627         dev_dbg_ratelimited(cdns->dev, "Slave status change\n");
628
629         slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
630         slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
631
632         cdns_update_slave_status(cdns, slave0, slave1);
633         cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0);
634         cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave1);
635
636         /* clear and unmask Slave interrupt now */
637         cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_SLAVE_MASK);
638         cdns_updatel(cdns, CDNS_MCP_INTMASK,
639                      CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK);
640
641         return IRQ_HANDLED;
642 }
643 EXPORT_SYMBOL(sdw_cdns_thread);
644
645 /*
646  * init routines
647  */
648 static int _cdns_enable_interrupt(struct sdw_cdns *cdns)
649 {
650         u32 mask;
651
652         cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,
653                     CDNS_MCP_SLAVE_INTMASK0_MASK);
654         cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
655                     CDNS_MCP_SLAVE_INTMASK1_MASK);
656
657         /* enable detection of all slave state changes */
658         mask = CDNS_MCP_INT_SLAVE_MASK;
659
660         /* enable detection of bus issues */
661         mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
662                 CDNS_MCP_INT_PARITY;
663
664         /* no detection of port interrupts for now */
665
666         /* enable detection of RX fifo level */
667         mask |= CDNS_MCP_INT_RX_WL;
668
669         /*
670          * CDNS_MCP_INT_IRQ needs to be set otherwise all previous
671          * settings are irrelevant
672          */
673         mask |= CDNS_MCP_INT_IRQ;
674
675         if (interrupt_mask) /* parameter override */
676                 mask = interrupt_mask;
677
678         cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
679
680         return 0;
681 }
682
683 /**
684  * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
685  * @cdns: Cadence instance
686  */
687 int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
688 {
689         int ret;
690
691         _cdns_enable_interrupt(cdns);
692         ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
693                              CDNS_MCP_CONFIG_UPDATE_BIT);
694         if (ret < 0)
695                 dev_err(cdns->dev, "Config update timedout\n");
696
697         return ret;
698 }
699 EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
700
701 static int cdns_allocate_pdi(struct sdw_cdns *cdns,
702                              struct sdw_cdns_pdi **stream,
703                              u32 num, u32 pdi_offset)
704 {
705         struct sdw_cdns_pdi *pdi;
706         int i;
707
708         if (!num)
709                 return 0;
710
711         pdi = devm_kcalloc(cdns->dev, num, sizeof(*pdi), GFP_KERNEL);
712         if (!pdi)
713                 return -ENOMEM;
714
715         for (i = 0; i < num; i++) {
716                 pdi[i].num = i + pdi_offset;
717                 pdi[i].assigned = false;
718         }
719
720         *stream = pdi;
721         return 0;
722 }
723
724 /**
725  * sdw_cdns_pdi_init() - PDI initialization routine
726  *
727  * @cdns: Cadence instance
728  * @config: Stream configurations
729  */
730 int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
731                       struct sdw_cdns_stream_config config)
732 {
733         struct sdw_cdns_streams *stream;
734         int offset, i, ret;
735
736         cdns->pcm.num_bd = config.pcm_bd;
737         cdns->pcm.num_in = config.pcm_in;
738         cdns->pcm.num_out = config.pcm_out;
739         cdns->pdm.num_bd = config.pdm_bd;
740         cdns->pdm.num_in = config.pdm_in;
741         cdns->pdm.num_out = config.pdm_out;
742
743         /* Allocate PDIs for PCMs */
744         stream = &cdns->pcm;
745
746         /* First two PDIs are reserved for bulk transfers */
747         if (stream->num_bd < CDNS_PCM_PDI_OFFSET)
748                 return -EINVAL;
749         stream->num_bd -= CDNS_PCM_PDI_OFFSET;
750         offset = CDNS_PCM_PDI_OFFSET;
751
752         ret = cdns_allocate_pdi(cdns, &stream->bd,
753                                 stream->num_bd, offset);
754         if (ret)
755                 return ret;
756
757         offset += stream->num_bd;
758
759         ret = cdns_allocate_pdi(cdns, &stream->in,
760                                 stream->num_in, offset);
761         if (ret)
762                 return ret;
763
764         offset += stream->num_in;
765
766         ret = cdns_allocate_pdi(cdns, &stream->out,
767                                 stream->num_out, offset);
768         if (ret)
769                 return ret;
770
771         /* Update total number of PCM PDIs */
772         stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
773         cdns->num_ports = stream->num_pdi;
774
775         /* Allocate PDIs for PDMs */
776         stream = &cdns->pdm;
777         offset = CDNS_PDM_PDI_OFFSET;
778         ret = cdns_allocate_pdi(cdns, &stream->bd,
779                                 stream->num_bd, offset);
780         if (ret)
781                 return ret;
782
783         offset += stream->num_bd;
784
785         ret = cdns_allocate_pdi(cdns, &stream->in,
786                                 stream->num_in, offset);
787         if (ret)
788                 return ret;
789
790         offset += stream->num_in;
791
792         ret = cdns_allocate_pdi(cdns, &stream->out,
793                                 stream->num_out, offset);
794         if (ret)
795                 return ret;
796
797         /* Update total number of PDM PDIs */
798         stream->num_pdi = stream->num_bd + stream->num_in + stream->num_out;
799         cdns->num_ports += stream->num_pdi;
800
801         cdns->ports = devm_kcalloc(cdns->dev, cdns->num_ports,
802                                    sizeof(*cdns->ports), GFP_KERNEL);
803         if (!cdns->ports) {
804                 ret = -ENOMEM;
805                 return ret;
806         }
807
808         for (i = 0; i < cdns->num_ports; i++) {
809                 cdns->ports[i].assigned = false;
810                 cdns->ports[i].num = i + 1; /* Port 0 reserved for bulk */
811         }
812
813         return 0;
814 }
815 EXPORT_SYMBOL(sdw_cdns_pdi_init);
816
817 static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols)
818 {
819         u32 val;
820         int c;
821         int r;
822
823         r = sdw_find_row_index(n_rows);
824         c = sdw_find_col_index(n_cols) & CDNS_MCP_FRAME_SHAPE_COL_MASK;
825
826         val = (r << CDNS_MCP_FRAME_SHAPE_ROW_OFFSET) | c;
827
828         return val;
829 }
830
831 /**
832  * sdw_cdns_init() - Cadence initialization
833  * @cdns: Cadence instance
834  */
835 int sdw_cdns_init(struct sdw_cdns *cdns)
836 {
837         struct sdw_bus *bus = &cdns->bus;
838         struct sdw_master_prop *prop = &bus->prop;
839         u32 val;
840         int divider;
841         int ret;
842
843         /* Exit clock stop */
844         ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
845                              CDNS_MCP_CONTROL_CLK_STOP_CLR);
846         if (ret < 0) {
847                 dev_err(cdns->dev, "Couldn't exit from clock stop\n");
848                 return ret;
849         }
850
851         /* Set clock divider */
852         divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
853
854         cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0,
855                      CDNS_MCP_CLK_MCLKD_MASK, divider);
856         cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1,
857                      CDNS_MCP_CLK_MCLKD_MASK, divider);
858
859         /*
860          * Frame shape changes after initialization have to be done
861          * with the bank switch mechanism
862          */
863         val = cdns_set_initial_frame_shape(prop->default_row,
864                                            prop->default_col);
865         cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, val);
866
867         /* Set SSP interval to default value */
868         cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);
869         cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, CDNS_DEFAULT_SSP_INTERVAL);
870
871         /* Set cmd accept mode */
872         cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT,
873                      CDNS_MCP_CONTROL_CMD_ACCEPT);
874
875         /* Configure mcp config */
876         val = cdns_readl(cdns, CDNS_MCP_CONFIG);
877
878         /* Set Max cmd retry to 15 */
879         val |= CDNS_MCP_CONFIG_MCMD_RETRY;
880
881         /* Set frame delay between PREQ and ping frame to 15 frames */
882         val |= 0xF << SDW_REG_SHIFT(CDNS_MCP_CONFIG_MPREQ_DELAY);
883
884         /* Disable auto bus release */
885         val &= ~CDNS_MCP_CONFIG_BUS_REL;
886
887         /* Disable sniffer mode */
888         val &= ~CDNS_MCP_CONFIG_SNIFFER;
889
890         /* Set cmd mode for Tx and Rx cmds */
891         val &= ~CDNS_MCP_CONFIG_CMD;
892
893         /* Set operation to normal */
894         val &= ~CDNS_MCP_CONFIG_OP;
895         val |= CDNS_MCP_CONFIG_OP_NORMAL;
896
897         cdns_writel(cdns, CDNS_MCP_CONFIG, val);
898
899         return 0;
900 }
901 EXPORT_SYMBOL(sdw_cdns_init);
902
903 int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params)
904 {
905         struct sdw_master_prop *prop = &bus->prop;
906         struct sdw_cdns *cdns = bus_to_cdns(bus);
907         int mcp_clkctrl_off;
908         int divider;
909
910         if (!params->curr_dr_freq) {
911                 dev_err(cdns->dev, "NULL curr_dr_freq\n");
912                 return -EINVAL;
913         }
914
915         divider = prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR /
916                 params->curr_dr_freq;
917         divider--; /* divider is 1/(N+1) */
918
919         if (params->next_bank)
920                 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL1;
921         else
922                 mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0;
923
924         cdns_updatel(cdns, mcp_clkctrl_off, CDNS_MCP_CLK_MCLKD_MASK, divider);
925
926         return 0;
927 }
928 EXPORT_SYMBOL(cdns_bus_conf);
929
930 static int cdns_port_params(struct sdw_bus *bus,
931                             struct sdw_port_params *p_params, unsigned int bank)
932 {
933         struct sdw_cdns *cdns = bus_to_cdns(bus);
934         int dpn_config = 0, dpn_config_off;
935
936         if (bank)
937                 dpn_config_off = CDNS_DPN_B1_CONFIG(p_params->num);
938         else
939                 dpn_config_off = CDNS_DPN_B0_CONFIG(p_params->num);
940
941         dpn_config = cdns_readl(cdns, dpn_config_off);
942
943         dpn_config |= ((p_params->bps - 1) <<
944                                 SDW_REG_SHIFT(CDNS_DPN_CONFIG_WL));
945         dpn_config |= (p_params->flow_mode <<
946                                 SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_FLOW));
947         dpn_config |= (p_params->data_mode <<
948                                 SDW_REG_SHIFT(CDNS_DPN_CONFIG_PORT_DAT));
949
950         cdns_writel(cdns, dpn_config_off, dpn_config);
951
952         return 0;
953 }
954
955 static int cdns_transport_params(struct sdw_bus *bus,
956                                  struct sdw_transport_params *t_params,
957                                  enum sdw_reg_bank bank)
958 {
959         struct sdw_cdns *cdns = bus_to_cdns(bus);
960         int dpn_offsetctrl = 0, dpn_offsetctrl_off;
961         int dpn_config = 0, dpn_config_off;
962         int dpn_hctrl = 0, dpn_hctrl_off;
963         int num = t_params->port_num;
964         int dpn_samplectrl_off;
965
966         /*
967          * Note: Only full data port is supported on the Master side for
968          * both PCM and PDM ports.
969          */
970
971         if (bank) {
972                 dpn_config_off = CDNS_DPN_B1_CONFIG(num);
973                 dpn_samplectrl_off = CDNS_DPN_B1_SAMPLE_CTRL(num);
974                 dpn_hctrl_off = CDNS_DPN_B1_HCTRL(num);
975                 dpn_offsetctrl_off = CDNS_DPN_B1_OFFSET_CTRL(num);
976         } else {
977                 dpn_config_off = CDNS_DPN_B0_CONFIG(num);
978                 dpn_samplectrl_off = CDNS_DPN_B0_SAMPLE_CTRL(num);
979                 dpn_hctrl_off = CDNS_DPN_B0_HCTRL(num);
980                 dpn_offsetctrl_off = CDNS_DPN_B0_OFFSET_CTRL(num);
981         }
982
983         dpn_config = cdns_readl(cdns, dpn_config_off);
984
985         dpn_config |= (t_params->blk_grp_ctrl <<
986                                 SDW_REG_SHIFT(CDNS_DPN_CONFIG_BGC));
987         dpn_config |= (t_params->blk_pkg_mode <<
988                                 SDW_REG_SHIFT(CDNS_DPN_CONFIG_BPM));
989         cdns_writel(cdns, dpn_config_off, dpn_config);
990
991         dpn_offsetctrl |= (t_params->offset1 <<
992                                 SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_1));
993         dpn_offsetctrl |= (t_params->offset2 <<
994                                 SDW_REG_SHIFT(CDNS_DPN_OFFSET_CTRL_2));
995         cdns_writel(cdns, dpn_offsetctrl_off,  dpn_offsetctrl);
996
997         dpn_hctrl |= (t_params->hstart <<
998                                 SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTART));
999         dpn_hctrl |= (t_params->hstop << SDW_REG_SHIFT(CDNS_DPN_HCTRL_HSTOP));
1000         dpn_hctrl |= (t_params->lane_ctrl <<
1001                                 SDW_REG_SHIFT(CDNS_DPN_HCTRL_LCTRL));
1002
1003         cdns_writel(cdns, dpn_hctrl_off, dpn_hctrl);
1004         cdns_writel(cdns, dpn_samplectrl_off, (t_params->sample_interval - 1));
1005
1006         return 0;
1007 }
1008
1009 static int cdns_port_enable(struct sdw_bus *bus,
1010                             struct sdw_enable_ch *enable_ch, unsigned int bank)
1011 {
1012         struct sdw_cdns *cdns = bus_to_cdns(bus);
1013         int dpn_chnen_off, ch_mask;
1014
1015         if (bank)
1016                 dpn_chnen_off = CDNS_DPN_B1_CH_EN(enable_ch->port_num);
1017         else
1018                 dpn_chnen_off = CDNS_DPN_B0_CH_EN(enable_ch->port_num);
1019
1020         ch_mask = enable_ch->ch_mask * enable_ch->enable;
1021         cdns_writel(cdns, dpn_chnen_off, ch_mask);
1022
1023         return 0;
1024 }
1025
1026 static const struct sdw_master_port_ops cdns_port_ops = {
1027         .dpn_set_port_params = cdns_port_params,
1028         .dpn_set_port_transport_params = cdns_transport_params,
1029         .dpn_port_enable_ch = cdns_port_enable,
1030 };
1031
1032 /**
1033  * sdw_cdns_probe() - Cadence probe routine
1034  * @cdns: Cadence instance
1035  */
1036 int sdw_cdns_probe(struct sdw_cdns *cdns)
1037 {
1038         init_completion(&cdns->tx_complete);
1039         cdns->bus.port_ops = &cdns_port_ops;
1040
1041         return 0;
1042 }
1043 EXPORT_SYMBOL(sdw_cdns_probe);
1044
1045 int cdns_set_sdw_stream(struct snd_soc_dai *dai,
1046                         void *stream, bool pcm, int direction)
1047 {
1048         struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
1049         struct sdw_cdns_dma_data *dma;
1050
1051         dma = kzalloc(sizeof(*dma), GFP_KERNEL);
1052         if (!dma)
1053                 return -ENOMEM;
1054
1055         if (pcm)
1056                 dma->stream_type = SDW_STREAM_PCM;
1057         else
1058                 dma->stream_type = SDW_STREAM_PDM;
1059
1060         dma->bus = &cdns->bus;
1061         dma->link_id = cdns->instance;
1062
1063         dma->stream = stream;
1064
1065         if (direction == SNDRV_PCM_STREAM_PLAYBACK)
1066                 dai->playback_dma_data = dma;
1067         else
1068                 dai->capture_dma_data = dma;
1069
1070         return 0;
1071 }
1072 EXPORT_SYMBOL(cdns_set_sdw_stream);
1073
1074 /**
1075  * cdns_find_pdi() - Find a free PDI
1076  *
1077  * @cdns: Cadence instance
1078  * @num: Number of PDIs
1079  * @pdi: PDI instances
1080  *
1081  * Find and return a free PDI for a given PDI array
1082  */
1083 static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns,
1084                                           unsigned int num,
1085                                           struct sdw_cdns_pdi *pdi)
1086 {
1087         int i;
1088
1089         for (i = 0; i < num; i++) {
1090                 if (pdi[i].assigned)
1091                         continue;
1092                 pdi[i].assigned = true;
1093                 return &pdi[i];
1094         }
1095
1096         return NULL;
1097 }
1098
1099 /**
1100  * sdw_cdns_config_stream: Configure a stream
1101  *
1102  * @cdns: Cadence instance
1103  * @port: Cadence data port
1104  * @ch: Channel count
1105  * @dir: Data direction
1106  * @pdi: PDI to be used
1107  */
1108 void sdw_cdns_config_stream(struct sdw_cdns *cdns,
1109                             struct sdw_cdns_port *port,
1110                             u32 ch, u32 dir, struct sdw_cdns_pdi *pdi)
1111 {
1112         u32 offset, val = 0;
1113
1114         if (dir == SDW_DATA_DIR_RX)
1115                 val = CDNS_PORTCTRL_DIRN;
1116
1117         offset = CDNS_PORTCTRL + port->num * CDNS_PORT_OFFSET;
1118         cdns_updatel(cdns, offset, CDNS_PORTCTRL_DIRN, val);
1119
1120         val = port->num;
1121         val |= ((1 << ch) - 1) << SDW_REG_SHIFT(CDNS_PDI_CONFIG_CHANNEL);
1122         cdns_writel(cdns, CDNS_PDI_CONFIG(pdi->num), val);
1123 }
1124 EXPORT_SYMBOL(sdw_cdns_config_stream);
1125
1126 /**
1127  * cdns_get_num_pdi() - Get number of PDIs required
1128  *
1129  * @cdns: Cadence instance
1130  * @pdi: PDI to be used
1131  * @num: Number of PDIs
1132  * @ch_count: Channel count
1133  */
1134 static int cdns_get_num_pdi(struct sdw_cdns *cdns,
1135                             struct sdw_cdns_pdi *pdi,
1136                             unsigned int num, u32 ch_count)
1137 {
1138         int i, pdis = 0;
1139
1140         for (i = 0; i < num; i++) {
1141                 if (pdi[i].assigned)
1142                         continue;
1143
1144                 if (pdi[i].ch_count < ch_count)
1145                         ch_count -= pdi[i].ch_count;
1146                 else
1147                         ch_count = 0;
1148
1149                 pdis++;
1150
1151                 if (!ch_count)
1152                         break;
1153         }
1154
1155         if (ch_count)
1156                 return 0;
1157
1158         return pdis;
1159 }
1160
1161 /**
1162  * sdw_cdns_get_stream() - Get stream information
1163  *
1164  * @cdns: Cadence instance
1165  * @stream: Stream to be allocated
1166  * @ch: Channel count
1167  * @dir: Data direction
1168  */
1169 int sdw_cdns_get_stream(struct sdw_cdns *cdns,
1170                         struct sdw_cdns_streams *stream,
1171                         u32 ch, u32 dir)
1172 {
1173         int pdis = 0;
1174
1175         if (dir == SDW_DATA_DIR_RX)
1176                 pdis = cdns_get_num_pdi(cdns, stream->in, stream->num_in, ch);
1177         else
1178                 pdis = cdns_get_num_pdi(cdns, stream->out, stream->num_out, ch);
1179
1180         /* check if we found PDI, else find in bi-directional */
1181         if (!pdis)
1182                 pdis = cdns_get_num_pdi(cdns, stream->bd, stream->num_bd, ch);
1183
1184         return pdis;
1185 }
1186 EXPORT_SYMBOL(sdw_cdns_get_stream);
1187
1188 /**
1189  * sdw_cdns_alloc_stream() - Allocate a stream
1190  *
1191  * @cdns: Cadence instance
1192  * @stream: Stream to be allocated
1193  * @port: Cadence data port
1194  * @ch: Channel count
1195  * @dir: Data direction
1196  */
1197 int sdw_cdns_alloc_stream(struct sdw_cdns *cdns,
1198                           struct sdw_cdns_streams *stream,
1199                           struct sdw_cdns_port *port, u32 ch, u32 dir)
1200 {
1201         struct sdw_cdns_pdi *pdi = NULL;
1202
1203         if (dir == SDW_DATA_DIR_RX)
1204                 pdi = cdns_find_pdi(cdns, stream->num_in, stream->in);
1205         else
1206                 pdi = cdns_find_pdi(cdns, stream->num_out, stream->out);
1207
1208         /* check if we found a PDI, else find in bi-directional */
1209         if (!pdi)
1210                 pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd);
1211
1212         if (!pdi)
1213                 return -EIO;
1214
1215         port->pdi = pdi;
1216         pdi->l_ch_num = 0;
1217         pdi->h_ch_num = ch - 1;
1218         pdi->dir = dir;
1219         pdi->ch_count = ch;
1220
1221         return 0;
1222 }
1223 EXPORT_SYMBOL(sdw_cdns_alloc_stream);
1224
1225 MODULE_LICENSE("Dual BSD/GPL");
1226 MODULE_DESCRIPTION("Cadence Soundwire Library");