cam_cpas_intf.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721
  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/of.h>
  7. #include <linux/module.h>
  8. #include <linux/kernel.h>
  9. #include <linux/platform_device.h>
  10. #include <media/v4l2-event.h>
  11. #include <media/v4l2-ioctl.h>
  12. #include <media/v4l2-subdev.h>
  13. #include <media/cam_cpas.h>
  14. #include <media/cam_req_mgr.h>
  15. #include <dt-bindings/msm-camera.h>
  16. #include "cam_subdev.h"
  17. #include "cam_cpas_hw_intf.h"
  18. #include "cam_cpas_soc.h"
  19. #include "cam_cpastop_hw.h"
  20. #include "camera_main.h"
  21. #include "cam_cpas_hw.h"
  22. #include <linux/soc/qcom/llcc-qcom.h>
  23. #include "cam_req_mgr_interface.h"
  24. #ifdef CONFIG_DYNAMIC_FD_PORT_CONFIG
  25. #include <linux/IClientEnv.h>
  26. #include <linux/ITrustedCameraDriver.h>
  27. #include <linux/CTrustedCameraDriver.h>
  28. #define CAM_CPAS_ERROR_NOT_ALLOWED 10
  29. #endif
  30. #define CAM_CPAS_DEV_NAME "cam-cpas"
  31. #define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done)
  32. /**
  33. * struct cam_cpas_intf : CPAS interface
  34. *
  35. * @pdev: Platform device
  36. * @subdev: Subdev info
  37. * @hw_intf: CPAS HW interface
  38. * @hw_caps: CPAS HW capabilities
  39. * @intf_lock: CPAS interface mutex
  40. * @open_cnt: CPAS subdev open count
  41. * @probe_done: Whether CPAS prove completed
  42. *
  43. */
  44. struct cam_cpas_intf {
  45. struct platform_device *pdev;
  46. struct cam_subdev subdev;
  47. struct cam_hw_intf *hw_intf;
  48. struct cam_cpas_hw_caps hw_caps;
  49. struct mutex intf_lock;
  50. uint32_t open_cnt;
  51. bool probe_done;
  52. };
  53. static struct cam_cpas_intf *g_cpas_intf;
  54. const char *cam_cpas_axi_util_path_type_to_string(
  55. uint32_t path_data_type)
  56. {
  57. switch (path_data_type) {
  58. /* IFE Paths */
  59. case CAM_AXI_PATH_DATA_IFE_LINEAR:
  60. return "IFE_LINEAR";
  61. case CAM_AXI_PATH_DATA_IFE_VID:
  62. return "IFE_VID";
  63. case CAM_AXI_PATH_DATA_IFE_DISP:
  64. return "IFE_DISP";
  65. case CAM_AXI_PATH_DATA_IFE_STATS:
  66. return "IFE_STATS";
  67. case CAM_AXI_PATH_DATA_IFE_RDI0:
  68. return "IFE_RDI0";
  69. case CAM_AXI_PATH_DATA_IFE_RDI1:
  70. return "IFE_RDI1";
  71. case CAM_AXI_PATH_DATA_IFE_RDI2:
  72. return "IFE_RDI2";
  73. case CAM_AXI_PATH_DATA_IFE_RDI3:
  74. return "IFE_RDI3";
  75. case CAM_AXI_PATH_DATA_IFE_PDAF:
  76. return "IFE_PDAF";
  77. case CAM_AXI_PATH_DATA_IFE_PIXEL_RAW:
  78. return "IFE_PIXEL_RAW";
  79. /* IPE Paths */
  80. case CAM_AXI_PATH_DATA_IPE_RD_IN:
  81. return "IPE_RD_IN";
  82. case CAM_AXI_PATH_DATA_IPE_RD_REF:
  83. return "IPE_RD_REF";
  84. case CAM_AXI_PATH_DATA_IPE_WR_VID:
  85. return "IPE_WR_VID";
  86. case CAM_AXI_PATH_DATA_IPE_WR_DISP:
  87. return "IPE_WR_DISP";
  88. case CAM_AXI_PATH_DATA_IPE_WR_REF:
  89. return "IPE_WR_REF";
  90. case CAM_AXI_PATH_DATA_IPE_WR_APP:
  91. return "IPE_WR_APP";
  92. /* OPE Paths */
  93. case CAM_AXI_PATH_DATA_OPE_RD_IN:
  94. return "OPE_RD_IN";
  95. case CAM_AXI_PATH_DATA_OPE_RD_REF:
  96. return "OPE_RD_REF";
  97. case CAM_AXI_PATH_DATA_OPE_WR_VID:
  98. return "OPE_WR_VID";
  99. case CAM_AXI_PATH_DATA_OPE_WR_DISP:
  100. return "OPE_WR_DISP";
  101. case CAM_AXI_PATH_DATA_OPE_WR_REF:
  102. return "OPE_WR_REF";
  103. /* SFE Paths */
  104. case CAM_AXI_PATH_DATA_SFE_NRDI:
  105. return "SFE_NRDI";
  106. case CAM_AXI_PATH_DATA_SFE_RDI0:
  107. return "SFE_RDI0";
  108. case CAM_AXI_PATH_DATA_SFE_RDI1:
  109. return "SFE_RDI1";
  110. case CAM_AXI_PATH_DATA_SFE_RDI2:
  111. return "SFE_RDI2";
  112. case CAM_AXI_PATH_DATA_SFE_RDI3:
  113. return "SFE_RDI3";
  114. case CAM_AXI_PATH_DATA_SFE_RDI4:
  115. return "SFE_RDI4";
  116. case CAM_AXI_PATH_DATA_SFE_STATS:
  117. return "SFE_STATS";
  118. case CAM_AXI_PATH_DATA_CRE_RD_IN:
  119. return "CRE_RD_IN";
  120. case CAM_AXI_PATH_DATA_CRE_WR_OUT:
  121. return "CRE_WR_OUT";
  122. /* OFE Paths */
  123. case CAM_AXI_PATH_DATA_OFE_RD_EXT:
  124. return "OFE_RD_EXT";
  125. case CAM_AXI_PATH_DATA_OFE_RD_INT_PDI:
  126. return "OFE_RD_INT_PDI";
  127. case CAM_AXI_PATH_DATA_OFE_RD_INT_HDR:
  128. return "OFE_RD_INT_HDR";
  129. case CAM_AXI_PATH_DATA_OFE_WR_VID:
  130. return "OFE_WR_VID";
  131. case CAM_AXI_PATH_DATA_OFE_WR_DISP:
  132. return "OFE_WR_DISP";
  133. case CAM_AXI_PATH_DATA_OFE_WR_IR:
  134. return "OFE_WR_IR";
  135. case CAM_AXI_PATH_DATA_OFE_WR_HDR_LTM:
  136. return "OFE_WR_HDR_LTM";
  137. case CAM_AXI_PATH_DATA_OFE_WR_DC4:
  138. return "OFE_WR_DC4";
  139. case CAM_AXI_PATH_DATA_OFE_WR_AI:
  140. return "OFE_WR_AI";
  141. case CAM_AXI_PATH_DATA_OFE_WR_PDI:
  142. return "OFE_WR_PDI";
  143. case CAM_AXI_PATH_DATA_OFE_WR_IDEALRAW:
  144. return "OFE_WR_IDEALRAW";
  145. case CAM_AXI_PATH_DATA_OFE_WR_STATS:
  146. return "OFE_WR_STATS";
  147. /* Common Paths */
  148. case CAM_AXI_PATH_DATA_ALL:
  149. return "DATA_ALL";
  150. default:
  151. return "CPAS_PATH_INVALID";
  152. }
  153. }
  154. EXPORT_SYMBOL(cam_cpas_axi_util_path_type_to_string);
  155. const char *cam_cpas_axi_util_trans_type_to_string(
  156. uint32_t transac_type)
  157. {
  158. switch (transac_type) {
  159. case CAM_AXI_TRANSACTION_READ:
  160. return "TRANSAC_READ";
  161. case CAM_AXI_TRANSACTION_WRITE:
  162. return "TRANSAC_WRITE";
  163. default:
  164. return "TRANSAC_INVALID";
  165. }
  166. }
  167. EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string);
  168. const char *cam_cpas_axi_util_drv_vote_lvl_to_string(
  169. uint32_t vote_lvl)
  170. {
  171. switch (vote_lvl) {
  172. case CAM_CPAS_VOTE_LEVEL_LOW:
  173. return "VOTE_LVL_LOW";
  174. case CAM_CPAS_VOTE_LEVEL_HIGH:
  175. return "VOTE_LVL_HIGH";
  176. default:
  177. return "VOTE_LVL_INVALID";
  178. }
  179. }
  180. EXPORT_SYMBOL(cam_cpas_axi_util_drv_vote_lvl_to_string);
  181. const char *cam_cpas_util_vote_type_to_string(enum cam_cpas_vote_type vote_type)
  182. {
  183. switch (vote_type) {
  184. case CAM_CPAS_VOTE_TYPE_HLOS:
  185. return "VOTE_TYPE_HLOS";
  186. case CAM_CPAS_VOTE_TYPE_DRV:
  187. return "VOTE_TYPE_DRV";
  188. default:
  189. return "VOTE_TYPE_INVALID";
  190. }
  191. }
  192. EXPORT_SYMBOL(cam_cpas_util_vote_type_to_string);
  193. int cam_cpas_query_drv_enable(bool *is_ddr_drv_enabled, bool *is_clk_drv_enabled)
  194. {
  195. struct cam_hw_info *cpas_hw = NULL;
  196. struct cam_cpas_private_soc *soc_private = NULL;
  197. if (!CAM_CPAS_INTF_INITIALIZED()) {
  198. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  199. return -ENODEV;
  200. }
  201. if (!is_ddr_drv_enabled && !is_clk_drv_enabled) {
  202. CAM_ERR(CAM_CPAS, "invalid input ddr: %pK clk: %pK", is_ddr_drv_enabled,
  203. is_clk_drv_enabled);
  204. return -EINVAL;
  205. }
  206. cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
  207. soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  208. if (is_ddr_drv_enabled)
  209. *is_ddr_drv_enabled = soc_private->enable_cam_ddr_drv;
  210. if (is_clk_drv_enabled)
  211. *is_clk_drv_enabled = soc_private->enable_cam_clk_drv;
  212. return 0;
  213. }
  214. EXPORT_SYMBOL(cam_cpas_query_drv_enable);
  215. int cam_cpas_csid_process_resume(uint32_t csid_idx)
  216. {
  217. int rc;
  218. if (!CAM_CPAS_INTF_INITIALIZED()) {
  219. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  220. return -ENODEV;
  221. }
  222. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  223. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  224. g_cpas_intf->hw_intf->hw_priv,
  225. CAM_CPAS_HW_CMD_CSID_PROCESS_RESUME, &csid_idx,
  226. sizeof(uint32_t));
  227. if (rc)
  228. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  229. } else {
  230. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  231. rc = -EINVAL;
  232. }
  233. return rc;
  234. }
  235. EXPORT_SYMBOL(cam_cpas_csid_process_resume);
  236. int cam_cpas_csid_input_core_info_update(int csid_idx, int sfe_idx, bool set_port)
  237. {
  238. int rc;
  239. if (!CAM_CPAS_INTF_INITIALIZED()) {
  240. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  241. return -ENODEV;
  242. }
  243. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  244. struct cam_cpas_hw_cmd_csid_input_core_info_update core_info_update;
  245. core_info_update.csid_idx = csid_idx;
  246. core_info_update.sfe_idx = sfe_idx;
  247. core_info_update.set_port = set_port;
  248. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  249. g_cpas_intf->hw_intf->hw_priv,
  250. CAM_CPAS_HW_CMD_CSID_INPUT_CORE_INFO_UPDATE, &core_info_update,
  251. sizeof(core_info_update));
  252. if (rc)
  253. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  254. } else {
  255. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  256. rc = -EINVAL;
  257. }
  258. return rc;
  259. }
  260. EXPORT_SYMBOL(cam_cpas_csid_input_core_info_update);
  261. int cam_cpas_dump_camnoc_buff_fill_info(uint32_t client_handle)
  262. {
  263. int rc;
  264. if (!CAM_CPAS_INTF_INITIALIZED()) {
  265. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  266. return -ENODEV;
  267. }
  268. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  269. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  270. g_cpas_intf->hw_intf->hw_priv,
  271. CAM_CPAS_HW_CMD_DUMP_BUFF_FILL_INFO, &client_handle,
  272. sizeof(uint32_t));
  273. if (rc)
  274. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  275. } else {
  276. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  277. rc = -EINVAL;
  278. }
  279. return rc;
  280. }
  281. EXPORT_SYMBOL(cam_cpas_dump_camnoc_buff_fill_info);
  282. bool cam_cpas_is_part_supported(uint32_t flag, uint32_t hw_map, uint32_t part_info)
  283. {
  284. int32_t i;
  285. struct cam_hw_info *cpas_hw = g_cpas_intf->hw_intf->hw_priv;
  286. struct cam_cpas *cpas_core = NULL;
  287. struct cam_cpas_subpart_info *cam_subpart_info = NULL;
  288. mutex_lock(&cpas_hw->hw_mutex);
  289. cpas_core = cpas_hw->core_info;
  290. cam_subpart_info = cpas_core->cam_subpart_info;
  291. if (!cam_subpart_info) {
  292. CAM_DBG(CAM_CPAS, "Invalid address of cam_subpart_info");
  293. mutex_unlock(&cpas_hw->hw_mutex);
  294. return true;
  295. }
  296. for (i = 0; i < cam_subpart_info->num_bits; i++) {
  297. if ((cam_subpart_info->hw_bitmap_mask[i][0] == flag) &&
  298. (cam_subpart_info->hw_bitmap_mask[i][1] == hw_map)) {
  299. CAM_DBG(CAM_CPAS, "flag: %u hw_map: %u part_info:0x%x",
  300. flag, hw_map, part_info);
  301. mutex_unlock(&cpas_hw->hw_mutex);
  302. return ((part_info & BIT(i)) == 0);
  303. }
  304. }
  305. mutex_unlock(&cpas_hw->hw_mutex);
  306. return true;
  307. }
  308. bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
  309. uint32_t *fuse_val)
  310. {
  311. struct cam_hw_info *cpas_hw = NULL;
  312. struct cam_cpas_private_soc *soc_private = NULL;
  313. bool supported = true;
  314. int32_t i;
  315. if (!CAM_CPAS_INTF_INITIALIZED()) {
  316. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  317. return false;
  318. }
  319. cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
  320. soc_private =
  321. (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
  322. if (flag >= CAM_CPAS_FUSE_FEATURE_MAX) {
  323. CAM_ERR(CAM_CPAS, "Unknown feature flag %x", flag);
  324. return false;
  325. }
  326. supported = cam_cpas_is_part_supported(flag, hw_map, soc_private->part_info);
  327. for (i = 0; i < soc_private->num_feature_info; i++)
  328. if (soc_private->feature_info[i].feature == flag)
  329. break;
  330. if (i == soc_private->num_feature_info)
  331. goto end;
  332. if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE
  333. || (soc_private->feature_info[i].type ==
  334. CAM_CPAS_FEATURE_TYPE_ENABLE)) {
  335. if ((soc_private->feature_info[i].hw_map & hw_map) == hw_map) {
  336. if (!(supported && soc_private->feature_info[i].enable))
  337. supported = false;
  338. }
  339. } else {
  340. if (!fuse_val) {
  341. CAM_ERR(CAM_CPAS,
  342. "Invalid arg fuse_val");
  343. } else {
  344. *fuse_val = soc_private->feature_info[i].value;
  345. }
  346. }
  347. end:
  348. return supported;
  349. }
  350. EXPORT_SYMBOL(cam_cpas_is_feature_supported);
  351. int cam_cpas_get_cpas_hw_version(uint32_t *hw_version)
  352. {
  353. struct cam_hw_info *cpas_hw = NULL;
  354. if (!CAM_CPAS_INTF_INITIALIZED()) {
  355. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  356. return -ENODEV;
  357. }
  358. if (!hw_version) {
  359. CAM_ERR(CAM_CPAS, "invalid input %pK", hw_version);
  360. return -EINVAL;
  361. }
  362. cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
  363. *hw_version = cpas_hw->soc_info.hw_version;
  364. if (*hw_version == CAM_CPAS_TITAN_NONE) {
  365. CAM_DBG(CAM_CPAS, "Didn't find a valid HW Version %d",
  366. *hw_version);
  367. }
  368. return 0;
  369. }
  370. int cam_cpas_get_hw_info(uint32_t *camera_family,
  371. struct cam_hw_version *camera_version,
  372. struct cam_hw_version *cpas_version,
  373. uint32_t **cam_caps, uint32_t *num_cap_mask,
  374. struct cam_cpas_fuse_info *cam_fuse_info,
  375. struct cam_cpas_domain_id_caps *domain_id_info)
  376. {
  377. struct cam_hw_info *cpas_hw;
  378. struct cam_cpas_private_soc *soc_private;
  379. struct cam_cpas_domain_id_info cpas_domain_id;
  380. int i;
  381. if (!CAM_CPAS_INTF_INITIALIZED()) {
  382. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  383. return -ENODEV;
  384. }
  385. if (!camera_family || !camera_version || !cpas_version || !cam_caps || !num_cap_mask) {
  386. CAM_ERR(CAM_CPAS, "invalid input %pK %pK %pK %pK %pK",
  387. camera_family, camera_version, cpas_version, cam_caps, num_cap_mask);
  388. return -EINVAL;
  389. }
  390. cpas_hw = g_cpas_intf->hw_intf->hw_priv;
  391. soc_private = (struct cam_cpas_private_soc *)
  392. cpas_hw->soc_info.soc_private;
  393. *camera_family = g_cpas_intf->hw_caps.camera_family;
  394. *camera_version = g_cpas_intf->hw_caps.camera_version;
  395. *cpas_version = g_cpas_intf->hw_caps.cpas_version;
  396. *cam_caps = g_cpas_intf->hw_caps.camera_capability;
  397. *num_cap_mask = g_cpas_intf->hw_caps.num_capability_reg;
  398. if (cam_fuse_info)
  399. *cam_fuse_info = g_cpas_intf->hw_caps.fuse_info;
  400. if (domain_id_info) {
  401. cpas_domain_id = soc_private->domain_id_info;
  402. if (!soc_private->domain_id_info.domain_id_supported) {
  403. domain_id_info->num_mapping = 0;
  404. domain_id_info->is_supported = 0;
  405. } else {
  406. domain_id_info->is_supported = 1;
  407. domain_id_info->num_mapping =
  408. soc_private->domain_id_info.num_domain_ids;
  409. for (i = 0; i < domain_id_info->num_mapping; i++) {
  410. domain_id_info->entries[i].domain_type =
  411. cpas_domain_id.domain_id_entries[i].domain_type;
  412. domain_id_info->entries[i].mapping_id =
  413. cpas_domain_id.domain_id_entries[i].mapping_id;
  414. }
  415. }
  416. }
  417. CAM_DBG(CAM_CPAS, "Family %d, version %d.%d cam_caps %d, domain_id: %s",
  418. *camera_family, camera_version->major,
  419. camera_version->minor, *cam_caps,
  420. CAM_BOOL_TO_YESNO(soc_private->domain_id_info.domain_id_supported));
  421. return 0;
  422. }
  423. EXPORT_SYMBOL(cam_cpas_get_hw_info);
  424. static inline enum cam_cpas_reg_base __cam_cpas_get_internal_reg_base(
  425. enum cam_cpas_regbase_types reg_base)
  426. {
  427. switch (reg_base) {
  428. case CAM_CPAS_REGBASE_CPASTOP:
  429. return CAM_CPAS_REG_CPASTOP;
  430. default:
  431. return CAM_CPAS_REG_MAX;
  432. }
  433. }
  434. int cam_cpas_reg_write(uint32_t client_handle, enum cam_cpas_regbase_types reg_base,
  435. uint32_t offset, bool mb, uint32_t value)
  436. {
  437. int rc;
  438. if (!CAM_CPAS_INTF_INITIALIZED()) {
  439. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  440. return -ENODEV;
  441. }
  442. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  443. struct cam_cpas_hw_cmd_reg_read_write cmd_reg_write;
  444. enum cam_cpas_reg_base internal_reg_base;
  445. internal_reg_base = __cam_cpas_get_internal_reg_base(reg_base);
  446. if (internal_reg_base >= CAM_CPAS_REG_MAX) {
  447. CAM_ERR(CAM_CPAS, "Invalid reg base: %d for write ops client: %u",
  448. reg_base, client_handle);
  449. return -EINVAL;
  450. }
  451. cmd_reg_write.client_handle = client_handle;
  452. cmd_reg_write.reg_base = internal_reg_base;
  453. cmd_reg_write.offset = offset;
  454. cmd_reg_write.value = value;
  455. cmd_reg_write.mb = mb;
  456. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  457. g_cpas_intf->hw_intf->hw_priv,
  458. CAM_CPAS_HW_CMD_REG_WRITE, &cmd_reg_write,
  459. sizeof(struct cam_cpas_hw_cmd_reg_read_write));
  460. if (rc)
  461. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  462. } else {
  463. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  464. rc = -EINVAL;
  465. }
  466. return rc;
  467. }
  468. EXPORT_SYMBOL(cam_cpas_reg_write);
  469. int cam_cpas_reg_read(uint32_t client_handle, enum cam_cpas_regbase_types reg_base,
  470. uint32_t offset, bool mb, uint32_t *value)
  471. {
  472. int rc;
  473. if (!CAM_CPAS_INTF_INITIALIZED()) {
  474. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  475. return -ENODEV;
  476. }
  477. if (!value) {
  478. CAM_ERR(CAM_CPAS, "Invalid arg value");
  479. return -EINVAL;
  480. }
  481. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  482. struct cam_cpas_hw_cmd_reg_read_write cmd_reg_read;
  483. enum cam_cpas_reg_base internal_reg_base;
  484. internal_reg_base = __cam_cpas_get_internal_reg_base(reg_base);
  485. if (internal_reg_base >= CAM_CPAS_REG_MAX) {
  486. CAM_ERR(CAM_CPAS, "Invalid reg base: %d for read ops client: %u",
  487. reg_base, client_handle);
  488. return -EINVAL;
  489. }
  490. cmd_reg_read.client_handle = client_handle;
  491. cmd_reg_read.reg_base = internal_reg_base;
  492. cmd_reg_read.offset = offset;
  493. cmd_reg_read.mb = mb;
  494. cmd_reg_read.value = 0;
  495. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  496. g_cpas_intf->hw_intf->hw_priv,
  497. CAM_CPAS_HW_CMD_REG_READ, &cmd_reg_read,
  498. sizeof(struct cam_cpas_hw_cmd_reg_read_write));
  499. if (rc) {
  500. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  501. return rc;
  502. }
  503. *value = cmd_reg_read.value;
  504. } else {
  505. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  506. rc = -EINVAL;
  507. }
  508. return rc;
  509. }
  510. EXPORT_SYMBOL(cam_cpas_reg_read);
  511. int cam_cpas_update_axi_vote(uint32_t client_handle,
  512. struct cam_axi_vote *axi_vote)
  513. {
  514. int rc;
  515. if (!CAM_CPAS_INTF_INITIALIZED()) {
  516. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  517. return -ENODEV;
  518. }
  519. if (!axi_vote) {
  520. CAM_ERR(CAM_CPAS, "NULL axi vote");
  521. return -EINVAL;
  522. }
  523. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  524. struct cam_cpas_hw_cmd_axi_vote cmd_axi_vote;
  525. cmd_axi_vote.client_handle = client_handle;
  526. cmd_axi_vote.axi_vote = axi_vote;
  527. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  528. g_cpas_intf->hw_intf->hw_priv,
  529. CAM_CPAS_HW_CMD_AXI_VOTE, &cmd_axi_vote,
  530. sizeof(struct cam_cpas_hw_cmd_axi_vote));
  531. if (rc)
  532. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  533. } else {
  534. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  535. rc = -EINVAL;
  536. }
  537. return rc;
  538. }
  539. EXPORT_SYMBOL(cam_cpas_update_axi_vote);
  540. int cam_cpas_update_ahb_vote(uint32_t client_handle,
  541. struct cam_ahb_vote *ahb_vote)
  542. {
  543. int rc;
  544. if (!CAM_CPAS_INTF_INITIALIZED()) {
  545. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  546. return -ENODEV;
  547. }
  548. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  549. struct cam_cpas_hw_cmd_ahb_vote cmd_ahb_vote;
  550. cmd_ahb_vote.client_handle = client_handle;
  551. cmd_ahb_vote.ahb_vote = ahb_vote;
  552. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  553. g_cpas_intf->hw_intf->hw_priv,
  554. CAM_CPAS_HW_CMD_AHB_VOTE, &cmd_ahb_vote,
  555. sizeof(struct cam_cpas_hw_cmd_ahb_vote));
  556. if (rc)
  557. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  558. } else {
  559. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  560. rc = -EINVAL;
  561. }
  562. return rc;
  563. }
  564. EXPORT_SYMBOL(cam_cpas_update_ahb_vote);
  565. int cam_cpas_stop(uint32_t client_handle)
  566. {
  567. int rc;
  568. if (!CAM_CPAS_INTF_INITIALIZED()) {
  569. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  570. return -ENODEV;
  571. }
  572. if (g_cpas_intf->hw_intf->hw_ops.stop) {
  573. struct cam_cpas_hw_cmd_stop cmd_hw_stop;
  574. cmd_hw_stop.client_handle = client_handle;
  575. rc = g_cpas_intf->hw_intf->hw_ops.stop(
  576. g_cpas_intf->hw_intf->hw_priv, &cmd_hw_stop,
  577. sizeof(struct cam_cpas_hw_cmd_stop));
  578. if (rc)
  579. CAM_ERR(CAM_CPAS, "Failed in stop, rc=%d", rc);
  580. } else {
  581. CAM_ERR(CAM_CPAS, "Invalid stop ops");
  582. rc = -EINVAL;
  583. }
  584. return rc;
  585. }
  586. EXPORT_SYMBOL(cam_cpas_stop);
  587. int cam_cpas_start(uint32_t client_handle,
  588. struct cam_ahb_vote *ahb_vote, struct cam_axi_vote *axi_vote)
  589. {
  590. int rc;
  591. if (!CAM_CPAS_INTF_INITIALIZED()) {
  592. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  593. return -ENODEV;
  594. }
  595. if (!axi_vote) {
  596. CAM_ERR(CAM_CPAS, "NULL axi vote");
  597. return -EINVAL;
  598. }
  599. if (g_cpas_intf->hw_intf->hw_ops.start) {
  600. struct cam_cpas_hw_cmd_start cmd_hw_start;
  601. cmd_hw_start.client_handle = client_handle;
  602. cmd_hw_start.ahb_vote = ahb_vote;
  603. cmd_hw_start.axi_vote = axi_vote;
  604. rc = g_cpas_intf->hw_intf->hw_ops.start(
  605. g_cpas_intf->hw_intf->hw_priv, &cmd_hw_start,
  606. sizeof(struct cam_cpas_hw_cmd_start));
  607. if (rc)
  608. CAM_ERR(CAM_CPAS, "Failed in start, rc=%d", rc);
  609. } else {
  610. CAM_ERR(CAM_CPAS, "Invalid start ops");
  611. rc = -EINVAL;
  612. }
  613. return rc;
  614. }
  615. EXPORT_SYMBOL(cam_cpas_start);
  616. void cam_cpas_log_votes(bool ddr_only)
  617. {
  618. int rc;
  619. if (!CAM_CPAS_INTF_INITIALIZED()) {
  620. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  621. return;
  622. }
  623. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  624. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  625. g_cpas_intf->hw_intf->hw_priv,
  626. CAM_CPAS_HW_CMD_LOG_VOTE, &ddr_only,
  627. sizeof(ddr_only));
  628. if (rc)
  629. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  630. } else {
  631. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  632. }
  633. }
  634. EXPORT_SYMBOL(cam_cpas_log_votes);
  635. int cam_cpas_select_qos_settings(uint32_t selection_mask)
  636. {
  637. int rc = 0;
  638. if (!CAM_CPAS_INTF_INITIALIZED()) {
  639. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  640. return -EBADR;
  641. }
  642. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  643. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  644. g_cpas_intf->hw_intf->hw_priv,
  645. CAM_CPAS_HW_CMD_SELECT_QOS, &selection_mask,
  646. sizeof(selection_mask));
  647. if (rc)
  648. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  649. } else {
  650. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  651. rc = -EBADR;
  652. }
  653. return rc;
  654. }
  655. EXPORT_SYMBOL(cam_cpas_select_qos_settings);
  656. int cam_cpas_enable_tpg_mux_sel(uint32_t tpg_mux_sel)
  657. {
  658. int rc = 0;
  659. if (!CAM_CPAS_INTF_INITIALIZED()) {
  660. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  661. return -EBADR;
  662. }
  663. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  664. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  665. g_cpas_intf->hw_intf->hw_priv,
  666. CAM_CPAS_HW_CMD_TPG_MUX_SEL, &tpg_mux_sel,
  667. sizeof(tpg_mux_sel));
  668. if (rc)
  669. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  670. } else {
  671. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  672. rc = -EBADR;
  673. }
  674. return rc;
  675. }
  676. EXPORT_SYMBOL(cam_cpas_enable_tpg_mux_sel);
  677. int cam_cpas_notify_event(const char *identifier_string,
  678. int32_t identifier_value)
  679. {
  680. int rc = 0;
  681. if (!CAM_CPAS_INTF_INITIALIZED()) {
  682. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  683. return -EBADR;
  684. }
  685. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  686. struct cam_cpas_hw_cmd_notify_event event = { 0 };
  687. event.identifier_string = identifier_string;
  688. event.identifier_value = identifier_value;
  689. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  690. g_cpas_intf->hw_intf->hw_priv,
  691. CAM_CPAS_HW_CMD_LOG_EVENT, &event,
  692. sizeof(event));
  693. if (rc)
  694. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  695. } else {
  696. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  697. rc = -EBADR;
  698. }
  699. return rc;
  700. }
  701. EXPORT_SYMBOL(cam_cpas_notify_event);
  702. int cam_cpas_unregister_client(uint32_t client_handle)
  703. {
  704. int rc;
  705. if (!CAM_CPAS_INTF_INITIALIZED()) {
  706. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  707. return -ENODEV;
  708. }
  709. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  710. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  711. g_cpas_intf->hw_intf->hw_priv,
  712. CAM_CPAS_HW_CMD_UNREGISTER_CLIENT,
  713. &client_handle, sizeof(uint32_t));
  714. if (rc)
  715. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  716. } else {
  717. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  718. rc = -EINVAL;
  719. }
  720. return rc;
  721. }
  722. EXPORT_SYMBOL(cam_cpas_unregister_client);
  723. int cam_cpas_register_client(
  724. struct cam_cpas_register_params *register_params)
  725. {
  726. int rc;
  727. if (!CAM_CPAS_INTF_INITIALIZED()) {
  728. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  729. return -ENODEV;
  730. }
  731. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  732. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  733. g_cpas_intf->hw_intf->hw_priv,
  734. CAM_CPAS_HW_CMD_REGISTER_CLIENT, register_params,
  735. sizeof(struct cam_cpas_register_params));
  736. if (rc)
  737. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  738. } else {
  739. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  740. rc = -EINVAL;
  741. }
  742. return rc;
  743. }
  744. EXPORT_SYMBOL(cam_cpas_register_client);
  745. int cam_cpas_get_scid(
  746. enum cam_sys_cache_config_types type)
  747. {
  748. int rc;
  749. if (!CAM_CPAS_INTF_INITIALIZED()) {
  750. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  751. return -ENODEV;
  752. }
  753. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  754. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  755. g_cpas_intf->hw_intf->hw_priv,
  756. CAM_CPAS_HW_CMD_GET_SCID, &type,
  757. sizeof(type));
  758. } else {
  759. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  760. rc = -EINVAL;
  761. }
  762. return rc;
  763. }
  764. EXPORT_SYMBOL(cam_cpas_get_scid);
  765. int cam_cpas_prepare_subpart_info(enum cam_subparts_index idx, uint32_t num_subpart_available,
  766. uint32_t num_subpart_functional)
  767. {
  768. struct cam_hw_info *cpas_hw = NULL;
  769. struct cam_cpas_private_soc *soc_private = NULL;
  770. if (!CAM_CPAS_INTF_INITIALIZED()) {
  771. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  772. return -ENODEV;
  773. }
  774. cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
  775. mutex_lock(&cpas_hw->hw_mutex);
  776. soc_private = (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
  777. if (!soc_private) {
  778. CAM_ERR(CAM_CPAS, "Invalid soc_private: 0x%x", soc_private);
  779. mutex_unlock(&cpas_hw->hw_mutex);
  780. return -EINVAL;
  781. }
  782. switch (idx) {
  783. case CAM_IFE_HW_IDX:
  784. soc_private->sysfs_info.num_ifes[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
  785. num_subpart_available;
  786. soc_private->sysfs_info.num_ifes[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
  787. num_subpart_functional;
  788. break;
  789. case CAM_IFE_LITE_HW_IDX:
  790. soc_private->sysfs_info.num_ife_lites[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
  791. num_subpart_available;
  792. soc_private->sysfs_info.num_ife_lites[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
  793. num_subpart_functional;
  794. break;
  795. case CAM_SFE_HW_IDX:
  796. soc_private->sysfs_info.num_sfes[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
  797. num_subpart_available;
  798. soc_private->sysfs_info.num_sfes[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
  799. num_subpart_functional;
  800. break;
  801. case CAM_CUSTOM_HW_IDX:
  802. soc_private->sysfs_info.num_custom[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
  803. num_subpart_available;
  804. soc_private->sysfs_info.num_custom[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
  805. num_subpart_functional;
  806. break;
  807. default:
  808. CAM_ERR(CAM_CPAS, "Invalid camera subpart index : %d", idx);
  809. mutex_unlock(&cpas_hw->hw_mutex);
  810. return -EINVAL;
  811. }
  812. mutex_unlock(&cpas_hw->hw_mutex);
  813. return 0;
  814. }
  815. EXPORT_SYMBOL(cam_cpas_prepare_subpart_info);
  816. int cam_cpas_activate_llcc(
  817. enum cam_sys_cache_config_types type)
  818. {
  819. int rc;
  820. if (!CAM_CPAS_INTF_INITIALIZED()) {
  821. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  822. return -ENODEV;
  823. }
  824. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  825. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  826. g_cpas_intf->hw_intf->hw_priv,
  827. CAM_CPAS_HW_CMD_ACTIVATE_LLC, &type,
  828. sizeof(type));
  829. if (rc)
  830. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  831. } else {
  832. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  833. rc = -EINVAL;
  834. }
  835. return rc;
  836. }
  837. EXPORT_SYMBOL(cam_cpas_activate_llcc);
  838. int cam_cpas_deactivate_llcc(
  839. enum cam_sys_cache_config_types type)
  840. {
  841. int rc;
  842. if (!CAM_CPAS_INTF_INITIALIZED()) {
  843. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  844. return -ENODEV;
  845. }
  846. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  847. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  848. g_cpas_intf->hw_intf->hw_priv,
  849. CAM_CPAS_HW_CMD_DEACTIVATE_LLC, &type,
  850. sizeof(type));
  851. if (rc)
  852. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  853. } else {
  854. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  855. rc = -EINVAL;
  856. }
  857. return rc;
  858. }
  859. EXPORT_SYMBOL(cam_cpas_deactivate_llcc);
  860. int cam_cpas_configure_staling_llcc(
  861. enum cam_sys_cache_config_types type,
  862. enum cam_sys_cache_llcc_staling_mode mode_param,
  863. enum cam_sys_cache_llcc_staling_op_type operation_type,
  864. uint32_t staling_distance)
  865. {
  866. int rc;
  867. struct cam_sys_cache_local_info sys_cache_info;
  868. if (!CAM_CPAS_INTF_INITIALIZED()) {
  869. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  870. return -ENODEV;
  871. }
  872. if (!cam_cpas_is_notif_staling_supported())
  873. return -EOPNOTSUPP;
  874. sys_cache_info.mode = mode_param;
  875. sys_cache_info.op_type = operation_type;
  876. sys_cache_info.staling_distance
  877. = staling_distance;
  878. sys_cache_info.type = type;
  879. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  880. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  881. g_cpas_intf->hw_intf->hw_priv,
  882. CAM_CPAS_HW_CMD_CONFIGURE_STALING_LLC, &sys_cache_info,
  883. sizeof(struct cam_sys_cache_local_info));
  884. if (rc)
  885. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  886. } else {
  887. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  888. rc = -EINVAL;
  889. }
  890. return rc;
  891. }
  892. EXPORT_SYMBOL(cam_cpas_configure_staling_llcc);
  893. int cam_cpas_notif_increment_staling_counter(
  894. enum cam_sys_cache_config_types type)
  895. {
  896. int rc;
  897. if (!CAM_CPAS_INTF_INITIALIZED()) {
  898. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  899. return -ENODEV;
  900. }
  901. if (!cam_cpas_is_notif_staling_supported())
  902. return -EOPNOTSUPP;
  903. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  904. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  905. g_cpas_intf->hw_intf->hw_priv,
  906. CAM_CPAS_HW_CMD_NOTIF_STALL_INC_LLC, &type,
  907. sizeof(type));
  908. if (rc)
  909. CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
  910. } else {
  911. CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
  912. rc = -EINVAL;
  913. }
  914. return rc;
  915. }
  916. EXPORT_SYMBOL(cam_cpas_notif_increment_staling_counter);
  917. bool cam_cpas_is_notif_staling_supported(void)
  918. {
  919. #if IS_ENABLED(CONFIG_SPECTRA_LLCC_STALING)
  920. return true;
  921. #else
  922. return false;
  923. #endif
  924. }
  925. EXPORT_SYMBOL(cam_cpas_is_notif_staling_supported);
  926. bool cam_cpas_query_domain_id_security_support(void)
  927. {
  928. struct cam_hw_info *cpas_hw = NULL;
  929. struct cam_cpas_private_soc *soc_private = NULL;
  930. if (!CAM_CPAS_INTF_INITIALIZED()) {
  931. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  932. return false;
  933. }
  934. cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
  935. soc_private =
  936. (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
  937. return soc_private->domain_id_info.domain_id_supported;
  938. }
  939. EXPORT_SYMBOL(cam_cpas_query_domain_id_security_support);
  940. int cam_cpas_enable_clks_for_domain_id(bool enable)
  941. {
  942. int rc = 0;
  943. if (!CAM_CPAS_INTF_INITIALIZED()) {
  944. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  945. return -ENODEV;
  946. }
  947. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  948. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  949. g_cpas_intf->hw_intf->hw_priv,
  950. CAM_CPAS_HW_CMD_ENABLE_DISABLE_DOMAIN_ID_CLK, &enable,
  951. sizeof(enable));
  952. }
  953. return rc;
  954. }
  955. EXPORT_SYMBOL(cam_cpas_enable_clks_for_domain_id);
  956. int cam_cpas_dump_state_monitor_info(struct cam_req_mgr_dump_info *info)
  957. {
  958. int rc = 0;
  959. if (!CAM_CPAS_INTF_INITIALIZED()) {
  960. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  961. return -ENODEV;
  962. }
  963. if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
  964. rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
  965. g_cpas_intf->hw_intf->hw_priv,
  966. CAM_CPAS_HW_CMD_DUMP_STATE_MONITOR_INFO, info,
  967. sizeof(*info));
  968. }
  969. return rc;
  970. }
  971. EXPORT_SYMBOL(cam_cpas_dump_state_monitor_info);
  972. #ifdef CONFIG_DYNAMIC_FD_PORT_CONFIG
  973. static int cam_cpas_handle_fd_port_config(uint32_t is_secure)
  974. {
  975. int rc = 0;
  976. struct Object client_env, sc_object;
  977. struct cam_hw_info *cpas_hw = NULL;
  978. struct cam_cpas *cpas_core;
  979. if (!CAM_CPAS_INTF_INITIALIZED()) {
  980. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  981. return -EINVAL;
  982. }
  983. cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
  984. if (cpas_hw) {
  985. cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  986. mutex_lock(&cpas_hw->hw_mutex);
  987. if (cpas_core->streamon_clients > 0) {
  988. CAM_ERR(CAM_CPAS,
  989. "FD port config can not be updated during the session");
  990. mutex_unlock(&cpas_hw->hw_mutex);
  991. return -EINVAL;
  992. }
  993. } else {
  994. CAM_ERR(CAM_CPAS, "cpas_hw handle not initialized");
  995. return -EINVAL;
  996. }
  997. /* Need to vote first before enabling clocks */
  998. rc = cam_cpas_util_vote_default_ahb_axi(cpas_hw, true);
  999. if (rc) {
  1000. CAM_ERR(CAM_CPAS,
  1001. "failed to vote for the default ahb/axi clock, rc=%d", rc);
  1002. goto release_mutex;
  1003. }
  1004. rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info,
  1005. cpas_hw->soc_info.lowest_clk_level);
  1006. if (rc) {
  1007. CAM_ERR(CAM_CPAS, "failed in soc_enable_resources, rc=%d", rc);
  1008. goto remove_default_vote;
  1009. }
  1010. rc = get_client_env_object(&client_env);
  1011. if (rc) {
  1012. CAM_ERR(CAM_CPAS, "Failed getting mink env object, rc: %d", rc);
  1013. goto disable_resources;
  1014. }
  1015. rc = IClientEnv_open(client_env, CTrustedCameraDriver_UID, &sc_object);
  1016. if (rc) {
  1017. CAM_ERR(CAM_CPAS, "Failed getting mink sc_object, rc: %d", rc);
  1018. goto client_release;
  1019. }
  1020. rc = ITrustedCameraDriver_dynamicConfigureFDPort(sc_object, is_secure);
  1021. if (rc) {
  1022. if (rc == CAM_CPAS_ERROR_NOT_ALLOWED) {
  1023. CAM_ERR(CAM_CPAS, "Dynamic FD port config not allowed");
  1024. rc = -EPERM;
  1025. } else {
  1026. CAM_ERR(CAM_CPAS, "Mink secure call failed, rc: %d", rc);
  1027. rc = -EINVAL;
  1028. }
  1029. goto obj_release;
  1030. }
  1031. rc = Object_release(sc_object);
  1032. if (rc) {
  1033. CAM_ERR(CAM_CSIPHY, "Failed releasing secure camera object, rc: %d", rc);
  1034. goto client_release;
  1035. }
  1036. rc = Object_release(client_env);
  1037. if (rc) {
  1038. CAM_ERR(CAM_CSIPHY, "Failed releasing mink env object, rc: %d", rc);
  1039. goto disable_resources;
  1040. }
  1041. rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
  1042. if (rc) {
  1043. CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
  1044. goto remove_default_vote;
  1045. }
  1046. rc = cam_cpas_util_vote_default_ahb_axi(cpas_hw, false);
  1047. if (rc)
  1048. CAM_ERR(CAM_CPAS,
  1049. "failed remove the vote on ahb/axi clock, rc=%d", rc);
  1050. mutex_unlock(&cpas_hw->hw_mutex);
  1051. return rc;
  1052. obj_release:
  1053. Object_release(sc_object);
  1054. client_release:
  1055. Object_release(client_env);
  1056. disable_resources:
  1057. cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
  1058. remove_default_vote:
  1059. cam_cpas_util_vote_default_ahb_axi(cpas_hw, false);
  1060. release_mutex:
  1061. mutex_unlock(&cpas_hw->hw_mutex);
  1062. return rc;
  1063. }
  1064. #endif
  1065. static int cam_cpas_handle_custom_config_cmd(struct cam_cpas_intf *cpas_intf,
  1066. struct cam_custom_cmd *cmd)
  1067. {
  1068. int32_t rc = 0;
  1069. if (!cmd) {
  1070. CAM_ERR(CAM_CPAS, "Invalid input cmd");
  1071. return -EINVAL;
  1072. }
  1073. switch (cmd->cmd_type) {
  1074. #ifdef CONFIG_DYNAMIC_FD_PORT_CONFIG
  1075. case CAM_CPAS_CUSTOM_CMD_FD_PORT_CFG: {
  1076. struct cam_cpas_fd_port_config cfg;
  1077. if (cmd->size < sizeof(cfg))
  1078. return -EINVAL;
  1079. rc = copy_from_user(&cfg, u64_to_user_ptr(cmd->handle),
  1080. sizeof(cfg));
  1081. if (rc) {
  1082. CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
  1083. rc);
  1084. rc = -EINVAL;
  1085. break;
  1086. }
  1087. rc = cam_cpas_handle_fd_port_config(cfg.is_secure);
  1088. break;
  1089. }
  1090. #endif
  1091. default:
  1092. CAM_ERR(CAM_CPAS, "Invalid custom command %d for CPAS", cmd->cmd_type);
  1093. rc = -EINVAL;
  1094. break;
  1095. }
  1096. return rc;
  1097. }
  1098. int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf,
  1099. struct cam_control *cmd)
  1100. {
  1101. int rc = 0;
  1102. uint32_t *camera_capability, num_cap_mask;
  1103. if (!cmd) {
  1104. CAM_ERR(CAM_CPAS, "Invalid input cmd");
  1105. return -EINVAL;
  1106. }
  1107. switch (cmd->op_code) {
  1108. case CAM_QUERY_CAP: {
  1109. struct cam_cpas_query_cap query;
  1110. rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle),
  1111. sizeof(query));
  1112. if (rc) {
  1113. CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
  1114. rc);
  1115. break;
  1116. }
  1117. rc = cam_cpas_get_hw_info(&query.camera_family,
  1118. &query.camera_version, &query.cpas_version,
  1119. &camera_capability, &num_cap_mask, NULL, NULL);
  1120. if (rc)
  1121. break;
  1122. query.reserved = camera_capability[0];
  1123. rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query,
  1124. sizeof(query));
  1125. if (rc)
  1126. CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc);
  1127. break;
  1128. }
  1129. case CAM_QUERY_CAP_V2: {
  1130. struct cam_cpas_query_cap_v2 query;
  1131. rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle),
  1132. sizeof(query));
  1133. if (rc) {
  1134. CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
  1135. rc);
  1136. break;
  1137. }
  1138. rc = cam_cpas_get_hw_info(&query.camera_family,
  1139. &query.camera_version, &query.cpas_version,
  1140. &camera_capability, &num_cap_mask,
  1141. &query.fuse_info, NULL);
  1142. if (rc)
  1143. break;
  1144. query.reserved = camera_capability[0];
  1145. rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query,
  1146. sizeof(query));
  1147. if (rc)
  1148. CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc);
  1149. break;
  1150. }
  1151. case CAM_QUERY_CAP_V3: {
  1152. struct cam_cpas_query_cap_v3 query;
  1153. rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle),
  1154. sizeof(query));
  1155. if (rc) {
  1156. CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
  1157. rc);
  1158. break;
  1159. }
  1160. rc = cam_cpas_get_hw_info(&query.camera_family,
  1161. &query.camera_version, &query.cpas_version,
  1162. &camera_capability, &num_cap_mask, &query.fuse_info,
  1163. &query.domain_id_info);
  1164. if (rc)
  1165. break;
  1166. query.camera_caps = camera_capability[0];
  1167. rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query,
  1168. sizeof(query));
  1169. if (rc)
  1170. CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc);
  1171. break;
  1172. }
  1173. case CAM_CUSTOM_DEV_CONFIG: {
  1174. struct cam_custom_cmd custom_cmd;
  1175. rc = copy_from_user(&custom_cmd, u64_to_user_ptr(cmd->handle),
  1176. sizeof(custom_cmd));
  1177. if (rc) {
  1178. CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d",
  1179. rc);
  1180. break;
  1181. }
  1182. rc = cam_cpas_handle_custom_config_cmd(cpas_intf, &custom_cmd);
  1183. break;
  1184. }
  1185. case CAM_SD_SHUTDOWN:
  1186. break;
  1187. default:
  1188. CAM_ERR(CAM_CPAS, "Unknown op code %d for CPAS", cmd->op_code);
  1189. rc = -EINVAL;
  1190. break;
  1191. }
  1192. return rc;
  1193. }
  1194. static int cam_cpas_subdev_open(struct v4l2_subdev *sd,
  1195. struct v4l2_subdev_fh *fh)
  1196. {
  1197. struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
  1198. if (!cpas_intf || !cpas_intf->probe_done) {
  1199. CAM_ERR(CAM_CPAS, "CPAS not initialized");
  1200. return -ENODEV;
  1201. }
  1202. mutex_lock(&cpas_intf->intf_lock);
  1203. cpas_intf->open_cnt++;
  1204. CAM_DBG(CAM_CPAS, "CPAS Subdev open count %d", cpas_intf->open_cnt);
  1205. mutex_unlock(&cpas_intf->intf_lock);
  1206. return 0;
  1207. }
  1208. static int __cam_cpas_subdev_close(struct v4l2_subdev *sd,
  1209. struct v4l2_subdev_fh *fh)
  1210. {
  1211. struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
  1212. if (!cpas_intf || !cpas_intf->probe_done) {
  1213. CAM_ERR(CAM_CPAS, "CPAS not initialized");
  1214. return -ENODEV;
  1215. }
  1216. mutex_lock(&cpas_intf->intf_lock);
  1217. if (cpas_intf->open_cnt <= 0) {
  1218. CAM_WARN(CAM_CPAS, "device already closed, open_cnt: %d", cpas_intf->open_cnt);
  1219. mutex_unlock(&cpas_intf->intf_lock);
  1220. return 0;
  1221. }
  1222. cpas_intf->open_cnt--;
  1223. CAM_DBG(CAM_CPAS, "CPAS Subdev close count %d", cpas_intf->open_cnt);
  1224. mutex_unlock(&cpas_intf->intf_lock);
  1225. return 0;
  1226. }
  1227. static int cam_cpas_subdev_close(struct v4l2_subdev *sd,
  1228. struct v4l2_subdev_fh *fh)
  1229. {
  1230. bool crm_active = cam_req_mgr_is_open();
  1231. if (crm_active) {
  1232. CAM_DBG(CAM_CPAS, "CRM is ACTIVE, close should be from CRM");
  1233. return 0;
  1234. }
  1235. return __cam_cpas_subdev_close(sd, fh);
  1236. }
  1237. static long cam_cpas_subdev_ioctl(struct v4l2_subdev *sd,
  1238. unsigned int cmd, void *arg)
  1239. {
  1240. int32_t rc;
  1241. struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
  1242. if (!cpas_intf || !cpas_intf->probe_done) {
  1243. CAM_ERR(CAM_CPAS, "CPAS not initialized");
  1244. return -ENODEV;
  1245. }
  1246. switch (cmd) {
  1247. case VIDIOC_CAM_CONTROL:
  1248. rc = cam_cpas_subdev_cmd(cpas_intf, (struct cam_control *) arg);
  1249. break;
  1250. case CAM_SD_SHUTDOWN:
  1251. rc = __cam_cpas_subdev_close(sd, NULL);
  1252. break;
  1253. default:
  1254. CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd);
  1255. rc = -EINVAL;
  1256. break;
  1257. }
  1258. return rc;
  1259. }
  1260. #ifdef CONFIG_COMPAT
  1261. static long cam_cpas_subdev_compat_ioctl(struct v4l2_subdev *sd,
  1262. unsigned int cmd, unsigned long arg)
  1263. {
  1264. struct cam_control cmd_data;
  1265. int32_t rc;
  1266. struct cam_cpas_intf *cpas_intf = v4l2_get_subdevdata(sd);
  1267. if (!cpas_intf || !cpas_intf->probe_done) {
  1268. CAM_ERR(CAM_CPAS, "CPAS not initialized");
  1269. return -ENODEV;
  1270. }
  1271. if (copy_from_user(&cmd_data, (void __user *)arg,
  1272. sizeof(cmd_data))) {
  1273. CAM_ERR(CAM_CPAS, "Failed to copy from user_ptr=%pK size=%zu",
  1274. (void __user *)arg, sizeof(cmd_data));
  1275. return -EFAULT;
  1276. }
  1277. switch (cmd) {
  1278. case VIDIOC_CAM_CONTROL:
  1279. rc = cam_cpas_subdev_cmd(cpas_intf, &cmd_data);
  1280. break;
  1281. default:
  1282. CAM_ERR(CAM_CPAS, "Invalid command %d for CPAS!", cmd);
  1283. rc = -EINVAL;
  1284. break;
  1285. }
  1286. if (!rc) {
  1287. if (copy_to_user((void __user *)arg, &cmd_data,
  1288. sizeof(cmd_data))) {
  1289. CAM_ERR(CAM_CPAS,
  1290. "Failed to copy to user_ptr=%pK size=%zu",
  1291. (void __user *)arg, sizeof(cmd_data));
  1292. rc = -EFAULT;
  1293. }
  1294. }
  1295. return rc;
  1296. }
  1297. #endif
  1298. static struct v4l2_subdev_core_ops cpas_subdev_core_ops = {
  1299. .ioctl = cam_cpas_subdev_ioctl,
  1300. #ifdef CONFIG_COMPAT
  1301. .compat_ioctl32 = cam_cpas_subdev_compat_ioctl,
  1302. #endif
  1303. };
  1304. static const struct v4l2_subdev_ops cpas_subdev_ops = {
  1305. .core = &cpas_subdev_core_ops,
  1306. };
  1307. static const struct v4l2_subdev_internal_ops cpas_subdev_intern_ops = {
  1308. .open = cam_cpas_subdev_open,
  1309. .close = cam_cpas_subdev_close,
  1310. };
  1311. static int cam_cpas_subdev_register(struct platform_device *pdev)
  1312. {
  1313. int rc;
  1314. struct cam_subdev *subdev;
  1315. if (!g_cpas_intf)
  1316. return -EINVAL;
  1317. subdev = &g_cpas_intf->subdev;
  1318. subdev->name = CAM_CPAS_DEV_NAME;
  1319. subdev->pdev = pdev;
  1320. subdev->ops = &cpas_subdev_ops;
  1321. subdev->internal_ops = &cpas_subdev_intern_ops;
  1322. subdev->token = g_cpas_intf;
  1323. subdev->sd_flags =
  1324. V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
  1325. subdev->ent_function = CAM_CPAS_DEVICE_TYPE;
  1326. subdev->close_seq_prior = CAM_SD_CLOSE_LOW_PRIORITY;
  1327. rc = cam_register_subdev(subdev);
  1328. if (rc) {
  1329. CAM_ERR(CAM_CPAS, "failed register subdev: %s!",
  1330. CAM_CPAS_DEV_NAME);
  1331. return rc;
  1332. }
  1333. platform_set_drvdata(g_cpas_intf->pdev, g_cpas_intf);
  1334. return rc;
  1335. }
  1336. static int cam_cpas_dev_component_bind(struct device *dev,
  1337. struct device *master_dev, void *data)
  1338. {
  1339. struct cam_cpas_hw_caps *hw_caps;
  1340. struct cam_hw_intf *hw_intf;
  1341. int rc;
  1342. struct platform_device *pdev = to_platform_device(dev);
  1343. if (g_cpas_intf) {
  1344. CAM_ERR(CAM_CPAS, "cpas component already binded");
  1345. return -EALREADY;
  1346. }
  1347. g_cpas_intf = kzalloc(sizeof(*g_cpas_intf), GFP_KERNEL);
  1348. if (!g_cpas_intf)
  1349. return -ENOMEM;
  1350. mutex_init(&g_cpas_intf->intf_lock);
  1351. g_cpas_intf->pdev = pdev;
  1352. rc = cam_cpas_hw_probe(pdev, &g_cpas_intf->hw_intf);
  1353. if (rc || (g_cpas_intf->hw_intf == NULL)) {
  1354. CAM_ERR(CAM_CPAS, "Failed in hw probe, rc=%d", rc);
  1355. goto error_destroy_mem;
  1356. }
  1357. hw_intf = g_cpas_intf->hw_intf;
  1358. hw_caps = &g_cpas_intf->hw_caps;
  1359. if (hw_intf->hw_ops.get_hw_caps) {
  1360. rc = hw_intf->hw_ops.get_hw_caps(hw_intf->hw_priv,
  1361. hw_caps, sizeof(struct cam_cpas_hw_caps));
  1362. if (rc) {
  1363. CAM_ERR(CAM_CPAS, "Failed in get_hw_caps, rc=%d", rc);
  1364. goto error_hw_remove;
  1365. }
  1366. } else {
  1367. CAM_ERR(CAM_CPAS, "Invalid get_hw_caps ops");
  1368. goto error_hw_remove;
  1369. }
  1370. rc = cam_cpas_subdev_register(pdev);
  1371. if (rc)
  1372. goto error_hw_remove;
  1373. g_cpas_intf->probe_done = true;
  1374. CAM_DBG(CAM_CPAS,
  1375. "Component bound successfully %d, %d.%d.%d, %d.%d.%d, 0x%x",
  1376. hw_caps->camera_family, hw_caps->camera_version.major,
  1377. hw_caps->camera_version.minor, hw_caps->camera_version.incr,
  1378. hw_caps->cpas_version.major, hw_caps->cpas_version.minor,
  1379. hw_caps->cpas_version.incr, hw_caps->camera_capability);
  1380. return rc;
  1381. error_hw_remove:
  1382. cam_cpas_hw_remove(g_cpas_intf->hw_intf);
  1383. error_destroy_mem:
  1384. mutex_destroy(&g_cpas_intf->intf_lock);
  1385. kfree(g_cpas_intf);
  1386. g_cpas_intf = NULL;
  1387. CAM_ERR(CAM_CPAS, "CPAS component bind failed");
  1388. return rc;
  1389. }
  1390. static void cam_cpas_dev_component_unbind(struct device *dev,
  1391. struct device *master_dev, void *data)
  1392. {
  1393. if (!CAM_CPAS_INTF_INITIALIZED()) {
  1394. CAM_ERR(CAM_CPAS, "cpas intf not initialized");
  1395. return;
  1396. }
  1397. mutex_lock(&g_cpas_intf->intf_lock);
  1398. g_cpas_intf->probe_done = false;
  1399. cam_unregister_subdev(&g_cpas_intf->subdev);
  1400. cam_cpas_hw_remove(g_cpas_intf->hw_intf);
  1401. mutex_unlock(&g_cpas_intf->intf_lock);
  1402. mutex_destroy(&g_cpas_intf->intf_lock);
  1403. kfree(g_cpas_intf);
  1404. g_cpas_intf = NULL;
  1405. }
  1406. const static struct component_ops cam_cpas_dev_component_ops = {
  1407. .bind = cam_cpas_dev_component_bind,
  1408. .unbind = cam_cpas_dev_component_unbind,
  1409. };
  1410. static int cam_cpas_dev_probe(struct platform_device *pdev)
  1411. {
  1412. int rc = 0;
  1413. CAM_DBG(CAM_CPAS, "Adding CPAS INTF component");
  1414. rc = component_add(&pdev->dev, &cam_cpas_dev_component_ops);
  1415. if (rc)
  1416. CAM_ERR(CAM_CPAS, "failed to add component rc: %d", rc);
  1417. return rc;
  1418. }
  1419. static int cam_cpas_dev_remove(struct platform_device *pdev)
  1420. {
  1421. component_del(&pdev->dev, &cam_cpas_dev_component_ops);
  1422. return 0;
  1423. }
  1424. static const struct of_device_id cam_cpas_dt_match[] = {
  1425. {.compatible = "qcom,cam-cpas"},
  1426. {}
  1427. };
  1428. struct platform_driver cam_cpas_driver = {
  1429. .probe = cam_cpas_dev_probe,
  1430. .remove = cam_cpas_dev_remove,
  1431. .driver = {
  1432. .name = CAM_CPAS_DEV_NAME,
  1433. .owner = THIS_MODULE,
  1434. .of_match_table = cam_cpas_dt_match,
  1435. .suppress_bind_attrs = true,
  1436. },
  1437. };
  1438. int cam_cpas_dev_init_module(void)
  1439. {
  1440. return platform_driver_register(&cam_cpas_driver);
  1441. }
  1442. void cam_cpas_dev_exit_module(void)
  1443. {
  1444. platform_driver_unregister(&cam_cpas_driver);
  1445. }
  1446. MODULE_DESCRIPTION("MSM CPAS driver");
  1447. MODULE_LICENSE("GPL v2");