cam_cdm_util.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/types.h>
  7. #include <linux/kernel.h>
  8. #include <linux/errno.h>
  9. #include <linux/bug.h>
  10. #include "cam_cdm_intf_api.h"
  11. #include "cam_cdm_util.h"
  12. #include "cam_cdm.h"
  13. #include "cam_io_util.h"
  14. #define CAM_CDM_DWORD 4
  15. #define CAM_CDM_SW_CMD_COUNT 2
  16. #define CAM_CMD_LENGTH_MASK 0xFFFF
  17. #define CAM_CDM_REG_OFFSET_MASK 0x00FFFFFF
  18. #define CAM_CDM_DMI_DATA_HI_OFFSET 8
  19. #define CAM_CDM_DMI_DATA_OFFSET 8
  20. #define CAM_CDM_DMI_DATA_LO_OFFSET 12
  21. static unsigned int CDMCmdHeaderSizes[
  22. CAM_CDM_CMD_PRIVATE_BASE + CAM_CDM_SW_CMD_COUNT] = {
  23. 0, /* UNUSED*/
  24. 3, /* DMI*/
  25. 0, /* UNUSED*/
  26. 2, /* RegContinuous*/
  27. 1, /* RegRandom*/
  28. 2, /* BUFFER_INDIREC*/
  29. 2, /* GenerateIRQ*/
  30. 3, /* WaitForEvent*/
  31. 1, /* ChangeBase*/
  32. 1, /* PERF_CONTROL*/
  33. 3, /* DMI32*/
  34. 3, /* DMI64*/
  35. 3, /* WaitCompEvent*/
  36. 3, /* ClearCompEvent*/
  37. 3, /* WaitPrefetchDisable*/
  38. };
  39. /**
  40. * struct cdm_regrandom_cmd - Definition for CDM random register command.
  41. * @count: Number of register writes
  42. * @reserved: reserved bits
  43. * @cmd: Command ID (CDMCmd)
  44. */
  45. struct cdm_regrandom_cmd {
  46. unsigned int count : 16;
  47. unsigned int reserved : 8;
  48. unsigned int cmd : 8;
  49. } __attribute__((__packed__));
  50. /**
  51. * struct cdm_regcontinuous_cmd - Definition for a CDM register range command.
  52. * @count: Number of register writes
  53. * @reserved0: reserved bits
  54. * @cmd: Command ID (CDMCmd)
  55. * @offset: Start address of the range of registers
  56. * @reserved1: reserved bits
  57. */
  58. struct cdm_regcontinuous_cmd {
  59. unsigned int count : 16;
  60. unsigned int reserved0 : 8;
  61. unsigned int cmd : 8;
  62. unsigned int offset : 24;
  63. unsigned int reserved1 : 8;
  64. } __attribute__((__packed__));
  65. /**
  66. * struct cdm_dmi_cmd - Definition for a CDM DMI command.
  67. * @length: Number of bytes in LUT - 1
  68. * @reserved: reserved bits
  69. * @cmd: Command ID (CDMCmd)
  70. * @addr: Address of the LUT in memory
  71. * @DMIAddr: Address of the target DMI config register
  72. * @DMISel: DMI identifier
  73. */
  74. struct cdm_dmi_cmd {
  75. unsigned int length : 16;
  76. unsigned int reserved : 8;
  77. unsigned int cmd : 8;
  78. unsigned int addr;
  79. unsigned int DMIAddr : 24;
  80. unsigned int DMISel : 8;
  81. } __attribute__((__packed__));
  82. /**
  83. * struct cdm_indirect_cmd - Definition for a CDM indirect buffer command.
  84. * @length: Number of bytes in buffer - 1
  85. * @reserved: reserved bits
  86. * @cmd: Command ID (CDMCmd)
  87. * @addr: Device address of the indirect buffer
  88. */
  89. struct cdm_indirect_cmd {
  90. unsigned int length : 16;
  91. unsigned int reserved : 8;
  92. unsigned int cmd : 8;
  93. unsigned int addr;
  94. } __attribute__((__packed__));
  95. /**
  96. * struct cdm_changebase_cmd - Definition for CDM base address change command.
  97. * @base: Base address to be changed to
  98. * @cmd:Command ID (CDMCmd)
  99. */
  100. struct cdm_changebase_cmd {
  101. unsigned int base : 24;
  102. unsigned int cmd : 8;
  103. } __attribute__((__packed__));
  104. /**
  105. * struct cdm_wait_event_cmd - Definition for a CDM Gen IRQ command.
  106. * @mask: Mask for the events
  107. * @id: ID to read back for debug
  108. * @iw_reserved: reserved bits
  109. * @iw: iw AHB write bit
  110. * @cmd:Command ID (CDMCmd)
  111. * @offset: Offset to where data is written
  112. * @offset_reserved: reserved bits
  113. * @data: data returned in IRQ_USR_DATA
  114. */
  115. struct cdm_wait_event_cmd {
  116. unsigned int mask : 8;
  117. unsigned int id : 8;
  118. unsigned int iw_reserved : 7;
  119. unsigned int iw : 1;
  120. unsigned int cmd : 8;
  121. unsigned int offset : 24;
  122. unsigned int offset_reserved : 8;
  123. unsigned int data;
  124. } __attribute__((__packed__));
  125. /**
  126. * struct cdm_genirq_cmd - Definition for a CDM Wait event command.
  127. * @reserved: reserved bits
  128. * @cmd:Command ID (CDMCmd)
  129. * @userdata: userdata returned in IRQ_USR_DATA
  130. */
  131. struct cdm_genirq_cmd {
  132. unsigned int reserved : 24;
  133. unsigned int cmd : 8;
  134. unsigned int userdata;
  135. } __attribute__((__packed__));
  136. /**
  137. * struct cdm_perf_ctrl_cmd_t - Definition for CDM perf control command.
  138. * @perf: perf command
  139. * @reserved: reserved bits
  140. * @cmd:Command ID (CDMCmd)
  141. */
  142. struct cdm_perf_ctrl_cmd {
  143. unsigned int perf : 2;
  144. unsigned int reserved : 22;
  145. unsigned int cmd : 8;
  146. } __attribute__((__packed__));
  147. struct cdm_wait_comp_event_cmd {
  148. unsigned int reserved : 8;
  149. unsigned int id : 8;
  150. unsigned int id_reserved: 8;
  151. unsigned int cmd : 8;
  152. unsigned int mask1;
  153. unsigned int mask2;
  154. } __attribute__((__packed__));
  155. struct cdm_clear_comp_event_cmd {
  156. unsigned int reserved : 8;
  157. unsigned int id : 8;
  158. unsigned int id_reserved: 8;
  159. unsigned int cmd : 8;
  160. unsigned int mask1;
  161. unsigned int mask2;
  162. } __attribute__((__packed__));
  163. struct cdm_prefetch_disable_event_cmd {
  164. unsigned int reserved : 8;
  165. unsigned int id : 8;
  166. unsigned int id_reserved: 8;
  167. unsigned int cmd : 8;
  168. unsigned int mask1;
  169. unsigned int mask2;
  170. } __attribute__((__packed__));
  171. uint32_t cam_cdm_get_cmd_header_size(unsigned int command)
  172. {
  173. return CDMCmdHeaderSizes[command];
  174. }
  175. uint32_t cam_cdm_required_size_dmi(void)
  176. {
  177. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_DMI);
  178. }
  179. uint32_t cam_cdm_required_size_reg_continuous(uint32_t numVals)
  180. {
  181. if (!numVals) {
  182. CAM_WARN(CAM_CDM, "numVals cant be 0");
  183. return 0;
  184. }
  185. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT) + numVals;
  186. }
  187. uint32_t cam_cdm_required_size_reg_random(uint32_t numRegVals)
  188. {
  189. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM) +
  190. (2 * numRegVals);
  191. }
  192. uint32_t cam_cdm_required_size_indirect(void)
  193. {
  194. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_BUFF_INDIRECT);
  195. }
  196. uint32_t cam_cdm_required_size_genirq(void)
  197. {
  198. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_GEN_IRQ);
  199. }
  200. uint32_t cam_cdm_required_size_wait_event(void)
  201. {
  202. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_WAIT_EVENT);
  203. }
  204. uint32_t cam_cdm_required_size_changebase(void)
  205. {
  206. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_CHANGE_BASE);
  207. }
  208. uint32_t cam_cdm_required_size_comp_wait(void)
  209. {
  210. return cam_cdm_get_cmd_header_size(CAM_CDM_CMD_COMP_WAIT);
  211. }
  212. uint32_t cam_cdm_required_size_clear_comp_event(void)
  213. {
  214. return cam_cdm_get_cmd_header_size(CAM_CDM_CLEAR_COMP_WAIT);
  215. }
  216. uint32_t cam_cdm_required_size_prefetch_disable(void)
  217. {
  218. return cam_cdm_get_cmd_header_size(CAM_CDM_WAIT_PREFETCH_DISABLE);
  219. }
  220. uint32_t cam_cdm_offsetof_dmi_addr(void)
  221. {
  222. return offsetof(struct cdm_dmi_cmd, addr);
  223. }
  224. uint32_t cam_cdm_offsetof_indirect_addr(void)
  225. {
  226. return offsetof(struct cdm_indirect_cmd, addr);
  227. }
  228. uint32_t *cam_cdm_write_dmi(uint32_t *pCmdBuffer, uint8_t dmiCmd,
  229. uint32_t DMIAddr, uint8_t DMISel, uint32_t dmiBufferAddr,
  230. uint32_t length)
  231. {
  232. struct cdm_dmi_cmd *pHeader = (struct cdm_dmi_cmd *)pCmdBuffer;
  233. pHeader->cmd = CAM_CDM_CMD_DMI;
  234. pHeader->addr = dmiBufferAddr;
  235. pHeader->length = length;
  236. pHeader->DMIAddr = DMIAddr;
  237. pHeader->DMISel = DMISel;
  238. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_DMI);
  239. return pCmdBuffer;
  240. }
  241. uint32_t *cam_cdm_write_regcontinuous(uint32_t *pCmdBuffer, uint32_t reg,
  242. uint32_t numVals, uint32_t *pVals)
  243. {
  244. uint32_t i;
  245. struct cdm_regcontinuous_cmd *pHeader =
  246. (struct cdm_regcontinuous_cmd *)pCmdBuffer;
  247. pHeader->count = numVals;
  248. pHeader->cmd = CAM_CDM_CMD_REG_CONT;
  249. pHeader->reserved0 = 0;
  250. pHeader->reserved1 = 0;
  251. pHeader->offset = reg;
  252. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT);
  253. for (i = 0; i < numVals; i++)
  254. (((uint32_t *)pCmdBuffer)[i]) = (((uint32_t *)pVals)[i]);
  255. pCmdBuffer += numVals;
  256. return pCmdBuffer;
  257. }
  258. uint32_t *cam_cdm_write_regrandom(uint32_t *pCmdBuffer, uint32_t numRegVals,
  259. uint32_t *pRegVals)
  260. {
  261. uint32_t i;
  262. uint32_t *dst, *src;
  263. struct cdm_regrandom_cmd *pHeader =
  264. (struct cdm_regrandom_cmd *)pCmdBuffer;
  265. if (!numRegVals) {
  266. CAM_ERR(CAM_CDM, "Number of reg-val pairs can not be 0");
  267. return pCmdBuffer;
  268. }
  269. pHeader->count = numRegVals;
  270. pHeader->cmd = CAM_CDM_CMD_REG_RANDOM;
  271. pHeader->reserved = 0;
  272. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
  273. dst = pCmdBuffer;
  274. src = pRegVals;
  275. for (i = 0; i < numRegVals; i++) {
  276. *dst++ = *src++;
  277. *dst++ = *src++;
  278. }
  279. return dst;
  280. }
  281. uint32_t *cam_cdm_write_indirect(uint32_t *pCmdBuffer, uint32_t indirectBufAddr,
  282. uint32_t length)
  283. {
  284. struct cdm_indirect_cmd *pHeader =
  285. (struct cdm_indirect_cmd *)pCmdBuffer;
  286. pHeader->cmd = CAM_CDM_CMD_BUFF_INDIRECT;
  287. pHeader->addr = indirectBufAddr;
  288. pHeader->length = length - 1;
  289. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_BUFF_INDIRECT);
  290. return pCmdBuffer;
  291. }
  292. void cam_cdm_write_genirq(uint32_t *pCmdBuffer, uint32_t userdata,
  293. bool bit_wr_enable, uint32_t fifo_idx)
  294. {
  295. struct cdm_genirq_cmd *pHeader = (struct cdm_genirq_cmd *)pCmdBuffer;
  296. CAM_DBG(CAM_CDM, "userdata 0x%x, fifo_idx %d",
  297. userdata, fifo_idx);
  298. if (bit_wr_enable)
  299. pHeader->reserved = (unsigned int)((fifo_idx << 1)
  300. | (unsigned int)(bit_wr_enable));
  301. pHeader->cmd = CAM_CDM_CMD_GEN_IRQ;
  302. pHeader->userdata = (userdata << (8 * fifo_idx));
  303. }
  304. uint32_t *cam_cdm_write_wait_event(uint32_t *pcmdbuffer, uint32_t iw,
  305. uint32_t id, uint32_t mask,
  306. uint32_t offset, uint32_t data)
  307. {
  308. struct cdm_wait_event_cmd *pheader =
  309. (struct cdm_wait_event_cmd *)pcmdbuffer;
  310. pheader->cmd = CAM_CDM_CMD_WAIT_EVENT;
  311. pheader->mask = mask;
  312. pheader->data = data;
  313. pheader->id = id;
  314. pheader->iw = iw;
  315. pheader->offset = offset;
  316. pheader->iw_reserved = 0;
  317. pheader->offset_reserved = 0;
  318. pcmdbuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_WAIT_EVENT);
  319. return pcmdbuffer;
  320. }
  321. uint32_t *cam_cdm_write_changebase(uint32_t *pCmdBuffer, uint32_t base)
  322. {
  323. struct cdm_changebase_cmd *pHeader =
  324. (struct cdm_changebase_cmd *)pCmdBuffer;
  325. CAM_DBG(CAM_CDM, "Change to base 0x%x", base);
  326. pHeader->cmd = CAM_CDM_CMD_CHANGE_BASE;
  327. pHeader->base = base;
  328. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_CHANGE_BASE);
  329. return pCmdBuffer;
  330. }
  331. uint32_t *cam_cdm_write_wait_comp_event(
  332. uint32_t *pCmdBuffer, uint32_t mask1, uint32_t mask2)
  333. {
  334. struct cdm_wait_comp_event_cmd *pHeader =
  335. (struct cdm_wait_comp_event_cmd *)pCmdBuffer;
  336. pHeader->cmd = CAM_CDM_CMD_COMP_WAIT;
  337. pHeader->mask1 = mask1;
  338. pHeader->mask2 = mask2;
  339. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_COMP_WAIT);
  340. return pCmdBuffer;
  341. }
  342. uint32_t *cam_cdm_write_clear_comp_event(
  343. uint32_t *pCmdBuffer, uint32_t mask1, uint32_t mask2)
  344. {
  345. struct cdm_clear_comp_event_cmd *pHeader =
  346. (struct cdm_clear_comp_event_cmd *)pCmdBuffer;
  347. pHeader->cmd = CAM_CDM_CLEAR_COMP_WAIT;
  348. pHeader->mask1 = mask1;
  349. pHeader->mask2 = mask2;
  350. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_CLEAR_COMP_WAIT);
  351. return pCmdBuffer;
  352. }
  353. uint32_t *cam_cdm_write_wait_prefetch_disable(
  354. uint32_t *pCmdBuffer,
  355. uint32_t id,
  356. uint32_t mask1,
  357. uint32_t mask2)
  358. {
  359. struct cdm_prefetch_disable_event_cmd *pHeader =
  360. (struct cdm_prefetch_disable_event_cmd *)pCmdBuffer;
  361. pHeader->cmd = CAM_CDM_WAIT_PREFETCH_DISABLE;
  362. pHeader->id = id;
  363. pHeader->mask1 = mask1;
  364. pHeader->mask2 = mask2;
  365. pCmdBuffer += cam_cdm_get_cmd_header_size(CAM_CDM_WAIT_PREFETCH_DISABLE);
  366. return pCmdBuffer;
  367. }
  368. struct cam_cdm_utils_ops CDM170_ops = {
  369. .cdm_get_cmd_header_size = cam_cdm_get_cmd_header_size,
  370. .cdm_required_size_dmi = cam_cdm_required_size_dmi,
  371. .cdm_required_size_reg_continuous = cam_cdm_required_size_reg_continuous,
  372. .cdm_required_size_reg_random = cam_cdm_required_size_reg_random,
  373. .cdm_required_size_indirect = cam_cdm_required_size_indirect,
  374. .cdm_required_size_genirq = cam_cdm_required_size_genirq,
  375. .cdm_required_size_wait_event = cam_cdm_required_size_wait_event,
  376. .cdm_required_size_changebase = cam_cdm_required_size_changebase,
  377. .cdm_required_size_comp_wait = cam_cdm_required_size_comp_wait,
  378. .cdm_required_size_clear_comp_event = cam_cdm_required_size_clear_comp_event,
  379. .cdm_required_size_prefetch_disable = cam_cdm_required_size_prefetch_disable,
  380. .cdm_offsetof_dmi_addr = cam_cdm_offsetof_dmi_addr,
  381. .cdm_offsetof_indirect_addr = cam_cdm_offsetof_indirect_addr,
  382. .cdm_write_dmi = cam_cdm_write_dmi,
  383. .cdm_write_regcontinuous = cam_cdm_write_regcontinuous,
  384. .cdm_write_regrandom = cam_cdm_write_regrandom,
  385. .cdm_write_indirect = cam_cdm_write_indirect,
  386. .cdm_write_genirq = cam_cdm_write_genirq,
  387. .cdm_write_wait_event = cam_cdm_write_wait_event,
  388. .cdm_write_changebase = cam_cdm_write_changebase,
  389. .cdm_write_wait_comp_event = cam_cdm_write_wait_comp_event,
  390. .cdm_write_clear_comp_event = cam_cdm_write_clear_comp_event,
  391. .cdm_write_wait_prefetch_disable = cam_cdm_write_wait_prefetch_disable,
  392. };
  393. int cam_cdm_get_ioremap_from_base(uint32_t hw_base,
  394. uint32_t base_array_size,
  395. struct cam_soc_reg_map *base_table[CAM_SOC_MAX_BLOCK],
  396. void __iomem **device_base)
  397. {
  398. int ret = -EINVAL, i;
  399. for (i = 0; i < base_array_size; i++) {
  400. if (base_table[i])
  401. CAM_DBG(CAM_CDM, "In loop %d ioremap for %x addr=%x",
  402. i, (base_table[i])->mem_cam_base, hw_base);
  403. if ((base_table[i]) &&
  404. ((base_table[i])->mem_cam_base == hw_base)) {
  405. *device_base = (base_table[i])->mem_base;
  406. ret = 0;
  407. break;
  408. }
  409. }
  410. return ret;
  411. }
  412. static int cam_cdm_util_reg_cont_write(void __iomem *base_addr,
  413. uint32_t *cmd_buf, uint32_t cmd_buf_size, uint32_t *used_bytes)
  414. {
  415. int ret = 0;
  416. uint32_t *data;
  417. struct cdm_regcontinuous_cmd *reg_cont;
  418. if ((cmd_buf_size < cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)) ||
  419. (!base_addr)) {
  420. CAM_ERR(CAM_CDM, "invalid base addr and data length %d %pK",
  421. cmd_buf_size, base_addr);
  422. return -EINVAL;
  423. }
  424. reg_cont = (struct cdm_regcontinuous_cmd *)cmd_buf;
  425. if ((!reg_cont->count) || (((reg_cont->count * sizeof(uint32_t)) +
  426. cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT)) >
  427. cmd_buf_size)) {
  428. CAM_ERR(CAM_CDM, "buffer size %d is not sufficient for count%d",
  429. cmd_buf_size, reg_cont->count);
  430. return -EINVAL;
  431. }
  432. data = cmd_buf + cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT);
  433. cam_io_memcpy(base_addr + reg_cont->offset, data,
  434. reg_cont->count * sizeof(uint32_t));
  435. *used_bytes = (reg_cont->count * sizeof(uint32_t)) +
  436. (4 * cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT));
  437. return ret;
  438. }
  439. static int cam_cdm_util_reg_random_write(void __iomem *base_addr,
  440. uint32_t *cmd_buf, uint32_t cmd_buf_size, uint32_t *used_bytes)
  441. {
  442. uint32_t i;
  443. struct cdm_regrandom_cmd *reg_random;
  444. uint32_t *data;
  445. if (!base_addr) {
  446. CAM_ERR(CAM_CDM, "invalid base address");
  447. return -EINVAL;
  448. }
  449. reg_random = (struct cdm_regrandom_cmd *) cmd_buf;
  450. if ((!reg_random->count) || (((reg_random->count * (sizeof(uint32_t) * 2)) +
  451. cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM)) >
  452. cmd_buf_size)) {
  453. CAM_ERR(CAM_CDM, "invalid reg_count %d cmd_buf_size %d",
  454. reg_random->count, cmd_buf_size);
  455. return -EINVAL;
  456. }
  457. data = cmd_buf + cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
  458. for (i = 0; i < reg_random->count; i++) {
  459. CAM_DBG(CAM_CDM, "reg random: offset %pK, value 0x%x",
  460. ((void __iomem *)(base_addr + data[0])),
  461. data[1]);
  462. cam_io_w(data[1], base_addr + data[0]);
  463. data += 2;
  464. }
  465. *used_bytes = ((reg_random->count * (sizeof(uint32_t) * 2)) +
  466. (4 * cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM)));
  467. return 0;
  468. }
  469. static int cam_cdm_util_swd_dmi_write(uint32_t cdm_cmd_type,
  470. void __iomem *base_addr, uint32_t *cmd_buf, uint32_t cmd_buf_size,
  471. uint32_t *used_bytes)
  472. {
  473. uint32_t i;
  474. struct cdm_dmi_cmd *swd_dmi;
  475. uint32_t *data;
  476. swd_dmi = (struct cdm_dmi_cmd *)cmd_buf;
  477. if (cmd_buf_size < (cam_cdm_required_size_dmi() + swd_dmi->length + 1)) {
  478. CAM_ERR(CAM_CDM, "invalid CDM_SWD_DMI length %d",
  479. swd_dmi->length + 1);
  480. return -EINVAL;
  481. }
  482. data = cmd_buf + cam_cdm_required_size_dmi();
  483. if (cdm_cmd_type == CAM_CDM_CMD_SWD_DMI_64) {
  484. for (i = 0; i < (swd_dmi->length + 1)/8; i++) {
  485. cam_io_w_mb(data[0], base_addr +
  486. swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_LO_OFFSET);
  487. cam_io_w_mb(data[1], base_addr +
  488. swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_HI_OFFSET);
  489. data += 2;
  490. }
  491. } else if (cdm_cmd_type == CAM_CDM_CMD_DMI) {
  492. for (i = 0; i < (swd_dmi->length + 1)/4; i++) {
  493. cam_io_w_mb(data[0], base_addr +
  494. swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_OFFSET);
  495. data += 1;
  496. }
  497. } else {
  498. for (i = 0; i < (swd_dmi->length + 1)/4; i++) {
  499. cam_io_w_mb(data[0], base_addr +
  500. swd_dmi->DMIAddr + CAM_CDM_DMI_DATA_LO_OFFSET);
  501. data += 1;
  502. }
  503. }
  504. *used_bytes = (4 * cam_cdm_required_size_dmi()) + swd_dmi->length + 1;
  505. return 0;
  506. }
  507. int cam_cdm_util_cmd_buf_write(void __iomem **current_device_base,
  508. uint32_t *cmd_buf, uint32_t cmd_buf_size,
  509. struct cam_soc_reg_map *base_table[CAM_SOC_MAX_BLOCK],
  510. uint32_t base_array_size, uint8_t bl_tag)
  511. {
  512. int ret = 0;
  513. uint32_t cdm_cmd_type = 0;
  514. uint32_t used_bytes = 0;
  515. while (cmd_buf_size > 0) {
  516. CAM_DBG(CAM_CDM, "cmd data=%x", *cmd_buf);
  517. cdm_cmd_type = (*cmd_buf >> CAM_CDM_COMMAND_OFFSET);
  518. switch (cdm_cmd_type) {
  519. case CAM_CDM_CMD_REG_CONT: {
  520. ret = cam_cdm_util_reg_cont_write(*current_device_base,
  521. cmd_buf, cmd_buf_size, &used_bytes);
  522. if (ret)
  523. break;
  524. if (used_bytes > 0) {
  525. cmd_buf_size -= used_bytes;
  526. cmd_buf += used_bytes/4;
  527. }
  528. }
  529. break;
  530. case CAM_CDM_CMD_REG_RANDOM: {
  531. ret = cam_cdm_util_reg_random_write(
  532. *current_device_base, cmd_buf, cmd_buf_size,
  533. &used_bytes);
  534. if (ret)
  535. break;
  536. if (used_bytes > 0) {
  537. cmd_buf_size -= used_bytes;
  538. cmd_buf += used_bytes / 4;
  539. }
  540. }
  541. break;
  542. case CAM_CDM_CMD_DMI:
  543. case CAM_CDM_CMD_SWD_DMI_32:
  544. case CAM_CDM_CMD_SWD_DMI_64: {
  545. if (*current_device_base == 0) {
  546. CAM_ERR(CAM_CDM,
  547. "Got SWI DMI cmd =%d for invalid hw",
  548. cdm_cmd_type);
  549. ret = -EINVAL;
  550. break;
  551. }
  552. ret = cam_cdm_util_swd_dmi_write(cdm_cmd_type,
  553. *current_device_base, cmd_buf, cmd_buf_size,
  554. &used_bytes);
  555. if (ret)
  556. break;
  557. if (used_bytes > 0) {
  558. cmd_buf_size -= used_bytes;
  559. cmd_buf += used_bytes / 4;
  560. }
  561. }
  562. break;
  563. case CAM_CDM_CMD_CHANGE_BASE: {
  564. struct cdm_changebase_cmd *change_base_cmd =
  565. (struct cdm_changebase_cmd *)cmd_buf;
  566. ret = cam_cdm_get_ioremap_from_base(
  567. change_base_cmd->base, base_array_size,
  568. base_table, current_device_base);
  569. if (ret != 0) {
  570. CAM_ERR(CAM_CDM,
  571. "Get ioremap change base failed %x",
  572. change_base_cmd->base);
  573. break;
  574. }
  575. CAM_DBG(CAM_CDM, "Got ioremap for %x addr=%pK",
  576. change_base_cmd->base,
  577. current_device_base);
  578. cmd_buf_size -= (4 *
  579. cam_cdm_required_size_changebase());
  580. cmd_buf += cam_cdm_required_size_changebase();
  581. }
  582. break;
  583. default:
  584. CAM_ERR(CAM_CDM, "unsupported cdm_cmd_type type 0%x",
  585. cdm_cmd_type);
  586. ret = -EINVAL;
  587. break;
  588. }
  589. if (ret < 0)
  590. break;
  591. }
  592. return ret;
  593. }
  594. static long cam_cdm_util_dump_dmi_cmd(uint32_t *cmd_buf_addr,
  595. uint32_t *cmd_buf_addr_end)
  596. {
  597. long ret = 0;
  598. struct cdm_dmi_cmd *p_dmi_cmd;
  599. uint32_t *temp_ptr = cmd_buf_addr;
  600. p_dmi_cmd = (struct cdm_dmi_cmd *)cmd_buf_addr;
  601. temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI];
  602. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI];
  603. if (temp_ptr > cmd_buf_addr_end)
  604. CAM_ERR(CAM_CDM,
  605. "Invalid cmd start addr:%pK end addr:%pK",
  606. temp_ptr, cmd_buf_addr_end);
  607. CAM_INFO(CAM_CDM,
  608. "DMI: LEN: %u DMIAddr: 0x%X DMISel: 0x%X LUT_addr: 0x%X",
  609. p_dmi_cmd->length, p_dmi_cmd->DMIAddr,
  610. p_dmi_cmd->DMISel, p_dmi_cmd->addr);
  611. return ret;
  612. }
  613. static long cam_cdm_util_dump_buff_indirect(uint32_t *cmd_buf_addr,
  614. uint32_t *cmd_buf_addr_end)
  615. {
  616. long ret = 0;
  617. struct cdm_indirect_cmd *p_indirect_cmd;
  618. uint32_t *temp_ptr = cmd_buf_addr;
  619. p_indirect_cmd = (struct cdm_indirect_cmd *)cmd_buf_addr;
  620. temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT];
  621. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT];
  622. if (temp_ptr > cmd_buf_addr_end)
  623. CAM_ERR(CAM_CDM,
  624. "Invalid cmd start addr:%pK end addr:%pK",
  625. temp_ptr, cmd_buf_addr_end);
  626. CAM_INFO(CAM_CDM,
  627. "Buff Indirect: LEN: %u addr: 0x%X",
  628. p_indirect_cmd->length, p_indirect_cmd->addr);
  629. return ret;
  630. }
  631. static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr,
  632. uint32_t *cmd_buf_addr_end)
  633. {
  634. long ret = 0;
  635. struct cdm_regcontinuous_cmd *p_regcont_cmd;
  636. uint32_t *temp_ptr = cmd_buf_addr;
  637. int i = 0;
  638. p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr;
  639. temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
  640. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
  641. CAM_INFO(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X",
  642. p_regcont_cmd->count, p_regcont_cmd->offset);
  643. for (i = 0; i < p_regcont_cmd->count; i++) {
  644. if (temp_ptr > cmd_buf_addr_end) {
  645. CAM_ERR(CAM_CDM,
  646. "Invalid cmd(%d) start addr:%pK end addr:%pK",
  647. i, temp_ptr, cmd_buf_addr_end);
  648. break;
  649. }
  650. CAM_INFO(CAM_CDM, "DATA_%d: 0x%X", i,
  651. *temp_ptr);
  652. temp_ptr++;
  653. ret++;
  654. }
  655. return ret;
  656. }
  657. static long cam_cdm_util_dump_reg_random_cmd(uint32_t *cmd_buf_addr,
  658. uint32_t *cmd_buf_addr_end)
  659. {
  660. struct cdm_regrandom_cmd *p_regrand_cmd;
  661. uint32_t *temp_ptr = cmd_buf_addr;
  662. long ret = 0;
  663. int i = 0;
  664. p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr;
  665. temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
  666. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
  667. CAM_INFO(CAM_CDM, "REG_RAND: COUNT: %u",
  668. p_regrand_cmd->count);
  669. for (i = 0; i < p_regrand_cmd->count; i++) {
  670. if (temp_ptr > cmd_buf_addr_end) {
  671. CAM_ERR(CAM_CDM,
  672. "Invalid cmd(%d) start addr:%pK end addr:%pK",
  673. i, temp_ptr, cmd_buf_addr_end);
  674. break;
  675. }
  676. CAM_INFO(CAM_CDM, "OFFSET_%d: 0x%X DATA_%d: 0x%X",
  677. i, *temp_ptr & CAM_CDM_REG_OFFSET_MASK, i,
  678. *(temp_ptr + 1));
  679. temp_ptr += 2;
  680. ret += 2;
  681. }
  682. return ret;
  683. }
  684. static long cam_cdm_util_dump_gen_irq_cmd(uint32_t *cmd_buf_addr)
  685. {
  686. long ret = 0;
  687. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ];
  688. CAM_INFO(CAM_CDM, "GEN_IRQ");
  689. return ret;
  690. }
  691. static long cam_cdm_util_dump_wait_event_cmd(uint32_t *cmd_buf_addr)
  692. {
  693. long ret = 0;
  694. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT];
  695. CAM_INFO(CAM_CDM, "WAIT_EVENT");
  696. return ret;
  697. }
  698. static long cam_cdm_util_dump_change_base_cmd(uint32_t *cmd_buf_addr,
  699. uint32_t *cmd_buf_addr_end)
  700. {
  701. long ret = 0;
  702. struct cdm_changebase_cmd *p_cbase_cmd;
  703. uint32_t *temp_ptr = cmd_buf_addr;
  704. if (temp_ptr > cmd_buf_addr_end) {
  705. CAM_ERR(CAM_CDM,
  706. "Invalid cmd start addr:%pK end addr:%pK",
  707. temp_ptr, cmd_buf_addr_end);
  708. return 0;
  709. }
  710. p_cbase_cmd = (struct cdm_changebase_cmd *)temp_ptr;
  711. temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE];
  712. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE];
  713. CAM_INFO(CAM_CDM, "CHANGE_BASE: 0x%X, curr cmd addr: %pK",
  714. p_cbase_cmd->base, temp_ptr);
  715. return ret;
  716. }
  717. static long cam_cdm_util_dump_comp_wait_event_cmd(uint32_t *cmd_buf_addr)
  718. {
  719. long ret = 0;
  720. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_COMP_WAIT];
  721. CAM_INFO(CAM_CDM, "WAIT_EVENT");
  722. return ret;
  723. }
  724. static long cam_cdm_util_dump_perf_ctrl_cmd(uint32_t *cmd_buf_addr)
  725. {
  726. long ret = 0;
  727. ret += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL];
  728. CAM_INFO(CAM_CDM, "PERF_CTRL");
  729. return ret;
  730. }
  731. bool cam_cdm_util_validate_cmd_buf(
  732. uint32_t *cmd_buf_start, uint32_t *cmd_buf_end)
  733. {
  734. uint32_t *buf_now = cmd_buf_start;
  735. uint32_t *buf_end = cmd_buf_end;
  736. uint32_t cmd = 0;
  737. int i = 0;
  738. struct cdm_regcontinuous_cmd *p_regcont_cmd = NULL;
  739. struct cdm_regrandom_cmd *p_regrand_cmd = NULL;
  740. if (!cmd_buf_start || !cmd_buf_end) {
  741. CAM_ERR(CAM_CDM, "Invalid args");
  742. return true;
  743. }
  744. do {
  745. cmd = *buf_now;
  746. cmd = cmd >> CAM_CDM_COMMAND_OFFSET;
  747. switch (cmd) {
  748. case CAM_CDM_CMD_DMI:
  749. case CAM_CDM_CMD_DMI_32:
  750. case CAM_CDM_CMD_DMI_64:
  751. if (buf_now > buf_end)
  752. return true;
  753. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI];
  754. break;
  755. case CAM_CDM_CMD_REG_CONT:
  756. p_regcont_cmd = (struct cdm_regcontinuous_cmd *)buf_now;
  757. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
  758. for (i = 0; i < p_regcont_cmd->count; i++) {
  759. if (buf_now > buf_end)
  760. return true;
  761. buf_now++;
  762. }
  763. break;
  764. case CAM_CDM_CMD_REG_RANDOM:
  765. p_regrand_cmd = (struct cdm_regrandom_cmd *)buf_now;
  766. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
  767. for (i = 0; i < p_regrand_cmd->count; i++) {
  768. if (buf_now > buf_end)
  769. return true;
  770. buf_now += 2;
  771. }
  772. break;
  773. case CAM_CDM_CMD_BUFF_INDIRECT:
  774. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT];
  775. if (buf_now > buf_end)
  776. return true;
  777. break;
  778. case CAM_CDM_CMD_GEN_IRQ:
  779. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ];
  780. break;
  781. case CAM_CDM_CMD_WAIT_EVENT:
  782. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT];
  783. break;
  784. case CAM_CDM_CMD_CHANGE_BASE:
  785. if (buf_now > buf_end)
  786. return true;
  787. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE];
  788. break;
  789. case CAM_CDM_CMD_PERF_CTRL:
  790. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL];
  791. break;
  792. case CAM_CDM_CMD_COMP_WAIT:
  793. buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_COMP_WAIT];
  794. break;
  795. default:
  796. CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x",
  797. cmd, *buf_now);
  798. return true;
  799. }
  800. } while (buf_now < cmd_buf_end);
  801. return false;
  802. }
  803. void cam_cdm_util_dump_cmd_buf(
  804. uint32_t *cmd_buf_start, uint32_t *cmd_buf_end)
  805. {
  806. uint32_t *buf_now = cmd_buf_start;
  807. uint32_t *buf_end = cmd_buf_end;
  808. uint32_t cmd = 0;
  809. if (!cmd_buf_start || !cmd_buf_end) {
  810. CAM_ERR(CAM_CDM, "Invalid args");
  811. return;
  812. }
  813. do {
  814. cmd = *buf_now;
  815. cmd = cmd >> CAM_CDM_COMMAND_OFFSET;
  816. switch (cmd) {
  817. case CAM_CDM_CMD_DMI:
  818. case CAM_CDM_CMD_DMI_32:
  819. case CAM_CDM_CMD_DMI_64:
  820. buf_now += cam_cdm_util_dump_dmi_cmd(buf_now,
  821. buf_end);
  822. break;
  823. case CAM_CDM_CMD_REG_CONT:
  824. buf_now += cam_cdm_util_dump_reg_cont_cmd(buf_now,
  825. buf_end);
  826. break;
  827. case CAM_CDM_CMD_REG_RANDOM:
  828. buf_now += cam_cdm_util_dump_reg_random_cmd(buf_now,
  829. buf_end);
  830. break;
  831. case CAM_CDM_CMD_BUFF_INDIRECT:
  832. buf_now += cam_cdm_util_dump_buff_indirect(buf_now,
  833. buf_end);
  834. break;
  835. case CAM_CDM_CMD_GEN_IRQ:
  836. buf_now += cam_cdm_util_dump_gen_irq_cmd(buf_now);
  837. break;
  838. case CAM_CDM_CMD_WAIT_EVENT:
  839. buf_now += cam_cdm_util_dump_wait_event_cmd(buf_now);
  840. break;
  841. case CAM_CDM_CMD_CHANGE_BASE:
  842. buf_now += cam_cdm_util_dump_change_base_cmd(buf_now,
  843. buf_end);
  844. break;
  845. case CAM_CDM_CMD_PERF_CTRL:
  846. buf_now += cam_cdm_util_dump_perf_ctrl_cmd(buf_now);
  847. break;
  848. case CAM_CDM_CMD_COMP_WAIT:
  849. buf_now +=
  850. cam_cdm_util_dump_comp_wait_event_cmd(buf_now);
  851. break;
  852. default:
  853. CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x",
  854. cmd, *buf_now);
  855. buf_now++;
  856. break;
  857. }
  858. } while (buf_now < cmd_buf_end);
  859. }
  860. static uint32_t cam_cdm_util_dump_reg_cont_cmd_v2(
  861. uint32_t *cmd_buf_addr,
  862. struct cam_cdm_cmd_buf_dump_info *dump_info)
  863. {
  864. int i;
  865. long ret;
  866. uint8_t *dst;
  867. size_t remain_len;
  868. uint32_t *temp_ptr = cmd_buf_addr;
  869. uint32_t *addr, *start;
  870. uint32_t min_len;
  871. struct cdm_regcontinuous_cmd *p_regcont_cmd;
  872. struct cam_cdm_cmd_dump_header *hdr;
  873. p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr;
  874. temp_ptr += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT);
  875. ret = cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT);
  876. min_len = (sizeof(uint32_t) * p_regcont_cmd->count) +
  877. sizeof(struct cam_cdm_cmd_dump_header) +
  878. (2 * sizeof(uint32_t));
  879. remain_len = dump_info->dst_max_size - dump_info->dst_offset;
  880. if (remain_len < min_len) {
  881. CAM_WARN_RATE_LIMIT(CAM_CDM,
  882. "Dump buffer exhaust remain %zu min %u",
  883. remain_len, min_len);
  884. return ret;
  885. }
  886. dst = (char *)dump_info->dst_start + dump_info->dst_offset;
  887. hdr = (struct cam_cdm_cmd_dump_header *)dst;
  888. scnprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_CONT:");
  889. hdr->word_size = sizeof(uint32_t);
  890. addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header));
  891. start = addr;
  892. *addr++ = p_regcont_cmd->offset;
  893. *addr++ = p_regcont_cmd->count;
  894. for (i = 0; i < p_regcont_cmd->count; i++) {
  895. *addr = *temp_ptr;
  896. temp_ptr++;
  897. addr++;
  898. ret++;
  899. }
  900. hdr->size = hdr->word_size * (addr - start);
  901. dump_info->dst_offset += hdr->size +
  902. sizeof(struct cam_cdm_cmd_dump_header);
  903. return ret;
  904. }
  905. static uint32_t cam_cdm_util_dump_reg_random_cmd_v2(
  906. uint32_t *cmd_buf_addr,
  907. struct cam_cdm_cmd_buf_dump_info *dump_info)
  908. {
  909. int i;
  910. long ret;
  911. uint8_t *dst;
  912. uint32_t *temp_ptr = cmd_buf_addr;
  913. uint32_t *addr, *start;
  914. size_t remain_len;
  915. uint32_t min_len;
  916. struct cdm_regrandom_cmd *p_regrand_cmd;
  917. struct cam_cdm_cmd_dump_header *hdr;
  918. p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr;
  919. temp_ptr += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
  920. ret = cam_cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
  921. min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) +
  922. sizeof(struct cam_cdm_cmd_dump_header) + sizeof(uint32_t);
  923. remain_len = dump_info->dst_max_size - dump_info->dst_offset;
  924. if (remain_len < min_len) {
  925. CAM_WARN_RATE_LIMIT(CAM_CDM,
  926. "Dump buffer exhaust remain %zu min %u",
  927. remain_len, min_len);
  928. return ret;
  929. }
  930. dst = (char *)dump_info->dst_start + dump_info->dst_offset;
  931. hdr = (struct cam_cdm_cmd_dump_header *)dst;
  932. scnprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_RANDOM:");
  933. hdr->word_size = sizeof(uint32_t);
  934. addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header));
  935. start = addr;
  936. *addr++ = p_regrand_cmd->count;
  937. for (i = 0; i < p_regrand_cmd->count; i++) {
  938. addr[0] = temp_ptr[0] & CAM_CDM_REG_OFFSET_MASK;
  939. addr[1] = temp_ptr[1];
  940. temp_ptr += 2;
  941. addr += 2;
  942. ret += 2;
  943. }
  944. hdr->size = hdr->word_size * (addr - start);
  945. dump_info->dst_offset += hdr->size +
  946. sizeof(struct cam_cdm_cmd_dump_header);
  947. return ret;
  948. }
  949. int cam_cdm_util_dump_cmd_bufs_v2(
  950. struct cam_cdm_cmd_buf_dump_info *dump_info)
  951. {
  952. uint32_t cmd;
  953. uint32_t *buf_now;
  954. int rc = 0;
  955. if (!dump_info || !dump_info->src_start || !dump_info->src_end ||
  956. !dump_info->dst_start) {
  957. CAM_INFO(CAM_CDM, "Invalid args");
  958. return -EINVAL;
  959. }
  960. buf_now = dump_info->src_start;
  961. do {
  962. if (dump_info->dst_offset >= dump_info->dst_max_size) {
  963. CAM_WARN(CAM_CDM,
  964. "Dump overshoot offset %zu size %zu",
  965. dump_info->dst_offset,
  966. dump_info->dst_max_size);
  967. return -ENOSPC;
  968. }
  969. cmd = *buf_now;
  970. cmd = cmd >> CAM_CDM_COMMAND_OFFSET;
  971. switch (cmd) {
  972. case CAM_CDM_CMD_DMI:
  973. case CAM_CDM_CMD_DMI_32:
  974. case CAM_CDM_CMD_DMI_64:
  975. buf_now += cam_cdm_get_cmd_header_size(CAM_CDM_CMD_DMI);
  976. break;
  977. case CAM_CDM_CMD_REG_CONT:
  978. buf_now += cam_cdm_util_dump_reg_cont_cmd_v2(buf_now,
  979. dump_info);
  980. break;
  981. case CAM_CDM_CMD_REG_RANDOM:
  982. buf_now += cam_cdm_util_dump_reg_random_cmd_v2(buf_now,
  983. dump_info);
  984. break;
  985. case CAM_CDM_CMD_BUFF_INDIRECT:
  986. buf_now += cam_cdm_get_cmd_header_size(
  987. CAM_CDM_CMD_BUFF_INDIRECT);
  988. break;
  989. case CAM_CDM_CMD_GEN_IRQ:
  990. buf_now += cam_cdm_get_cmd_header_size(
  991. CAM_CDM_CMD_GEN_IRQ);
  992. break;
  993. case CAM_CDM_CMD_WAIT_EVENT:
  994. buf_now += cam_cdm_get_cmd_header_size(
  995. CAM_CDM_CMD_WAIT_EVENT);
  996. break;
  997. case CAM_CDM_CMD_CHANGE_BASE:
  998. buf_now += cam_cdm_get_cmd_header_size(
  999. CAM_CDM_CMD_CHANGE_BASE);
  1000. break;
  1001. case CAM_CDM_CMD_PERF_CTRL:
  1002. buf_now += cam_cdm_get_cmd_header_size(
  1003. CAM_CDM_CMD_PERF_CTRL);
  1004. break;
  1005. case CAM_CDM_CMD_COMP_WAIT:
  1006. buf_now += cam_cdm_get_cmd_header_size(
  1007. CAM_CDM_CMD_COMP_WAIT);
  1008. break;
  1009. default:
  1010. CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x", cmd);
  1011. buf_now++;
  1012. break;
  1013. }
  1014. } while (buf_now < dump_info->src_end);
  1015. return rc;
  1016. }