cadence_master.c 28 KB

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