secdp_sysfs.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/device.h>
  18. #include <drm/drm_edid.h>
  19. #include <linux/string.h>
  20. #if defined(CONFIG_SECDP_BIGDATA)
  21. #include <linux/secdp_bigdata.h>
  22. #endif
  23. #include "dp_link.h"
  24. #include "dp_panel.h"
  25. #include "dp_power.h"
  26. #include "dp_catalog.h"
  27. #include "dp_debug.h"
  28. #include "dp_display.h"
  29. #include "secdp.h"
  30. #include "secdp_sysfs.h"
  31. #include "sde_edid_parser.h"
  32. #include "secdp_unit_test.h"
  33. enum secdp_unit_test_cmd {
  34. SECDP_UTCMD_EDID_PARSE = 0,
  35. };
  36. struct secdp_sysfs_private {
  37. struct device *dev;
  38. struct dp_parser *parser;
  39. struct dp_panel *panel;
  40. struct dp_power *power;
  41. struct dp_link *link;
  42. struct dp_ctrl *ctrl;
  43. struct dp_catalog *catalog;
  44. struct secdp_misc *sec;
  45. struct secdp_sysfs dp_sysfs;
  46. enum secdp_unit_test_cmd test_cmd;
  47. };
  48. static inline char *secdp_utcmd_to_str(u32 cmd_type)
  49. {
  50. switch (cmd_type) {
  51. case SECDP_UTCMD_EDID_PARSE:
  52. return SECDP_ENUM_STR(SECDP_UTCMD_EDID_PARSE);
  53. default:
  54. return "unknown";
  55. }
  56. }
  57. /** check if buf has range('-') format
  58. * @buf buf to be checked
  59. * @size buf size
  60. * @retval 0 if args are ok, -1 if '-' included
  61. */
  62. static int secdp_check_store_args(const char *buf, size_t size)
  63. {
  64. int ret;
  65. if (strnchr(buf, size, '-')) {
  66. DP_ERR("range is forbidden!\n");
  67. ret = -1;
  68. goto exit;
  69. }
  70. ret = 0;
  71. exit:
  72. return ret;
  73. }
  74. static struct secdp_sysfs_private *secdp_get_sysfs_private(struct class *class)
  75. {
  76. struct secdp_sysfs *dp_sysfs;
  77. dp_sysfs = container_of(class, struct secdp_sysfs, dp_class);
  78. return container_of(dp_sysfs, struct secdp_sysfs_private, dp_sysfs);
  79. }
  80. #if defined(CONFIG_SECDP_FACTORY_DPSWITCH_TEST)
  81. static ssize_t dp_sbu_sw_sel_store(struct class *class,
  82. struct class_attribute *attr, const char *buf, size_t size)
  83. {
  84. struct secdp_sysfs_private *sysfs;
  85. int sbu_sw_sel, sbu_sw_oe, val[10] = {0,};
  86. if (secdp_check_store_args(buf, size)) {
  87. DP_ERR("args error!\n");
  88. goto exit;
  89. }
  90. get_options(buf, ARRAY_SIZE(val), val);
  91. sbu_sw_sel = val[1];
  92. sbu_sw_oe = val[2];
  93. DP_INFO("sw_sel:%d sw_oe:%d\n", sbu_sw_sel, sbu_sw_oe);
  94. sysfs = secdp_get_sysfs_private(class);
  95. if (sbu_sw_oe == 0/*on*/)
  96. secdp_config_gpios_factory(sysfs->power, sbu_sw_sel, true);
  97. else if (sbu_sw_oe == 1/*off*/)
  98. secdp_config_gpios_factory(sysfs->power, sbu_sw_sel, false);
  99. else
  100. DP_ERR("unknown sw_oe %d\n", sbu_sw_oe);
  101. exit:
  102. return size;
  103. }
  104. static CLASS_ATTR_WO(dp_sbu_sw_sel);
  105. #endif
  106. #define SECDP_DEX_ADAPTER_SKIP "SkipAdapterCheck"
  107. #define SECDP_EXTDISP_OFF "ExtDispOff"
  108. static ssize_t dex_show(struct class *class,
  109. struct class_attribute *attr, char *buf)
  110. {
  111. struct secdp_sysfs_private *sysfs;
  112. struct secdp_misc *sec;
  113. struct secdp_dex *dex;
  114. int rc = 0;
  115. sysfs = secdp_get_sysfs_private(class);
  116. sec = sysfs->sec;
  117. dex = &sec->dex;
  118. if (!secdp_get_cable_status() || !secdp_get_hpd_status() ||
  119. secdp_get_poor_connection_status(sysfs->link) ||
  120. !secdp_get_link_train_status(sysfs->ctrl)) {
  121. DP_INFO("cable is out\n");
  122. dex->prev = dex->curr = dex->status = DEX_DISABLED;
  123. }
  124. DP_INFO("prev:%d curr:%d status:%d %s:%d %s:%d\n",
  125. dex->prev, dex->curr, dex->status,
  126. SECDP_DEX_ADAPTER_SKIP, dex->adapter_check_skip,
  127. SECDP_EXTDISP_OFF, sec->extdisp_off);
  128. #if 1//org
  129. rc = scnprintf(buf, PAGE_SIZE, "%d\n", dex->status);
  130. #else//.TODO: DeX team needs to check if this chnage is good to parse
  131. rc = scnprintf(buf, PAGE_SIZE, "%d,%s:%d,%s:%d\n", dex->status,
  132. SECDP_DEX_ADAPTER_SKIP, dex->adapter_check_skip,
  133. SECDP_EXTDISP_OFF, sec->extdisp_off);
  134. #endif
  135. if (dex->status == DEX_MODE_CHANGING)
  136. dex->status = dex->curr;
  137. return rc;
  138. }
  139. /*
  140. * assume that 1 HMD device has name(14),vid(4),pid(4) each, then
  141. * max 32 HMD devices(name,vid,pid) need 806 bytes including TAG, NUM, comba
  142. */
  143. #define MAX_DEX_STORE_LEN 1024
  144. static ssize_t dex_store(struct class *class,
  145. struct class_attribute *attr, const char *buf, size_t size)
  146. {
  147. struct secdp_sysfs_private *sysfs;
  148. struct secdp_misc *sec;
  149. struct secdp_dex *dex;
  150. struct secdp_pdic_noti *pdic_noti;
  151. char *p, *tok, str[MAX_DEX_STORE_LEN] = {0,};
  152. int len, val[4] = {0,};
  153. int setting_ui; /* setting has Dex mode? if yes, 1. otherwise 0 */
  154. int run; /* dex is running now? if yes, 1. otherwise 0 */
  155. sysfs = secdp_get_sysfs_private(class);
  156. sec = sysfs->sec;
  157. dex = &sec->dex;
  158. pdic_noti = &sec->pdic_noti;
  159. if (secdp_get_lpm_mode(sec)) {
  160. DP_INFO("LPM mode, skip\n");
  161. goto exit;
  162. }
  163. if (size >= MAX_DEX_STORE_LEN) {
  164. DP_ERR("too long args! %lu\n", size);
  165. goto exit;
  166. }
  167. if (secdp_check_store_args(buf, size)) {
  168. DP_ERR("args error!\n");
  169. goto exit;
  170. }
  171. mutex_lock(&sec->hmd.lock);
  172. memcpy(str, buf, size);
  173. p = str;
  174. tok = strsep(&p, ",");
  175. len = strlen(tok);
  176. //DP_DEBUG("tok:%s len:%d\n", tok, len);
  177. if (len && !strncmp(DEX_TAG_HMD, tok, len)) {
  178. int num_hmd = 0, sz = 0, ret;
  179. tok = strsep(&p, ",");
  180. if (!tok) {
  181. DP_ERR("wrong input!\n");
  182. mutex_unlock(&sec->hmd.lock);
  183. goto exit;
  184. }
  185. sz = strlen(tok);
  186. ret = kstrtouint(tok, 10, &num_hmd);
  187. DP_DEBUG("[%s] num:%d sz:%d ret:%d\n", DEX_TAG_HMD,
  188. num_hmd, sz, ret);
  189. if (!ret) {
  190. ret = secdp_store_hmd_dev(sysfs->sec, str + (len + sz + 2),
  191. size - (len + sz + 2), num_hmd);
  192. }
  193. if (ret)
  194. size = ret; /* error! */
  195. mutex_unlock(&sec->hmd.lock);
  196. goto exit;
  197. }
  198. mutex_unlock(&sec->hmd.lock);
  199. if (len && !strncmp(SECDP_DEX_ADAPTER_SKIP, tok, len)) {
  200. int param = 0, sz = 0, ret;
  201. tok = strsep(&p, ",");
  202. if (!tok) {
  203. DP_ERR("wrong input!\n");
  204. goto exit;
  205. }
  206. sz = strlen(tok);
  207. ret = kstrtouint(tok, 2, &param);
  208. if (ret) {
  209. DP_ERR("error %d\n", ret);
  210. goto exit;
  211. }
  212. DP_DEBUG("[%s] param:%d sz:%d ret:%d\n", SECDP_DEX_ADAPTER_SKIP,
  213. param, sz, ret);
  214. dex->adapter_check_skip = (!param) ? false : true;
  215. goto exit;
  216. }
  217. if (len && !strncmp(SECDP_EXTDISP_OFF, tok, len)) {
  218. int param = 0, sz = 0, ret;
  219. tok = strsep(&p, ",");
  220. if (!tok) {
  221. DP_ERR("wrong input!\n");
  222. goto exit;
  223. }
  224. sz = strlen(tok);
  225. ret = kstrtouint(tok, 2, &param);
  226. if (ret) {
  227. DP_ERR("error %d\n", ret);
  228. goto exit;
  229. }
  230. DP_DEBUG("[%s] param:%d sz:%d ret:%d\n", SECDP_EXTDISP_OFF,
  231. param, sz, ret);
  232. sec->extdisp_off = (!param) ? false : true;
  233. if (sec->extdisp_off)
  234. secdp_extdisp_off(sec);
  235. else
  236. secdp_extdisp_on(sec);
  237. goto exit;
  238. }
  239. get_options(buf, ARRAY_SIZE(val), val);
  240. setting_ui = (val[1] & 0xf0) >> 4;
  241. run = (val[1] & 0x0f);
  242. DP_INFO("0x%02x setting_ui:%d run:%d cable:%d\n", val[1],
  243. setting_ui, run, sec->cable_connected);
  244. dex->setting_ui = setting_ui;
  245. dex->status = dex->curr = run;
  246. mutex_lock(&sec->notifier_lock);
  247. if (!pdic_noti->registered) {
  248. int rc;
  249. /* cancel immediately */
  250. rc = cancel_delayed_work(&pdic_noti->reg_work);
  251. DP_DEBUG("notifier get registered by dex, cancel:%d\n", rc);
  252. destroy_delayed_work_on_stack(&pdic_noti->reg_work);
  253. /* register */
  254. rc = secdp_pdic_noti_register_ex(sec, false);
  255. if (rc)
  256. DP_ERR("noti register fail %d\n", rc);
  257. mutex_unlock(&sec->notifier_lock);
  258. goto exit;
  259. }
  260. mutex_unlock(&sec->notifier_lock);
  261. if (!secdp_get_cable_status() || !secdp_get_hpd_status() ||
  262. secdp_get_poor_connection_status(sysfs->link) ||
  263. !secdp_get_link_train_status(sysfs->ctrl)) {
  264. DP_INFO("cable is out\n");
  265. dex->prev = dex->curr = dex->status = DEX_DISABLED;
  266. goto exit;
  267. }
  268. if (sec->hpd.noti_deferred) {
  269. secdp_send_deferred_hpd_noti(sec);
  270. dex->prev = dex->setting_ui;
  271. goto exit;
  272. }
  273. if (dex->curr == dex->prev) {
  274. DP_INFO("dex is already %s\n",
  275. (dex->curr == DEX_ENABLED) ? "enabled" :
  276. ((dex->curr == DEX_DISABLED) ? "disabled" : "changing"));
  277. goto exit;
  278. }
  279. if (dex->curr != dex->setting_ui) {
  280. DP_INFO("curr and setting_ui are different %d %d\n",
  281. dex->curr, dex->setting_ui);
  282. goto exit;
  283. }
  284. #if defined(CONFIG_SECDP_BIGDATA)
  285. if (run)
  286. secdp_bigdata_save_item(BD_DP_MODE, "DEX");
  287. else
  288. secdp_bigdata_save_item(BD_DP_MODE, "MIRROR");
  289. #endif
  290. if (sec->dex.res == DEX_RES_NOT_SUPPORT) {
  291. DP_DEBUG("this dongle does not support dex\n");
  292. goto exit;
  293. }
  294. if (!secdp_check_reconnect(sysfs->sec)) {
  295. DP_INFO("not need reconnect\n");
  296. goto exit;
  297. }
  298. secdp_reconnect(sysfs->sec);
  299. dex->prev = run;
  300. exit:
  301. return size;
  302. }
  303. static CLASS_ATTR_RW(dex);
  304. static ssize_t dex_ver_show(struct class *class,
  305. struct class_attribute *attr, char *buf)
  306. {
  307. struct secdp_sysfs_private *sysfs;
  308. struct secdp_adapter *adapter;
  309. int rc;
  310. sysfs = secdp_get_sysfs_private(class);
  311. adapter = &sysfs->sec->adapter;
  312. DP_INFO("branch revision: HW(0x%X),SW(0x%X,0x%X)\n",
  313. adapter->fw_ver[0], adapter->fw_ver[1], adapter->fw_ver[2]);
  314. rc = scnprintf(buf, PAGE_SIZE, "%02X%02X\n",
  315. adapter->fw_ver[1], adapter->fw_ver[2]);
  316. return rc;
  317. }
  318. static CLASS_ATTR_RO(dex_ver);
  319. /* note: needs test once wifi is fixed */
  320. static ssize_t monitor_info_show(struct class *class,
  321. struct class_attribute *attr, char *buf)
  322. {
  323. struct secdp_sysfs_private *sysfs;
  324. struct dp_panel *panel;
  325. struct sde_edid_ctrl *edid_ctrl = NULL;
  326. struct edid *edid = NULL;
  327. short prod_id = 0;
  328. int rc = 0;
  329. sysfs = secdp_get_sysfs_private(class);
  330. panel = sysfs->panel;
  331. edid_ctrl = panel->edid_ctrl;
  332. if (!edid_ctrl) {
  333. DP_ERR("unable to find edid_ctrl\n");
  334. goto exit;
  335. }
  336. edid = edid_ctrl->edid;
  337. if (!edid) {
  338. DP_ERR("unable to find edid\n");
  339. goto exit;
  340. }
  341. prod_id |= (edid->prod_code[0] << 8) | (edid->prod_code[1]);
  342. DP_DEBUG("prod_code[0]:%02x, prod_code[1]:%02x, prod_id:%04x\n",
  343. edid->prod_code[0], edid->prod_code[1], prod_id);
  344. rc = snprintf(buf, SZ_32, "%s,0x%x,0x%x\n",
  345. edid_ctrl->vendor_id, prod_id, edid->serial); /* byte order? */
  346. exit:
  347. return rc;
  348. }
  349. static CLASS_ATTR_RO(monitor_info);
  350. #ifdef SYSFS_BW_CODE
  351. static ssize_t bw_code_show(struct class *class,
  352. struct class_attribute *attr, char *buf)
  353. {
  354. struct secdp_sysfs_private *sysfs;
  355. struct dp_parser *parser;
  356. struct dp_link *link;
  357. struct dp_link_params *params;
  358. int val = 0, rc = 0;
  359. DP_ENTER("\n");
  360. sysfs = secdp_get_sysfs_private(class);
  361. parser = sysfs->parser;
  362. if (!parser->rf_tx_backoff) {
  363. DP_DEBUG("RF TX backoff not supported\n");
  364. goto exit;
  365. }
  366. if (!secdp_get_cable_status())
  367. goto exit;
  368. if (!secdp_get_hpd_status())
  369. goto exit;
  370. link = sysfs->link;
  371. params = &link->link_params;
  372. switch(params->bw_code) {
  373. case DP_LINK_BW_1_62:
  374. val = 1;
  375. break;
  376. case DP_LINK_BW_2_7:
  377. val = 2;
  378. break;
  379. case DP_LINK_BW_5_4:
  380. val = 4;
  381. break;
  382. case DP_LINK_BW_8_1:
  383. val = 8;
  384. break;
  385. default:
  386. DP_INFO("unknown bw_code %d\n", params->bw_code);
  387. val = 0;
  388. break;
  389. }
  390. DP_INFO("bw %d\n", val);
  391. exit:
  392. rc = snprintf(buf, SZ_32, "%d\n", val);
  393. return rc;
  394. }
  395. static CLASS_ATTR_RO(bw_code);
  396. #endif
  397. #if defined(CONFIG_SECDP_BIGDATA)
  398. static ssize_t dp_error_info_show(struct class *class,
  399. struct class_attribute *attr, char *buf)
  400. {
  401. return _secdp_bigdata_show(class, attr, buf);
  402. }
  403. static ssize_t dp_error_info_store(struct class *dev,
  404. struct class_attribute *attr, const char *buf, size_t size)
  405. {
  406. return _secdp_bigdata_store(dev, attr, buf, size);
  407. }
  408. static CLASS_ATTR_RW(dp_error_info);
  409. #endif
  410. #ifdef SECDP_SELF_TEST
  411. static struct secdp_sef_test_item g_self_test[] = {
  412. {DP_ENUM_STR(ST_CLEAR_CMD), .arg_cnt = 0, .arg_str = "clear all configurations"},
  413. {DP_ENUM_STR(ST_LANE_CNT), .arg_cnt = 1, .arg_str = "lane_count: 1 = 1 lane, 2 = 2 lane, 4 = 4 lane, 555 = disable"},
  414. {DP_ENUM_STR(ST_LINK_RATE), .arg_cnt = 1, .arg_str = "link_rate: 1 = 1.62G , 2 = 2.7G, 3 = 5.4G, 555 = disable"},
  415. {DP_ENUM_STR(ST_CONNECTION_TEST), .arg_cnt = 1, .arg_str = "reconnection time(sec) : range = 5 ~ 50, 555 = disable"},
  416. {DP_ENUM_STR(ST_HDCP_TEST), .arg_cnt = 1, .arg_str = "hdcp on/off time(sec): range = 5 ~ 50, 555 = disable"},
  417. {DP_ENUM_STR(ST_PREEM_TUN), .arg_cnt = 16, .arg_str = "pre-emphasis calibration value, 555 = disable"},
  418. {DP_ENUM_STR(ST_VOLTAGE_TUN), .arg_cnt = 16, .arg_str = "voltage-level calibration value, 555 = disable"},
  419. };
  420. int secdp_self_test_status(int cmd)
  421. {
  422. if (cmd >= ST_MAX)
  423. return -EINVAL;
  424. if (g_self_test[cmd].enabled) {
  425. DP_INFO("%s: %s\n", g_self_test[cmd].cmd_str,
  426. g_self_test[cmd].enabled ? "true" : "false");
  427. }
  428. return g_self_test[cmd].enabled ? g_self_test[cmd].arg_cnt : -1;
  429. }
  430. int *secdp_self_test_get_arg(int cmd)
  431. {
  432. return g_self_test[cmd].arg;
  433. }
  434. #if 0
  435. void secdp_self_register_clear_func(int cmd, void (*func)(void))
  436. {
  437. if (cmd >= ST_MAX)
  438. return;
  439. g_self_test[cmd].clear = func;
  440. DP_INFO("%s: clear func was registered.\n", g_self_test[cmd].cmd_str);
  441. }
  442. #endif
  443. static void secdp_self_test_reconnect_work(struct work_struct *work)
  444. {
  445. struct delayed_work *dw;
  446. struct secdp_misc *sec;
  447. int delay;
  448. static unsigned long test_cnt;
  449. if (!secdp_get_cable_status() || !secdp_get_hpd_status()) {
  450. DP_INFO("cable is out\n");
  451. test_cnt = 0;
  452. return;
  453. }
  454. dw = to_delayed_work(work);
  455. sec = container_of(dw, struct secdp_misc, self_test_reconnect_work);
  456. if (sec->self_test_reconnect_cb)
  457. sec->self_test_reconnect_cb(sec);
  458. test_cnt++;
  459. DP_INFO("test_cnt %lu\n", test_cnt);
  460. delay = g_self_test[ST_CONNECTION_TEST].arg[0];
  461. schedule_delayed_work(&sec->self_test_reconnect_work,
  462. msecs_to_jiffies(delay * 1000));
  463. }
  464. void secdp_self_test_start_reconnect(struct secdp_sysfs *dp_sysfs, void (*func)(struct secdp_misc *sec))
  465. {
  466. struct secdp_sysfs_private *sysfs;
  467. struct secdp_misc *sec;
  468. int delay;
  469. delay = g_self_test[ST_CONNECTION_TEST].arg[0];
  470. if (delay > 50 || delay < 5)
  471. delay = g_self_test[ST_CONNECTION_TEST].arg[0] = 10;
  472. DP_INFO("start reconnect test %d\n", delay);
  473. sysfs = container_of(dp_sysfs, struct secdp_sysfs_private, dp_sysfs);
  474. sec = sysfs->sec;
  475. sec->self_test_reconnect_cb = func;
  476. schedule_delayed_work(&sec->self_test_reconnect_work,
  477. msecs_to_jiffies(delay * 1000));
  478. }
  479. static void secdp_self_test_hdcp_test_work(struct work_struct *work)
  480. {
  481. struct delayed_work *dw;
  482. struct secdp_misc *sec;
  483. int delay;
  484. static unsigned long test_cnt;
  485. if (!secdp_get_cable_status() || !secdp_get_hpd_status()) {
  486. DP_INFO("cable is out\n");
  487. test_cnt = 0;
  488. return;
  489. }
  490. dw = to_delayed_work(work);
  491. sec = container_of(dw, struct secdp_misc, self_test_hdcp_test_work);
  492. if (sec->self_test_hdcp_off_cb)
  493. sec->self_test_hdcp_off_cb();
  494. msleep(3000);
  495. if (sec->self_test_hdcp_on_cb)
  496. sec->self_test_hdcp_on_cb();
  497. test_cnt++;
  498. DP_INFO("test_cnt %lu\n", test_cnt);
  499. delay = g_self_test[ST_HDCP_TEST].arg[0];
  500. schedule_delayed_work(&sec->self_test_hdcp_test_work,
  501. msecs_to_jiffies(delay * 1000));
  502. }
  503. void secdp_self_test_start_hdcp_test(struct secdp_sysfs *dp_sysfs,
  504. void (*func_on)(void), void (*func_off)(void))
  505. {
  506. struct secdp_sysfs_private *sysfs;
  507. struct secdp_misc *sec;
  508. int delay;
  509. delay = g_self_test[ST_HDCP_TEST].arg[0];
  510. if (!delay) {
  511. DP_INFO("hdcp test is aborted\n");
  512. return;
  513. }
  514. if (delay > 50 || delay < 5)
  515. delay = g_self_test[ST_HDCP_TEST].arg[0] = 10;
  516. DP_INFO("start hdcp test %d\n", delay);
  517. sysfs = container_of(dp_sysfs, struct secdp_sysfs_private, dp_sysfs);
  518. sec = sysfs->sec;
  519. sec->self_test_hdcp_on_cb = func_on;
  520. sec->self_test_hdcp_off_cb = func_off;
  521. schedule_delayed_work(&sec->self_test_hdcp_test_work,
  522. msecs_to_jiffies(delay * 1000));
  523. }
  524. static ssize_t dp_self_test_show(struct class *class,
  525. struct class_attribute *attr, char *buf)
  526. {
  527. int i, j, rc = 0;
  528. for (i = 0; i < ST_MAX; i++) {
  529. rc += scnprintf(buf + rc, PAGE_SIZE - rc,
  530. "%d. %s: %s\n ==>", i,
  531. g_self_test[i].cmd_str, g_self_test[i].arg_str);
  532. if (g_self_test[i].enabled) {
  533. rc += scnprintf(buf + rc, PAGE_SIZE - rc,
  534. "current value: enabled - arg: ");
  535. for (j = 0; j < g_self_test[i].arg_cnt; j++) {
  536. rc += scnprintf(buf + rc, PAGE_SIZE - rc,
  537. "0x%x ", g_self_test[i].arg[j]);
  538. }
  539. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "\n\n");
  540. } else {
  541. rc += scnprintf(buf + rc, PAGE_SIZE - rc,
  542. "current value: disabled\n\n");
  543. }
  544. }
  545. return rc;
  546. }
  547. static void dp_self_test_clear_func(int cmd)
  548. {
  549. int arg_cnt = (g_self_test[cmd].arg_cnt < ST_ARG_CNT) ? g_self_test[cmd].arg_cnt : ST_ARG_CNT;
  550. g_self_test[cmd].enabled = false;
  551. memset(g_self_test[cmd].arg, 0, sizeof(int) * arg_cnt);
  552. if (g_self_test[cmd].clear)
  553. g_self_test[cmd].clear();
  554. }
  555. static ssize_t dp_self_test_store(struct class *dev,
  556. struct class_attribute *attr, const char *buf, size_t size)
  557. {
  558. int val[ST_ARG_CNT + 2] = {0, };
  559. int arg, arg_cnt, cmd, i;
  560. if (secdp_check_store_args(buf, size)) {
  561. DP_ERR("args error!\n");
  562. goto end;
  563. }
  564. get_options(buf, ARRAY_SIZE(val), val);
  565. cmd = val[1];
  566. arg = val[2];
  567. if (cmd < 0 || cmd >= ST_MAX) {
  568. DP_INFO("invalid cmd\n");
  569. goto end;
  570. }
  571. if (cmd == ST_CLEAR_CMD) {
  572. for (i = 1; i < ST_MAX; i++)
  573. dp_self_test_clear_func(i);
  574. DP_INFO("cmd: ST_CLEAR_CMD\n");
  575. goto end;
  576. }
  577. g_self_test[cmd].enabled = (arg == ST_TEST_EXIT) ? false : true;
  578. if (g_self_test[cmd].enabled) {
  579. if ((val[0] - 1) != g_self_test[cmd].arg_cnt) {
  580. DP_INFO("invalid param.\n");
  581. goto end;
  582. }
  583. arg_cnt = (g_self_test[cmd].arg_cnt < ST_ARG_CNT) ? g_self_test[cmd].arg_cnt : ST_ARG_CNT;
  584. memcpy(g_self_test[cmd].arg, val + 2, sizeof(int) * arg_cnt);
  585. } else {
  586. dp_self_test_clear_func(cmd);
  587. }
  588. DP_INFO("cmd: %d. %s, enable:%s\n", cmd,
  589. (cmd < ST_MAX) ? g_self_test[cmd].cmd_str : "null",
  590. (cmd < ST_MAX) ? (g_self_test[cmd].enabled ? "true" : "false") : "null");
  591. end:
  592. return size;
  593. }
  594. static CLASS_ATTR_RW(dp_self_test);
  595. #endif
  596. #if defined(CONFIG_SECDP_DBG)
  597. bool secdp_func_trace;
  598. #define SECDP_FUNC_TRACE "func_trace" //ex) echo "func_trace,1" > dp_debug
  599. #define SECDP_SSC_ONOFF "ssc" //ex) echo "ssc,1" > dp_debug
  600. static ssize_t dp_debug_show(struct class *class,
  601. struct class_attribute *attr, char *buf)
  602. {
  603. struct secdp_sysfs_private *sysfs;
  604. struct secdp_misc *sec;
  605. struct secdp_dex *dex;
  606. char tmp[SZ_1K] = {0,};
  607. int rc = 0;
  608. sysfs = secdp_get_sysfs_private(class);
  609. sec = sysfs->sec;
  610. dex = &sec->dex;
  611. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "==========\n");
  612. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "[dbg] func_trace: %d\n", secdp_func_trace);
  613. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "[dex] adapter_check_skip: %d\n", dex->adapter_check_skip);
  614. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "[psm] extdisp_off: %d\n", sec->extdisp_off);
  615. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "[ssc] ssc_en: %d\n", secdp_debug_get_ssc(sec));
  616. secdp_show_hmd_dev(sysfs->sec, tmp);
  617. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "\n< HMD >\n%s\n", tmp);
  618. memset(tmp, 0, ARRAY_SIZE(tmp));
  619. secdp_show_phy_param(sysfs->parser, tmp);
  620. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "\n< DP-PHY >\n%s\n", tmp);
  621. memset(tmp, 0, ARRAY_SIZE(tmp));
  622. secdp_show_link_param(sysfs->link, tmp);
  623. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "\n< link params >\n%s\n", tmp);
  624. #if IS_ENABLED(CONFIG_COMBO_REDRIVER_PS5169)
  625. memset(tmp, 0, ARRAY_SIZE(tmp));
  626. secdp_show_ps5169_param(sysfs->parser, tmp);
  627. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "\n< PS5169 EQ0/EQ1 >\n%s\n", tmp);
  628. #endif
  629. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "==========\n");
  630. return rc;
  631. }
  632. static ssize_t dp_debug_store(struct class *class,
  633. struct class_attribute *attr, const char *buf, size_t size)
  634. {
  635. struct secdp_sysfs_private *sysfs;
  636. struct secdp_misc *sec;
  637. char str[MAX_DEX_STORE_LEN] = {0,}, *p, *tok;
  638. int len, val[10] = {0, };
  639. if (size >= MAX_DEX_STORE_LEN) {
  640. DP_ERR("too long args! %lu\n", size);
  641. goto exit;
  642. }
  643. if (secdp_check_store_args(buf, size)) {
  644. DP_ERR("args error!\n");
  645. goto exit;
  646. }
  647. sysfs = secdp_get_sysfs_private(class);
  648. sec = sysfs->sec;
  649. get_options(buf, ARRAY_SIZE(val), val);
  650. memcpy(str, buf, size);
  651. p = str;
  652. tok = strsep(&p, ",");
  653. if (!p) {
  654. DP_ERR("error: no token found\n");
  655. goto exit;
  656. }
  657. len = strlen(tok);
  658. if (!len) {
  659. DP_ERR("error: token len is zero\n");
  660. goto exit;
  661. }
  662. DP_DEBUG("tok:%s, len:%d\n", tok, len);
  663. if (len && !strncmp(SECDP_FUNC_TRACE, tok, len)) {
  664. int param = 0, sz = 0, ret;
  665. tok = strsep(&p, ",");
  666. if (!tok) {
  667. DP_ERR("wrong input!\n");
  668. goto exit;
  669. }
  670. sz = strlen(tok);
  671. ret = kstrtouint(tok, 2, &param);
  672. if (ret) {
  673. DP_ERR("error:%d\n", ret);
  674. goto exit;
  675. }
  676. DP_DEBUG("[%s] param:%d sz:%d ret:%d\n", SECDP_FUNC_TRACE,
  677. param, sz, ret);
  678. secdp_func_trace = param ? 1 : 0;
  679. goto exit;
  680. }
  681. if (len && !strncmp(SECDP_SSC_ONOFF, tok, len)) {
  682. int param = 0, sz = 0, ret;
  683. tok = strsep(&p, ",");
  684. if (!tok) {
  685. DP_ERR("wrong input!\n");
  686. goto exit;
  687. }
  688. sz = strlen(tok);
  689. ret = kstrtouint(tok, 2, &param);
  690. if (ret) {
  691. DP_ERR("error:%d\n", ret);
  692. goto exit;
  693. }
  694. DP_DEBUG("[%s] param:%d sz:%d ret:%d\n", SECDP_SSC_ONOFF,
  695. param, sz, ret);
  696. secdp_debug_set_ssc(sec, param ? true : false);
  697. goto exit;
  698. }
  699. exit:
  700. return size;
  701. }
  702. static CLASS_ATTR_RW(dp_debug);
  703. static ssize_t dp_unit_test_show(struct class *class,
  704. struct class_attribute *attr, char *buf)
  705. {
  706. struct secdp_sysfs_private *sysfs;
  707. int rc, cmd;
  708. bool res = false;
  709. sysfs = secdp_get_sysfs_private(class);
  710. cmd = sysfs->test_cmd;
  711. DP_INFO("test_cmd: %s\n", secdp_utcmd_to_str(cmd));
  712. switch (cmd) {
  713. case SECDP_UTCMD_EDID_PARSE:
  714. res = secdp_unit_test_edid_parse();
  715. break;
  716. default:
  717. DP_INFO("invalid test_cmd: %d\n", cmd);
  718. break;
  719. }
  720. rc = scnprintf(buf, 3, "%d\n", res ? 1 : 0);
  721. return rc;
  722. }
  723. static ssize_t dp_unit_test_store(struct class *class,
  724. struct class_attribute *attr, const char *buf, size_t size)
  725. {
  726. struct secdp_sysfs_private *sysfs;
  727. int val[10] = {0, };
  728. if (secdp_check_store_args(buf, size)) {
  729. DP_ERR("args error!\n");
  730. goto exit;
  731. }
  732. sysfs = secdp_get_sysfs_private(class);
  733. get_options(buf, ARRAY_SIZE(val), val);
  734. sysfs->test_cmd = val[1];
  735. DP_INFO("test_cmd: %d...%s\n", sysfs->test_cmd,
  736. secdp_utcmd_to_str(sysfs->test_cmd));
  737. exit:
  738. return size;
  739. }
  740. static CLASS_ATTR_RW(dp_unit_test);
  741. static ssize_t dp_aux_cfg_show(struct class *class,
  742. struct class_attribute *attr, char *buf)
  743. {
  744. struct secdp_sysfs_private *sysfs;
  745. char tmp[SZ_1K] = {0,};
  746. int rc = 0;
  747. sysfs = secdp_get_sysfs_private(class);
  748. secdp_aux_cfg_show(sysfs->parser, tmp);
  749. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "\n< AUX cfg >\n%s\n", tmp);
  750. return rc;
  751. }
  752. static ssize_t dp_aux_cfg_store(struct class *class,
  753. struct class_attribute *attr, const char *buf, size_t size)
  754. {
  755. struct secdp_sysfs_private *sysfs;
  756. char tmp[SZ_1K] = {0,};
  757. sysfs = secdp_get_sysfs_private(class);
  758. memcpy(tmp, buf, min(ARRAY_SIZE(tmp) - 1, size));
  759. secdp_aux_cfg_store(sysfs->parser, tmp);
  760. return size;
  761. }
  762. static CLASS_ATTR_RW(dp_aux_cfg);
  763. static ssize_t dp_preshoot_show(struct class *class,
  764. struct class_attribute *attr, char *buf)
  765. {
  766. struct secdp_sysfs_private *sysfs;
  767. char tmp[SZ_64] = {0,};
  768. int rc = 0;
  769. sysfs = secdp_get_sysfs_private(class);
  770. secdp_catalog_preshoot_show(sysfs->catalog, tmp);
  771. rc = snprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  772. return rc;
  773. }
  774. static ssize_t dp_preshoot_store(struct class *class,
  775. struct class_attribute *attr, const char *buf, size_t size)
  776. {
  777. struct secdp_sysfs_private *sysfs;
  778. char tmp[SZ_64] = {0,};
  779. int len = min(sizeof(tmp), size);
  780. if (!len || len >= SZ_64) {
  781. DP_ERR("wrong length! %d\n", len);
  782. goto end;
  783. }
  784. sysfs = secdp_get_sysfs_private(class);
  785. memcpy(tmp, buf, len);
  786. tmp[SZ_64 - 1] = '\0';
  787. secdp_catalog_preshoot_store(sysfs->catalog, tmp);
  788. end:
  789. return size;
  790. }
  791. static CLASS_ATTR_RW(dp_preshoot);
  792. static ssize_t dp_hbr2_3_voltage_swing_show(struct class *class,
  793. struct class_attribute *attr, char *buf)
  794. {
  795. struct secdp_sysfs_private *sysfs;
  796. char tmp[SZ_1K] = {0,};
  797. int rc = 0;
  798. sysfs = secdp_get_sysfs_private(class);
  799. secdp_parse_vxpx_show(sysfs->parser, DP_LR_HBR2_3, DP_PARAM_VX, tmp);
  800. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  801. return rc;
  802. }
  803. static ssize_t dp_hbr2_3_voltage_swing_store(struct class *class,
  804. struct class_attribute *attr, const char *buf, size_t size)
  805. {
  806. struct secdp_sysfs_private *sysfs;
  807. char tmp[SZ_64] = {0,};
  808. int len = min(sizeof(tmp), size);
  809. if (!len || len >= SZ_64) {
  810. DP_ERR("wrong length! %d\n", len);
  811. goto end;
  812. }
  813. sysfs = secdp_get_sysfs_private(class);
  814. memcpy(tmp, buf, len);
  815. tmp[SZ_64 - 1] = '\0';
  816. secdp_parse_vxpx_store(sysfs->parser, DP_LR_HBR2_3, DP_PARAM_VX, tmp);
  817. end:
  818. return size;
  819. }
  820. static CLASS_ATTR_RW(dp_hbr2_3_voltage_swing);
  821. static ssize_t dp_hbr2_3_pre_emphasis_show(struct class *class,
  822. struct class_attribute *attr, char *buf)
  823. {
  824. struct secdp_sysfs_private *sysfs;
  825. char tmp[SZ_1K] = {0,};
  826. int rc = 0;
  827. sysfs = secdp_get_sysfs_private(class);
  828. secdp_parse_vxpx_show(sysfs->parser, DP_LR_HBR2_3, DP_PARAM_PX, tmp);
  829. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  830. return rc;
  831. }
  832. static ssize_t dp_hbr2_3_pre_emphasis_store(struct class *class,
  833. struct class_attribute *attr, const char *buf, size_t size)
  834. {
  835. struct secdp_sysfs_private *sysfs;
  836. char tmp[SZ_64] = {0,};
  837. int len = min(sizeof(tmp), size);
  838. if (!len || len >= SZ_64) {
  839. DP_ERR("wrong length! %d\n", len);
  840. goto end;
  841. }
  842. sysfs = secdp_get_sysfs_private(class);
  843. memcpy(tmp, buf, len);
  844. tmp[SZ_64 - 1] = '\0';
  845. secdp_parse_vxpx_store(sysfs->parser, DP_LR_HBR2_3, DP_PARAM_PX, tmp);
  846. end:
  847. return size;
  848. }
  849. static CLASS_ATTR_RW(dp_hbr2_3_pre_emphasis);
  850. static ssize_t dp_hbr_rbr_voltage_swing_show(struct class *class,
  851. struct class_attribute *attr, char *buf)
  852. {
  853. struct secdp_sysfs_private *sysfs;
  854. char tmp[SZ_1K] = {0,};
  855. int rc = 0;
  856. sysfs = secdp_get_sysfs_private(class);
  857. secdp_parse_vxpx_show(sysfs->parser, DP_LR_HBR_RBR, DP_PARAM_VX, tmp);
  858. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  859. return rc;
  860. }
  861. static ssize_t dp_hbr_rbr_voltage_swing_store(struct class *class,
  862. struct class_attribute *attr, const char *buf, size_t size)
  863. {
  864. struct secdp_sysfs_private *sysfs;
  865. char tmp[SZ_64] = {0,};
  866. int len = min(sizeof(tmp), size);
  867. if (!len || len >= SZ_64) {
  868. DP_ERR("wrong length! %d\n", len);
  869. goto end;
  870. }
  871. sysfs = secdp_get_sysfs_private(class);
  872. memcpy(tmp, buf, len);
  873. tmp[SZ_64 - 1] = '\0';
  874. secdp_parse_vxpx_store(sysfs->parser, DP_LR_HBR_RBR, DP_PARAM_VX, tmp);
  875. end:
  876. return size;
  877. }
  878. static CLASS_ATTR_RW(dp_hbr_rbr_voltage_swing);
  879. static ssize_t dp_hbr_rbr_pre_emphasis_show(struct class *class,
  880. struct class_attribute *attr, char *buf)
  881. {
  882. struct secdp_sysfs_private *sysfs;
  883. char tmp[SZ_1K] = {0,};
  884. int rc = 0;
  885. sysfs = secdp_get_sysfs_private(class);
  886. secdp_parse_vxpx_show(sysfs->parser, DP_LR_HBR_RBR, DP_PARAM_PX, tmp);
  887. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  888. return rc;
  889. }
  890. static ssize_t dp_hbr_rbr_pre_emphasis_store(struct class *class,
  891. struct class_attribute *attr, const char *buf, size_t size)
  892. {
  893. struct secdp_sysfs_private *sysfs;
  894. char tmp[SZ_64] = {0,};
  895. int len = min(sizeof(tmp), size);
  896. if (!len || len >= SZ_64) {
  897. DP_ERR("wrong length! %d\n", len);
  898. goto end;
  899. }
  900. sysfs = secdp_get_sysfs_private(class);
  901. memcpy(tmp, buf, len);
  902. tmp[SZ_64 - 1] = '\0';
  903. secdp_parse_vxpx_store(sysfs->parser, DP_LR_HBR_RBR, DP_PARAM_PX, tmp);
  904. end:
  905. return size;
  906. }
  907. static CLASS_ATTR_RW(dp_hbr_rbr_pre_emphasis);
  908. static ssize_t dp_pref_skip_show(struct class *class,
  909. struct class_attribute *attr, char *buf)
  910. {
  911. struct secdp_sysfs_private *sysfs;
  912. int skip, rc;
  913. DP_ENTER("\n");
  914. sysfs = secdp_get_sysfs_private(class);
  915. skip = sysfs->sec->debug.prefer_check_skip;
  916. rc = snprintf(buf, SZ_8, "%d\n", skip);
  917. return rc;
  918. }
  919. static ssize_t dp_pref_skip_store(struct class *class,
  920. struct class_attribute *attr, const char *buf, size_t size)
  921. {
  922. struct secdp_sysfs_private *sysfs;
  923. int i, val[30] = {0, };
  924. if (secdp_check_store_args(buf, size)) {
  925. DP_ERR("args error!\n");
  926. goto exit;
  927. }
  928. DP_DEBUG("size:%d\n", (int)size);
  929. get_options(buf, ARRAY_SIZE(val), val);
  930. for (i = 0; i < 16; i = i + 4) {
  931. DP_DEBUG("%02x,%02x,%02x,%02x\n",
  932. val[i+1], val[i+2], val[i+3], val[i+4]);
  933. }
  934. sysfs = secdp_get_sysfs_private(class);
  935. sysfs->sec->debug.prefer_check_skip = val[1];
  936. exit:
  937. return size;
  938. }
  939. static CLASS_ATTR_RW(dp_pref_skip);
  940. static ssize_t dp_pref_ratio_show(struct class *class,
  941. struct class_attribute *attr, char *buf)
  942. {
  943. struct secdp_sysfs_private *sysfs;
  944. int ratio, rc;
  945. DP_ENTER("\n");
  946. sysfs = secdp_get_sysfs_private(class);
  947. ratio = sysfs->sec->prefer.ratio;
  948. rc = snprintf(buf, SZ_8, "%d\n", ratio);
  949. return rc;
  950. }
  951. static ssize_t dp_pref_ratio_store(struct class *class,
  952. struct class_attribute *attr, const char *buf, size_t size)
  953. {
  954. struct secdp_sysfs_private *sysfs;
  955. int i, val[30] = {0, };
  956. if (secdp_check_store_args(buf, size)) {
  957. DP_ERR("args error!\n");
  958. goto exit;
  959. }
  960. DP_DEBUG("size:%d\n", (int)size);
  961. get_options(buf, ARRAY_SIZE(val), val);
  962. for (i = 0; i < 16; i = i + 4) {
  963. DP_DEBUG("%02x,%02x,%02x,%02x\n",
  964. val[i+1], val[i+2], val[i+3], val[i+4]);
  965. }
  966. sysfs = secdp_get_sysfs_private(class);
  967. sysfs->sec->prefer.ratio = val[1];
  968. exit:
  969. return size;
  970. }
  971. static CLASS_ATTR_RW(dp_pref_ratio);
  972. #if IS_ENABLED(CONFIG_COMBO_REDRIVER_PS5169)
  973. static ssize_t dp_ps5169_rbr_eq0_show(struct class *class,
  974. struct class_attribute *attr, char *buf)
  975. {
  976. struct secdp_sysfs_private *sysfs;
  977. char tmp[SZ_1K] = {0,};
  978. int rc = 0;
  979. sysfs = secdp_get_sysfs_private(class);
  980. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_RBR, tmp);
  981. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  982. return rc;
  983. }
  984. static ssize_t dp_ps5169_rbr_eq0_store(struct class *class,
  985. struct class_attribute *attr, const char *buf, size_t size)
  986. {
  987. struct secdp_sysfs_private *sysfs;
  988. char tmp[SZ_64] = {0,};
  989. int len = min(sizeof(tmp), size);
  990. if (!len || len >= SZ_64) {
  991. DP_ERR("wrong length! %d\n", len);
  992. goto end;
  993. }
  994. sysfs = secdp_get_sysfs_private(class);
  995. memcpy(tmp, buf, len);
  996. tmp[SZ_64 - 1] = '\0';
  997. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_RBR, tmp);
  998. end:
  999. return size;
  1000. }
  1001. static CLASS_ATTR_RW(dp_ps5169_rbr_eq0);
  1002. static ssize_t dp_ps5169_rbr_eq1_show(struct class *class,
  1003. struct class_attribute *attr, char *buf)
  1004. {
  1005. struct secdp_sysfs_private *sysfs;
  1006. char tmp[SZ_1K] = {0,};
  1007. int rc = 0;
  1008. sysfs = secdp_get_sysfs_private(class);
  1009. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_RBR, tmp);
  1010. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1011. return rc;
  1012. }
  1013. static ssize_t dp_ps5169_rbr_eq1_store(struct class *class,
  1014. struct class_attribute *attr, const char *buf, size_t size)
  1015. {
  1016. struct secdp_sysfs_private *sysfs;
  1017. char tmp[SZ_64] = {0,};
  1018. int len = min(sizeof(tmp), size);
  1019. if (!len || len >= SZ_64) {
  1020. DP_ERR("wrong length! %d\n", len);
  1021. goto end;
  1022. }
  1023. sysfs = secdp_get_sysfs_private(class);
  1024. memcpy(tmp, buf, len);
  1025. tmp[SZ_64 - 1] = '\0';
  1026. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_RBR, tmp);
  1027. end:
  1028. return size;
  1029. }
  1030. static CLASS_ATTR_RW(dp_ps5169_rbr_eq1);
  1031. static ssize_t dp_ps5169_hbr_eq0_show(struct class *class,
  1032. struct class_attribute *attr, char *buf)
  1033. {
  1034. struct secdp_sysfs_private *sysfs;
  1035. char tmp[SZ_1K] = {0,};
  1036. int rc = 0;
  1037. sysfs = secdp_get_sysfs_private(class);
  1038. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_HBR, tmp);
  1039. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1040. return rc;
  1041. }
  1042. static ssize_t dp_ps5169_hbr_eq0_store(struct class *class,
  1043. struct class_attribute *attr, const char *buf, size_t size)
  1044. {
  1045. struct secdp_sysfs_private *sysfs;
  1046. char tmp[SZ_64] = {0,};
  1047. int len = min(sizeof(tmp), size);
  1048. if (!len || len >= SZ_64) {
  1049. DP_ERR("wrong length! %d\n", len);
  1050. goto end;
  1051. }
  1052. sysfs = secdp_get_sysfs_private(class);
  1053. memcpy(tmp, buf, len);
  1054. tmp[SZ_64 - 1] = '\0';
  1055. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_HBR, tmp);
  1056. end:
  1057. return size;
  1058. }
  1059. static CLASS_ATTR_RW(dp_ps5169_hbr_eq0);
  1060. static ssize_t dp_ps5169_hbr_eq1_show(struct class *class,
  1061. struct class_attribute *attr, char *buf)
  1062. {
  1063. struct secdp_sysfs_private *sysfs;
  1064. char tmp[SZ_1K] = {0,};
  1065. int rc = 0;
  1066. sysfs = secdp_get_sysfs_private(class);
  1067. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_HBR, tmp);
  1068. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1069. return rc;
  1070. }
  1071. static ssize_t dp_ps5169_hbr_eq1_store(struct class *class,
  1072. struct class_attribute *attr, const char *buf, size_t size)
  1073. {
  1074. struct secdp_sysfs_private *sysfs;
  1075. char tmp[SZ_64] = {0,};
  1076. int len = min(sizeof(tmp), size);
  1077. if (!len || len >= SZ_64) {
  1078. DP_ERR("wrong length! %d\n", len);
  1079. goto end;
  1080. }
  1081. sysfs = secdp_get_sysfs_private(class);
  1082. memcpy(tmp, buf, len);
  1083. tmp[SZ_64 - 1] = '\0';
  1084. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_HBR, tmp);
  1085. end:
  1086. return size;
  1087. }
  1088. static CLASS_ATTR_RW(dp_ps5169_hbr_eq1);
  1089. static ssize_t dp_ps5169_hbr2_eq0_show(struct class *class,
  1090. struct class_attribute *attr, char *buf)
  1091. {
  1092. struct secdp_sysfs_private *sysfs;
  1093. char tmp[SZ_1K] = {0,};
  1094. int rc = 0;
  1095. sysfs = secdp_get_sysfs_private(class);
  1096. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_HBR2, tmp);
  1097. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1098. return rc;
  1099. }
  1100. static ssize_t dp_ps5169_hbr2_eq0_store(struct class *class,
  1101. struct class_attribute *attr, const char *buf, size_t size)
  1102. {
  1103. struct secdp_sysfs_private *sysfs;
  1104. char tmp[SZ_64] = {0,};
  1105. int len = min(sizeof(tmp), size);
  1106. if (!len || len >= SZ_64) {
  1107. DP_ERR("wrong length! %d\n", len);
  1108. goto end;
  1109. }
  1110. sysfs = secdp_get_sysfs_private(class);
  1111. memcpy(tmp, buf, len);
  1112. tmp[SZ_64 - 1] = '\0';
  1113. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_HBR2, tmp);
  1114. end:
  1115. return size;
  1116. }
  1117. static CLASS_ATTR_RW(dp_ps5169_hbr2_eq0);
  1118. static ssize_t dp_ps5169_hbr2_eq1_show(struct class *class,
  1119. struct class_attribute *attr, char *buf)
  1120. {
  1121. struct secdp_sysfs_private *sysfs;
  1122. char tmp[SZ_1K] = {0,};
  1123. int rc = 0;
  1124. sysfs = secdp_get_sysfs_private(class);
  1125. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_HBR2, tmp);
  1126. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1127. return rc;
  1128. }
  1129. static ssize_t dp_ps5169_hbr2_eq1_store(struct class *class,
  1130. struct class_attribute *attr, const char *buf, size_t size)
  1131. {
  1132. struct secdp_sysfs_private *sysfs;
  1133. char tmp[SZ_64] = {0,};
  1134. int len = min(sizeof(tmp), size);
  1135. if (!len || len >= SZ_64) {
  1136. DP_ERR("wrong length! %d\n", len);
  1137. goto end;
  1138. }
  1139. sysfs = secdp_get_sysfs_private(class);
  1140. memcpy(tmp, buf, len);
  1141. tmp[SZ_64 - 1] = '\0';
  1142. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_HBR2, tmp);
  1143. end:
  1144. return size;
  1145. }
  1146. static CLASS_ATTR_RW(dp_ps5169_hbr2_eq1);
  1147. static ssize_t dp_ps5169_hbr3_eq0_show(struct class *class,
  1148. struct class_attribute *attr, char *buf)
  1149. {
  1150. struct secdp_sysfs_private *sysfs;
  1151. char tmp[SZ_1K] = {0,};
  1152. int rc = 0;
  1153. sysfs = secdp_get_sysfs_private(class);
  1154. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_HBR3, tmp);
  1155. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1156. return rc;
  1157. }
  1158. static ssize_t dp_ps5169_hbr3_eq0_store(struct class *class,
  1159. struct class_attribute *attr, const char *buf, size_t size)
  1160. {
  1161. struct secdp_sysfs_private *sysfs;
  1162. char tmp[SZ_64] = {0,};
  1163. int len = min(sizeof(tmp), size);
  1164. if (!len || len >= SZ_64) {
  1165. DP_ERR("wrong length! %d\n", len);
  1166. goto end;
  1167. }
  1168. sysfs = secdp_get_sysfs_private(class);
  1169. memcpy(tmp, buf, len);
  1170. tmp[SZ_64 - 1] = '\0';
  1171. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ0, DP_PS5169_RATE_HBR3, tmp);
  1172. end:
  1173. return size;
  1174. }
  1175. static CLASS_ATTR_RW(dp_ps5169_hbr3_eq0);
  1176. static ssize_t dp_ps5169_hbr3_eq1_show(struct class *class,
  1177. struct class_attribute *attr, char *buf)
  1178. {
  1179. struct secdp_sysfs_private *sysfs;
  1180. char tmp[SZ_1K] = {0,};
  1181. int rc = 0;
  1182. sysfs = secdp_get_sysfs_private(class);
  1183. secdp_parse_ps5169_show(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_HBR3, tmp);
  1184. rc += scnprintf(buf + rc, PAGE_SIZE - rc, "%s\n", tmp);
  1185. return rc;
  1186. }
  1187. static ssize_t dp_ps5169_hbr3_eq1_store(struct class *class,
  1188. struct class_attribute *attr, const char *buf, size_t size)
  1189. {
  1190. struct secdp_sysfs_private *sysfs;
  1191. char tmp[SZ_64] = {0,};
  1192. int len = min(sizeof(tmp), size);
  1193. if (!len || len >= SZ_64) {
  1194. DP_ERR("wrong length! %d\n", len);
  1195. goto end;
  1196. }
  1197. sysfs = secdp_get_sysfs_private(class);
  1198. memcpy(tmp, buf, len);
  1199. tmp[SZ_64 - 1] = '\0';
  1200. secdp_parse_ps5169_store(sysfs->parser, DP_PS5169_EQ1, DP_PS5169_RATE_HBR3, tmp);
  1201. end:
  1202. return size;
  1203. }
  1204. static CLASS_ATTR_RW(dp_ps5169_hbr3_eq1);
  1205. #endif/*CONFIG_COMBO_REDRIVER_PS5169*/
  1206. #endif/*CONFIG_SECDP_DBG*/
  1207. enum {
  1208. DEX = 0,
  1209. DEX_VER,
  1210. MONITOR_INFO,
  1211. #ifdef SYSFS_BW_CODE
  1212. BW_CODE,
  1213. #endif
  1214. #if defined(CONFIG_SECDP_BIGDATA)
  1215. DP_ERROR_INFO,
  1216. #endif
  1217. #if defined(CONFIG_SECDP_FACTORY_DPSWITCH_TEST)
  1218. DP_SBU_SW_SEL,
  1219. #endif
  1220. #ifdef SECDP_SELF_TEST
  1221. DP_SELF_TEST,
  1222. #endif
  1223. #if defined(CONFIG_SECDP_DBG)
  1224. DP_DBG,
  1225. DP_UNIT_TEST,
  1226. DP_AUX_CFG,
  1227. DP_PRESHOOT,
  1228. DP_HBR2_3_VOLTAGE_SWING,
  1229. DP_HBR2_3_PRE_EMPHASIS,
  1230. DP_HBR_RBR_VOLTAGE_SWING,
  1231. DP_HBR_RBR_PRE_EMPHASIS,
  1232. DP_PREF_SKIP,
  1233. DP_PREF_RATIO,
  1234. #if IS_ENABLED(CONFIG_COMBO_REDRIVER_PS5169)
  1235. DP_PS5169_RBR_EQ0,
  1236. DP_PS5169_RBR_EQ1,
  1237. DP_PS5169_HBR_EQ0,
  1238. DP_PS5169_HBR_EQ1,
  1239. DP_PS5169_HBR2_EQ0,
  1240. DP_PS5169_HBR2_EQ1,
  1241. DP_PS5169_HBR3_EQ0,
  1242. DP_PS5169_HBR3_EQ1,
  1243. #endif/*CONFIG_COMBO_REDRIVER_PS5169*/
  1244. #endif
  1245. };
  1246. static struct attribute *secdp_class_attrs[] = {
  1247. [DEX] = &class_attr_dex.attr,
  1248. [DEX_VER] = &class_attr_dex_ver.attr,
  1249. [MONITOR_INFO] = &class_attr_monitor_info.attr,
  1250. #ifdef SYSFS_BW_CODE
  1251. [BW_CODE] = &class_attr_bw_code.attr,
  1252. #endif
  1253. #if defined(CONFIG_SECDP_BIGDATA)
  1254. [DP_ERROR_INFO] = &class_attr_dp_error_info.attr,
  1255. #endif
  1256. #if defined(CONFIG_SECDP_FACTORY_DPSWITCH_TEST)
  1257. [DP_SBU_SW_SEL] = &class_attr_dp_sbu_sw_sel.attr,
  1258. #endif
  1259. #ifdef SECDP_SELF_TEST
  1260. [DP_SELF_TEST] = &class_attr_dp_self_test.attr,
  1261. #endif
  1262. #if defined(CONFIG_SECDP_DBG)
  1263. [DP_DBG] = &class_attr_dp_debug.attr,
  1264. [DP_UNIT_TEST] = &class_attr_dp_unit_test.attr,
  1265. [DP_AUX_CFG] = &class_attr_dp_aux_cfg.attr,
  1266. [DP_PRESHOOT] = &class_attr_dp_preshoot.attr,
  1267. [DP_HBR_RBR_VOLTAGE_SWING] = &class_attr_dp_hbr_rbr_voltage_swing.attr,
  1268. [DP_HBR_RBR_PRE_EMPHASIS] = &class_attr_dp_hbr_rbr_pre_emphasis.attr,
  1269. [DP_HBR2_3_VOLTAGE_SWING] = &class_attr_dp_hbr2_3_voltage_swing.attr,
  1270. [DP_HBR2_3_PRE_EMPHASIS] = &class_attr_dp_hbr2_3_pre_emphasis.attr,
  1271. [DP_PREF_SKIP] = &class_attr_dp_pref_skip.attr,
  1272. [DP_PREF_RATIO] = &class_attr_dp_pref_ratio.attr,
  1273. #if IS_ENABLED(CONFIG_COMBO_REDRIVER_PS5169)
  1274. [DP_PS5169_RBR_EQ0] = &class_attr_dp_ps5169_rbr_eq0.attr,
  1275. [DP_PS5169_RBR_EQ1] = &class_attr_dp_ps5169_rbr_eq1.attr,
  1276. [DP_PS5169_HBR_EQ0] = &class_attr_dp_ps5169_hbr_eq0.attr,
  1277. [DP_PS5169_HBR_EQ1] = &class_attr_dp_ps5169_hbr_eq1.attr,
  1278. [DP_PS5169_HBR2_EQ0] = &class_attr_dp_ps5169_hbr2_eq0.attr,
  1279. [DP_PS5169_HBR2_EQ1] = &class_attr_dp_ps5169_hbr2_eq1.attr,
  1280. [DP_PS5169_HBR3_EQ0] = &class_attr_dp_ps5169_hbr3_eq0.attr,
  1281. [DP_PS5169_HBR3_EQ1] = &class_attr_dp_ps5169_hbr3_eq1.attr,
  1282. #endif/*CONFIG_COMBO_REDRIVER_PS5169*/
  1283. #endif
  1284. NULL,
  1285. };
  1286. ATTRIBUTE_GROUPS(secdp_class);
  1287. struct secdp_sysfs *secdp_sysfs_get(struct secdp_sysfs_in *in)
  1288. {
  1289. struct class *dp_class = NULL;
  1290. struct secdp_sysfs_private *sysfs = NULL;
  1291. struct secdp_sysfs *dp_sysfs;
  1292. int rc = 0;
  1293. if (!in) {
  1294. DP_ERR("invalid input\n");
  1295. rc = -EINVAL;
  1296. goto error;
  1297. }
  1298. sysfs = devm_kzalloc(in->dev, sizeof(*sysfs), GFP_KERNEL);
  1299. if (!sysfs) {
  1300. rc = -EINVAL;
  1301. DP_ERR("alloc failed %d\n", rc);
  1302. goto error;
  1303. }
  1304. sysfs->dev = in->dev;
  1305. sysfs->parser = in->parser;
  1306. sysfs->power = in->power;
  1307. sysfs->panel = in->panel;
  1308. sysfs->link = in->link;
  1309. sysfs->ctrl = in->ctrl;
  1310. sysfs->catalog = in->catalog;
  1311. sysfs->sec = in->sec;
  1312. dp_sysfs = &sysfs->dp_sysfs;
  1313. dp_class = &dp_sysfs->dp_class;
  1314. dp_class->name = "dp_sec";
  1315. dp_class->owner = THIS_MODULE;
  1316. dp_class->class_groups = secdp_class_groups;
  1317. rc = class_register(dp_class);
  1318. if (rc) {
  1319. DP_ERR("cannot register dp_class %d\n", rc);
  1320. goto free_class;
  1321. }
  1322. #if defined(CONFIG_SECDP_BIGDATA)
  1323. secdp_bigdata_init(dp_class);
  1324. #endif
  1325. #ifdef SECDP_SELF_TEST
  1326. INIT_DELAYED_WORK(&sysfs->sec->self_test_reconnect_work,
  1327. secdp_self_test_reconnect_work);
  1328. INIT_DELAYED_WORK(&sysfs->sec->self_test_hdcp_test_work,
  1329. secdp_self_test_hdcp_test_work);
  1330. #endif
  1331. DP_DEBUG("success\n");
  1332. return dp_sysfs;
  1333. free_class:
  1334. devm_kfree(in->dev, sysfs);
  1335. error:
  1336. return ERR_PTR(rc);
  1337. }
  1338. void secdp_sysfs_put(struct device *dev, struct secdp_sysfs *dp_sysfs)
  1339. {
  1340. struct secdp_sysfs_private *sysfs;
  1341. if (!dp_sysfs)
  1342. return;
  1343. class_unregister(&dp_sysfs->dp_class);
  1344. sysfs = container_of(dp_sysfs, struct secdp_sysfs_private, dp_sysfs);
  1345. devm_kfree(dev, sysfs);
  1346. }