mgb4_sysfs_in.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2021-2023 Digiteq Automotive
  4. * author: Martin Tuma <martin.tuma@digiteqautomotive.com>
  5. *
  6. * This module handles all the sysfs info/configuration that is related to the
  7. * v4l2 input devices.
  8. */
  9. #include <linux/device.h>
  10. #include "mgb4_core.h"
  11. #include "mgb4_i2c.h"
  12. #include "mgb4_vin.h"
  13. #include "mgb4_cmt.h"
  14. #include "mgb4_sysfs.h"
  15. /* Common for both FPDL3 and GMSL */
  16. static ssize_t input_id_show(struct device *dev,
  17. struct device_attribute *attr, char *buf)
  18. {
  19. struct video_device *vdev = to_video_device(dev);
  20. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  21. return sprintf(buf, "%d\n", vindev->config->id);
  22. }
  23. static ssize_t oldi_lane_width_show(struct device *dev,
  24. struct device_attribute *attr, char *buf)
  25. {
  26. struct video_device *vdev = to_video_device(dev);
  27. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  28. struct mgb4_dev *mgbdev = vindev->mgbdev;
  29. u16 i2c_reg;
  30. u8 i2c_mask, i2c_single_val, i2c_dual_val;
  31. u32 config;
  32. int ret;
  33. i2c_reg = MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49;
  34. i2c_mask = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03;
  35. i2c_single_val = MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02;
  36. i2c_dual_val = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00;
  37. mutex_lock(&mgbdev->i2c_lock);
  38. ret = mgb4_i2c_read_byte(&vindev->deser, i2c_reg);
  39. mutex_unlock(&mgbdev->i2c_lock);
  40. if (ret < 0)
  41. return -EIO;
  42. config = mgb4_read_reg(&mgbdev->video, vindev->config->regs.config);
  43. if (((config & (1U << 9)) && ((ret & i2c_mask) != i2c_dual_val)) ||
  44. (!(config & (1U << 9)) && ((ret & i2c_mask) != i2c_single_val))) {
  45. dev_err(dev, "I2C/FPGA register value mismatch\n");
  46. return -EINVAL;
  47. }
  48. return sprintf(buf, "%s\n", config & (1U << 9) ? "1" : "0");
  49. }
  50. /*
  51. * OLDI lane width change is expected to be called on live streams. Video device
  52. * locking/queue check is not needed.
  53. */
  54. static ssize_t oldi_lane_width_store(struct device *dev,
  55. struct device_attribute *attr,
  56. const char *buf, size_t count)
  57. {
  58. struct video_device *vdev = to_video_device(dev);
  59. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  60. struct mgb4_dev *mgbdev = vindev->mgbdev;
  61. u32 fpga_data;
  62. u16 i2c_reg;
  63. u8 i2c_mask, i2c_data;
  64. unsigned long val;
  65. int ret;
  66. ret = kstrtoul(buf, 10, &val);
  67. if (ret)
  68. return ret;
  69. switch (val) {
  70. case 0: /* single */
  71. fpga_data = 0;
  72. i2c_data = MGB4_IS_GMSL(mgbdev) ? 0x00 : 0x02;
  73. break;
  74. case 1: /* dual */
  75. fpga_data = 1U << 9;
  76. i2c_data = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x00;
  77. break;
  78. default:
  79. return -EINVAL;
  80. }
  81. i2c_reg = MGB4_IS_GMSL(mgbdev) ? 0x1CE : 0x49;
  82. i2c_mask = MGB4_IS_GMSL(mgbdev) ? 0x0E : 0x03;
  83. mutex_lock(&mgbdev->i2c_lock);
  84. ret = mgb4_i2c_mask_byte(&vindev->deser, i2c_reg, i2c_mask, i2c_data);
  85. mutex_unlock(&mgbdev->i2c_lock);
  86. if (ret < 0)
  87. return -EIO;
  88. mgb4_mask_reg(&mgbdev->video, vindev->config->regs.config, 1U << 9,
  89. fpga_data);
  90. if (MGB4_IS_GMSL(mgbdev)) {
  91. /* reset input link */
  92. mutex_lock(&mgbdev->i2c_lock);
  93. ret = mgb4_i2c_mask_byte(&vindev->deser, 0x10, 1U << 5, 1U << 5);
  94. mutex_unlock(&mgbdev->i2c_lock);
  95. if (ret < 0)
  96. return -EIO;
  97. }
  98. return count;
  99. }
  100. static ssize_t color_mapping_show(struct device *dev,
  101. struct device_attribute *attr, char *buf)
  102. {
  103. struct video_device *vdev = to_video_device(dev);
  104. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  105. u32 config = mgb4_read_reg(&vindev->mgbdev->video,
  106. vindev->config->regs.config);
  107. return sprintf(buf, "%s\n", config & (1U << 8) ? "0" : "1");
  108. }
  109. /*
  110. * Color mapping change is expected to be called on live streams. Video device
  111. * locking/queue check is not needed.
  112. */
  113. static ssize_t color_mapping_store(struct device *dev,
  114. struct device_attribute *attr,
  115. const char *buf, size_t count)
  116. {
  117. struct video_device *vdev = to_video_device(dev);
  118. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  119. u32 fpga_data;
  120. unsigned long val;
  121. int ret;
  122. ret = kstrtoul(buf, 10, &val);
  123. if (ret)
  124. return ret;
  125. switch (val) {
  126. case 0: /* OLDI/JEIDA */
  127. fpga_data = (1U << 8);
  128. break;
  129. case 1: /* SPWG/VESA */
  130. fpga_data = 0;
  131. break;
  132. default:
  133. return -EINVAL;
  134. }
  135. mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.config,
  136. 1U << 8, fpga_data);
  137. return count;
  138. }
  139. static ssize_t link_status_show(struct device *dev,
  140. struct device_attribute *attr, char *buf)
  141. {
  142. struct video_device *vdev = to_video_device(dev);
  143. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  144. u32 status = mgb4_read_reg(&vindev->mgbdev->video,
  145. vindev->config->regs.status);
  146. return sprintf(buf, "%s\n", status & (1U << 2) ? "1" : "0");
  147. }
  148. static ssize_t stream_status_show(struct device *dev,
  149. struct device_attribute *attr, char *buf)
  150. {
  151. struct video_device *vdev = to_video_device(dev);
  152. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  153. u32 status = mgb4_read_reg(&vindev->mgbdev->video,
  154. vindev->config->regs.status);
  155. return sprintf(buf, "%s\n", ((status & (1 << 14)) &&
  156. (status & (1 << 2)) && (status & (3 << 9))) ? "1" : "0");
  157. }
  158. static ssize_t video_width_show(struct device *dev,
  159. struct device_attribute *attr, char *buf)
  160. {
  161. struct video_device *vdev = to_video_device(dev);
  162. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  163. u32 config = mgb4_read_reg(&vindev->mgbdev->video,
  164. vindev->config->regs.resolution);
  165. return sprintf(buf, "%u\n", config >> 16);
  166. }
  167. static ssize_t video_height_show(struct device *dev,
  168. struct device_attribute *attr, char *buf)
  169. {
  170. struct video_device *vdev = to_video_device(dev);
  171. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  172. u32 config = mgb4_read_reg(&vindev->mgbdev->video,
  173. vindev->config->regs.resolution);
  174. return sprintf(buf, "%u\n", config & 0xFFFF);
  175. }
  176. static ssize_t hsync_status_show(struct device *dev,
  177. struct device_attribute *attr, char *buf)
  178. {
  179. struct video_device *vdev = to_video_device(dev);
  180. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  181. u32 status = mgb4_read_reg(&vindev->mgbdev->video,
  182. vindev->config->regs.status);
  183. u32 res;
  184. if (!(status & (1U << 11)))
  185. res = 0x02; // not available
  186. else if (status & (1U << 12))
  187. res = 0x01; // active high
  188. else
  189. res = 0x00; // active low
  190. return sprintf(buf, "%u\n", res);
  191. }
  192. static ssize_t vsync_status_show(struct device *dev,
  193. struct device_attribute *attr, char *buf)
  194. {
  195. struct video_device *vdev = to_video_device(dev);
  196. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  197. u32 status = mgb4_read_reg(&vindev->mgbdev->video,
  198. vindev->config->regs.status);
  199. u32 res;
  200. if (!(status & (1U << 11)))
  201. res = 0x02; // not available
  202. else if (status & (1U << 13))
  203. res = 0x01; // active high
  204. else
  205. res = 0x00; // active low
  206. return sprintf(buf, "%u\n", res);
  207. }
  208. static ssize_t hsync_gap_length_show(struct device *dev,
  209. struct device_attribute *attr,
  210. char *buf)
  211. {
  212. struct video_device *vdev = to_video_device(dev);
  213. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  214. u32 sync = mgb4_read_reg(&vindev->mgbdev->video,
  215. vindev->config->regs.sync);
  216. return sprintf(buf, "%u\n", sync >> 16);
  217. }
  218. /*
  219. * HSYNC gap length change is expected to be called on live streams. Video
  220. * device locking/queue check is not needed.
  221. */
  222. static ssize_t hsync_gap_length_store(struct device *dev,
  223. struct device_attribute *attr,
  224. const char *buf, size_t count)
  225. {
  226. struct video_device *vdev = to_video_device(dev);
  227. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  228. unsigned long val;
  229. int ret;
  230. ret = kstrtoul(buf, 10, &val);
  231. if (ret)
  232. return ret;
  233. if (val > 0xFFFF)
  234. return -EINVAL;
  235. mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.sync,
  236. 0xFFFF0000, val << 16);
  237. return count;
  238. }
  239. static ssize_t vsync_gap_length_show(struct device *dev,
  240. struct device_attribute *attr, char *buf)
  241. {
  242. struct video_device *vdev = to_video_device(dev);
  243. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  244. u32 sync = mgb4_read_reg(&vindev->mgbdev->video,
  245. vindev->config->regs.sync);
  246. return sprintf(buf, "%u\n", sync & 0xFFFF);
  247. }
  248. /*
  249. * VSYNC gap length change is expected to be called on live streams. Video
  250. * device locking/queue check is not needed.
  251. */
  252. static ssize_t vsync_gap_length_store(struct device *dev,
  253. struct device_attribute *attr,
  254. const char *buf, size_t count)
  255. {
  256. struct video_device *vdev = to_video_device(dev);
  257. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  258. unsigned long val;
  259. int ret;
  260. ret = kstrtoul(buf, 10, &val);
  261. if (ret)
  262. return ret;
  263. if (val > 0xFFFF)
  264. return -EINVAL;
  265. mgb4_mask_reg(&vindev->mgbdev->video, vindev->config->regs.sync, 0xFFFF,
  266. val);
  267. return count;
  268. }
  269. static ssize_t pclk_frequency_show(struct device *dev,
  270. struct device_attribute *attr, char *buf)
  271. {
  272. struct video_device *vdev = to_video_device(dev);
  273. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  274. u32 freq = mgb4_read_reg(&vindev->mgbdev->video,
  275. vindev->config->regs.pclk);
  276. return sprintf(buf, "%u\n", freq);
  277. }
  278. static ssize_t hsync_width_show(struct device *dev,
  279. struct device_attribute *attr, char *buf)
  280. {
  281. struct video_device *vdev = to_video_device(dev);
  282. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  283. u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
  284. vindev->config->regs.signal);
  285. return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);
  286. }
  287. static ssize_t vsync_width_show(struct device *dev,
  288. struct device_attribute *attr, char *buf)
  289. {
  290. struct video_device *vdev = to_video_device(dev);
  291. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  292. u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
  293. vindev->config->regs.signal2);
  294. return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);
  295. }
  296. static ssize_t hback_porch_show(struct device *dev,
  297. struct device_attribute *attr, char *buf)
  298. {
  299. struct video_device *vdev = to_video_device(dev);
  300. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  301. u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
  302. vindev->config->regs.signal);
  303. return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);
  304. }
  305. static ssize_t hfront_porch_show(struct device *dev,
  306. struct device_attribute *attr, char *buf)
  307. {
  308. struct video_device *vdev = to_video_device(dev);
  309. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  310. u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
  311. vindev->config->regs.signal);
  312. return sprintf(buf, "%u\n", (sig & 0x000000FF));
  313. }
  314. static ssize_t vback_porch_show(struct device *dev,
  315. struct device_attribute *attr, char *buf)
  316. {
  317. struct video_device *vdev = to_video_device(dev);
  318. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  319. u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
  320. vindev->config->regs.signal2);
  321. return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);
  322. }
  323. static ssize_t vfront_porch_show(struct device *dev,
  324. struct device_attribute *attr, char *buf)
  325. {
  326. struct video_device *vdev = to_video_device(dev);
  327. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  328. u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
  329. vindev->config->regs.signal2);
  330. return sprintf(buf, "%u\n", (sig & 0x000000FF));
  331. }
  332. static ssize_t frequency_range_show(struct device *dev,
  333. struct device_attribute *attr, char *buf)
  334. {
  335. struct video_device *vdev = to_video_device(dev);
  336. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  337. return sprintf(buf, "%d\n", vindev->freq_range);
  338. }
  339. static ssize_t frequency_range_store(struct device *dev,
  340. struct device_attribute *attr,
  341. const char *buf, size_t count)
  342. {
  343. struct video_device *vdev = to_video_device(dev);
  344. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  345. unsigned long val;
  346. int ret;
  347. ret = kstrtoul(buf, 10, &val);
  348. if (ret)
  349. return ret;
  350. if (val > 1)
  351. return -EINVAL;
  352. mutex_lock(vindev->vdev.lock);
  353. if (vb2_is_busy(vindev->vdev.queue)) {
  354. mutex_unlock(vindev->vdev.lock);
  355. return -EBUSY;
  356. }
  357. mgb4_cmt_set_vin_freq_range(vindev, val);
  358. vindev->freq_range = val;
  359. mutex_unlock(vindev->vdev.lock);
  360. return count;
  361. }
  362. /* FPDL3 only */
  363. static ssize_t fpdl3_input_width_show(struct device *dev,
  364. struct device_attribute *attr, char *buf)
  365. {
  366. struct video_device *vdev = to_video_device(dev);
  367. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  368. s32 ret;
  369. mutex_lock(&vindev->mgbdev->i2c_lock);
  370. ret = mgb4_i2c_read_byte(&vindev->deser, 0x34);
  371. mutex_unlock(&vindev->mgbdev->i2c_lock);
  372. if (ret < 0)
  373. return -EIO;
  374. switch ((u8)ret & 0x18) {
  375. case 0:
  376. return sprintf(buf, "0\n");
  377. case 0x10:
  378. return sprintf(buf, "1\n");
  379. case 0x08:
  380. return sprintf(buf, "2\n");
  381. default:
  382. return -EINVAL;
  383. }
  384. }
  385. /*
  386. * FPD-Link width change is expected to be called on live streams. Video device
  387. * locking/queue check is not needed.
  388. */
  389. static ssize_t fpdl3_input_width_store(struct device *dev,
  390. struct device_attribute *attr,
  391. const char *buf, size_t count)
  392. {
  393. struct video_device *vdev = to_video_device(dev);
  394. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  395. u8 i2c_data;
  396. unsigned long val;
  397. int ret;
  398. ret = kstrtoul(buf, 10, &val);
  399. if (ret)
  400. return ret;
  401. switch (val) {
  402. case 0: /* auto */
  403. i2c_data = 0x00;
  404. break;
  405. case 1: /* single */
  406. i2c_data = 0x10;
  407. break;
  408. case 2: /* dual */
  409. i2c_data = 0x08;
  410. break;
  411. default:
  412. return -EINVAL;
  413. }
  414. mutex_lock(&vindev->mgbdev->i2c_lock);
  415. ret = mgb4_i2c_mask_byte(&vindev->deser, 0x34, 0x18, i2c_data);
  416. mutex_unlock(&vindev->mgbdev->i2c_lock);
  417. if (ret < 0)
  418. return -EIO;
  419. return count;
  420. }
  421. /* GMSL only */
  422. static ssize_t gmsl_mode_show(struct device *dev,
  423. struct device_attribute *attr, char *buf)
  424. {
  425. struct video_device *vdev = to_video_device(dev);
  426. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  427. s32 r1, r300, r3;
  428. mutex_lock(&vindev->mgbdev->i2c_lock);
  429. r1 = mgb4_i2c_read_byte(&vindev->deser, 0x01);
  430. r300 = mgb4_i2c_read_byte(&vindev->deser, 0x300);
  431. r3 = mgb4_i2c_read_byte(&vindev->deser, 0x03);
  432. mutex_unlock(&vindev->mgbdev->i2c_lock);
  433. if (r1 < 0 || r300 < 0 || r3 < 0)
  434. return -EIO;
  435. if ((r1 & 0x03) == 0x03 && (r300 & 0x0C) == 0x0C && (r3 & 0xC0) == 0xC0)
  436. return sprintf(buf, "0\n");
  437. else if ((r1 & 0x03) == 0x02 && (r300 & 0x0C) == 0x08 && (r3 & 0xC0) == 0x00)
  438. return sprintf(buf, "1\n");
  439. else if ((r1 & 0x03) == 0x01 && (r300 & 0x0C) == 0x04 && (r3 & 0xC0) == 0x00)
  440. return sprintf(buf, "2\n");
  441. else if ((r1 & 0x03) == 0x00 && (r300 & 0x0C) == 0x00 && (r3 & 0xC0) == 0x00)
  442. return sprintf(buf, "3\n");
  443. else
  444. return -EINVAL;
  445. }
  446. /*
  447. * GMSL mode change is expected to be called on live streams. Video device
  448. * locking/queue check is not needed.
  449. */
  450. static ssize_t gmsl_mode_store(struct device *dev,
  451. struct device_attribute *attr, const char *buf,
  452. size_t count)
  453. {
  454. static const struct mgb4_i2c_kv G12[] = {
  455. {0x01, 0x03, 0x03}, {0x300, 0x0C, 0x0C}, {0x03, 0xC0, 0xC0}};
  456. static const struct mgb4_i2c_kv G6[] = {
  457. {0x01, 0x03, 0x02}, {0x300, 0x0C, 0x08}, {0x03, 0xC0, 0x00}};
  458. static const struct mgb4_i2c_kv G3[] = {
  459. {0x01, 0x03, 0x01}, {0x300, 0x0C, 0x04}, {0x03, 0xC0, 0x00}};
  460. static const struct mgb4_i2c_kv G1[] = {
  461. {0x01, 0x03, 0x00}, {0x300, 0x0C, 0x00}, {0x03, 0xC0, 0x00}};
  462. static const struct mgb4_i2c_kv reset[] = {
  463. {0x10, 1U << 5, 1U << 5}, {0x300, 1U << 6, 1U << 6}};
  464. struct video_device *vdev = to_video_device(dev);
  465. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  466. const struct mgb4_i2c_kv *values;
  467. unsigned long val;
  468. int ret;
  469. ret = kstrtoul(buf, 10, &val);
  470. if (ret)
  471. return ret;
  472. switch (val) {
  473. case 0: /* 12Gb/s */
  474. values = G12;
  475. break;
  476. case 1: /* 6Gb/s */
  477. values = G6;
  478. break;
  479. case 2: /* 3Gb/s */
  480. values = G3;
  481. break;
  482. case 3: /* 1.5Gb/s */
  483. values = G1;
  484. break;
  485. default:
  486. return -EINVAL;
  487. }
  488. mutex_lock(&vindev->mgbdev->i2c_lock);
  489. ret = mgb4_i2c_configure(&vindev->deser, values, 3);
  490. ret |= mgb4_i2c_configure(&vindev->deser, reset, 2);
  491. mutex_unlock(&vindev->mgbdev->i2c_lock);
  492. if (ret < 0)
  493. return -EIO;
  494. return count;
  495. }
  496. static ssize_t gmsl_stream_id_show(struct device *dev,
  497. struct device_attribute *attr, char *buf)
  498. {
  499. struct video_device *vdev = to_video_device(dev);
  500. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  501. s32 ret;
  502. mutex_lock(&vindev->mgbdev->i2c_lock);
  503. ret = mgb4_i2c_read_byte(&vindev->deser, 0xA0);
  504. mutex_unlock(&vindev->mgbdev->i2c_lock);
  505. if (ret < 0)
  506. return -EIO;
  507. return sprintf(buf, "%d\n", ret & 0x03);
  508. }
  509. static ssize_t gmsl_stream_id_store(struct device *dev,
  510. struct device_attribute *attr,
  511. const char *buf, size_t count)
  512. {
  513. struct video_device *vdev = to_video_device(dev);
  514. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  515. unsigned long val;
  516. int ret;
  517. ret = kstrtoul(buf, 10, &val);
  518. if (ret)
  519. return ret;
  520. if (val > 3)
  521. return -EINVAL;
  522. mutex_lock(vindev->vdev.lock);
  523. if (vb2_is_busy(vindev->vdev.queue)) {
  524. mutex_unlock(vindev->vdev.lock);
  525. return -EBUSY;
  526. }
  527. mutex_lock(&vindev->mgbdev->i2c_lock);
  528. ret = mgb4_i2c_mask_byte(&vindev->deser, 0xA0, 0x03, (u8)val);
  529. mutex_unlock(&vindev->mgbdev->i2c_lock);
  530. mutex_unlock(vindev->vdev.lock);
  531. return (ret < 0) ? -EIO : count;
  532. }
  533. static ssize_t gmsl_fec_show(struct device *dev, struct device_attribute *attr,
  534. char *buf)
  535. {
  536. struct video_device *vdev = to_video_device(dev);
  537. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  538. s32 r3e0, r308;
  539. mutex_lock(&vindev->mgbdev->i2c_lock);
  540. r3e0 = mgb4_i2c_read_byte(&vindev->deser, 0x3E0);
  541. r308 = mgb4_i2c_read_byte(&vindev->deser, 0x308);
  542. mutex_unlock(&vindev->mgbdev->i2c_lock);
  543. if (r3e0 < 0 || r308 < 0)
  544. return -EIO;
  545. if ((r3e0 & 0x07) == 0x00 && (r308 & 0x01) == 0x00)
  546. return sprintf(buf, "0\n");
  547. else if ((r3e0 & 0x07) == 0x07 && (r308 & 0x01) == 0x01)
  548. return sprintf(buf, "1\n");
  549. else
  550. return -EINVAL;
  551. }
  552. /*
  553. * GMSL FEC change is expected to be called on live streams. Video device
  554. * locking/queue check is not needed.
  555. */
  556. static ssize_t gmsl_fec_store(struct device *dev, struct device_attribute *attr,
  557. const char *buf, size_t count)
  558. {
  559. struct video_device *vdev = to_video_device(dev);
  560. struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
  561. static const struct mgb4_i2c_kv enable[] = {
  562. {0x3E0, 0x07, 0x07}, {0x308, 0x01, 0x01}};
  563. static const struct mgb4_i2c_kv disable[] = {
  564. {0x3E0, 0x07, 0x00}, {0x308, 0x01, 0x00}};
  565. static const struct mgb4_i2c_kv reset[] = {
  566. {0x10, 1U << 5, 1U << 5}, {0x300, 1U << 6, 1U << 6}};
  567. const struct mgb4_i2c_kv *values;
  568. unsigned long val;
  569. int ret;
  570. ret = kstrtoul(buf, 10, &val);
  571. if (ret)
  572. return ret;
  573. switch (val) {
  574. case 0: /* disabled */
  575. values = disable;
  576. break;
  577. case 1: /* enabled */
  578. values = enable;
  579. break;
  580. default:
  581. return -EINVAL;
  582. }
  583. mutex_lock(&vindev->mgbdev->i2c_lock);
  584. ret = mgb4_i2c_configure(&vindev->deser, values, 2);
  585. ret |= mgb4_i2c_configure(&vindev->deser, reset, 2);
  586. mutex_unlock(&vindev->mgbdev->i2c_lock);
  587. if (ret < 0)
  588. return -EIO;
  589. return count;
  590. }
  591. static DEVICE_ATTR_RO(input_id);
  592. static DEVICE_ATTR_RW(oldi_lane_width);
  593. static DEVICE_ATTR_RW(color_mapping);
  594. static DEVICE_ATTR_RO(link_status);
  595. static DEVICE_ATTR_RO(stream_status);
  596. static DEVICE_ATTR_RO(video_width);
  597. static DEVICE_ATTR_RO(video_height);
  598. static DEVICE_ATTR_RO(hsync_status);
  599. static DEVICE_ATTR_RO(vsync_status);
  600. static DEVICE_ATTR_RW(hsync_gap_length);
  601. static DEVICE_ATTR_RW(vsync_gap_length);
  602. static DEVICE_ATTR_RO(pclk_frequency);
  603. static DEVICE_ATTR_RO(hsync_width);
  604. static DEVICE_ATTR_RO(vsync_width);
  605. static DEVICE_ATTR_RO(hback_porch);
  606. static DEVICE_ATTR_RO(hfront_porch);
  607. static DEVICE_ATTR_RO(vback_porch);
  608. static DEVICE_ATTR_RO(vfront_porch);
  609. static DEVICE_ATTR_RW(frequency_range);
  610. static DEVICE_ATTR_RW(fpdl3_input_width);
  611. static DEVICE_ATTR_RW(gmsl_mode);
  612. static DEVICE_ATTR_RW(gmsl_stream_id);
  613. static DEVICE_ATTR_RW(gmsl_fec);
  614. struct attribute *mgb4_fpdl3_in_attrs[] = {
  615. &dev_attr_input_id.attr,
  616. &dev_attr_link_status.attr,
  617. &dev_attr_stream_status.attr,
  618. &dev_attr_video_width.attr,
  619. &dev_attr_video_height.attr,
  620. &dev_attr_hsync_status.attr,
  621. &dev_attr_vsync_status.attr,
  622. &dev_attr_oldi_lane_width.attr,
  623. &dev_attr_color_mapping.attr,
  624. &dev_attr_hsync_gap_length.attr,
  625. &dev_attr_vsync_gap_length.attr,
  626. &dev_attr_pclk_frequency.attr,
  627. &dev_attr_hsync_width.attr,
  628. &dev_attr_vsync_width.attr,
  629. &dev_attr_hback_porch.attr,
  630. &dev_attr_hfront_porch.attr,
  631. &dev_attr_vback_porch.attr,
  632. &dev_attr_vfront_porch.attr,
  633. &dev_attr_frequency_range.attr,
  634. &dev_attr_fpdl3_input_width.attr,
  635. NULL
  636. };
  637. struct attribute *mgb4_gmsl_in_attrs[] = {
  638. &dev_attr_input_id.attr,
  639. &dev_attr_link_status.attr,
  640. &dev_attr_stream_status.attr,
  641. &dev_attr_video_width.attr,
  642. &dev_attr_video_height.attr,
  643. &dev_attr_hsync_status.attr,
  644. &dev_attr_vsync_status.attr,
  645. &dev_attr_oldi_lane_width.attr,
  646. &dev_attr_color_mapping.attr,
  647. &dev_attr_hsync_gap_length.attr,
  648. &dev_attr_vsync_gap_length.attr,
  649. &dev_attr_pclk_frequency.attr,
  650. &dev_attr_hsync_width.attr,
  651. &dev_attr_vsync_width.attr,
  652. &dev_attr_hback_porch.attr,
  653. &dev_attr_hfront_porch.attr,
  654. &dev_attr_vback_porch.attr,
  655. &dev_attr_vfront_porch.attr,
  656. &dev_attr_frequency_range.attr,
  657. &dev_attr_gmsl_mode.attr,
  658. &dev_attr_gmsl_stream_id.attr,
  659. &dev_attr_gmsl_fec.attr,
  660. NULL
  661. };