Advertisement
Guest User

Untitled

a guest
Oct 1st, 2017
1,508
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 900.00 KB | None | 0 0
  1. From 503568a576cf00b29eb77c674da1d98da0b1d042 Mon Sep 17 00:00:00 2001
  2. From: hehao <hehao@xiaomi.com>
  3. Date: Sat, 30 Sep 2017 17:25:02 +0800
  4. Subject: [PATCH] Kernel: Xiaomi kernel changes for Xiaomi 6
  5.  
  6. The Patch based on QualComm release version: MSM8998.LA.1.1.r1-00232-STD.PROD-3
  7. The kernel config file used is sagit_user_defconfig
  8.  
  9. Change-Id: Ie189e10280cd733e8d8bd403a992adae9a8a2521
  10. Signed-off-by: hehao <hehao@xiaomi.com>
  11. ---
  12. Documentation/devicetree/bindings/gpu/adreno.txt | 3 +
  13. arch/Kconfig | 7 +
  14. arch/arm/boot/dts/qcom/Makefile | 34 +-
  15. .../boot/dts/qcom/batterydata-c1-atl-3350mAh.dtsi | 69 +
  16. .../boot/dts/qcom/batterydata-c1-sdi-3440mAh.dtsi | 69 +
  17. .../boot/dts/qcom/batterydata-itech-3020mAh.dtsi | 54 +
  18. .../dts/qcom/dsi-panel-jdi-fhd-r63452-cmd.dtsi | 272 +
  19. .../dts/qcom/dsi-panel-lgd-fhd-td4322-cmd.dtsi | 270 +
  20. .../dts/qcom/dsi-panel-lgd-sw43401-wqhd-cmd.dtsi | 111 +
  21. arch/arm/boot/dts/qcom/msm-pm8998.dtsi | 6 +-
  22. arch/arm/boot/dts/qcom/msm-pmi8998.dtsi | 23 +-
  23. arch/arm/boot/dts/qcom/msm8998-audio.dtsi | 18 -
  24. arch/arm/boot/dts/qcom/msm8998-blsp.dtsi | 1 -
  25. .../boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi | 2 +
  26. .../boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi | 192 +-
  27. .../boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi | 100 +-
  28. arch/arm/boot/dts/qcom/msm8998-camera.dtsi | 9 +-
  29. .../qcom/msm8998-interposer-camera-sensor-mtp.dtsi | 13 +-
  30. .../qcom/msm8998-interposer-camera-sensor-qrd.dtsi | 13 +-
  31. arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi | 89 +-
  32. arch/arm/boot/dts/qcom/msm8998-mdss.dtsi | 2 +
  33. arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi | 284 +-
  34. arch/arm/boot/dts/qcom/msm8998-pm.dtsi | 1 +
  35. arch/arm/boot/dts/qcom/msm8998-regulator.dtsi | 35 +-
  36. arch/arm/boot/dts/qcom/msm8998-v2.dtsi | 8 +-
  37. arch/arm/boot/dts/qcom/msm8998.dtsi | 53 +-
  38. .../arm/boot/dts/qcom/sagit-camera-sensor-mtp.dtsi | 478 ++
  39. arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dts | 39 +
  40. arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dtsi | 944 +++
  41. arch/arm/boot/dts/qcom/sagit-msm8998-v2-mtp.dts | 24 +
  42. arch/arm/boot/dts/qcom/sagit-msm8998-v2.1-mtp.dts | 24 +
  43. arch/arm64/Kconfig | 15 +
  44. arch/arm64/configs/msmcortex_defconfig | 2 +-
  45. arch/arm64/configs/sagit_user_defconfig | 723 ++
  46. arch/arm64/include/asm/bootinfo.h | 55 +
  47. arch/arm64/include/asm/hwconf_manager.h | 21 +
  48. arch/arm64/kernel/Makefile | 2 +
  49. arch/arm64/kernel/bootinfo.c | 214 +
  50. arch/arm64/kernel/hwconf_manager.c | 459 ++
  51. arch/arm64/kernel/process.c | 2 +-
  52. arch/arm64/kernel/setup.c | 12 +
  53. drivers/Makefile | 2 +-
  54. drivers/android/binder.c | 3 +-
  55. drivers/base/power/wakeup.c | 4 +
  56. drivers/base/syscore.c | 11 +-
  57. drivers/block/zram/zram_drv.c | 41 +-
  58. drivers/bluetooth/btfm_slim.h | 2 +
  59. drivers/bluetooth/btfm_slim_codec.c | 4 +
  60. drivers/bluetooth/btfm_slim_wcn3990.c | 13 +-
  61. drivers/char/diag/diag_masks.c | 2 +
  62. drivers/clk/msm/clock-debug.c | 2 +-
  63. drivers/clk/msm/clock-mmss-8998.c | 2 +
  64. drivers/clk/msm/mdss/mdss-dsi-pll-8998.c | 2 +-
  65. drivers/elliptic/Makefile | 17 +
  66. drivers/elliptic/elliptic.c | 716 ++
  67. drivers/elliptic/elliptic_data_io.h | 100 +
  68. drivers/elliptic/elliptic_device.h | 54 +
  69. drivers/elliptic/elliptic_mixer_controls.h | 27 +
  70. drivers/elliptic/elliptic_sysfs.c | 182 +
  71. drivers/elliptic/elliptic_sysfs.h | 10 +
  72. drivers/elliptic/io_modules/Makefile | 2 +
  73. drivers/elliptic/io_modules/msm/elliptic_data_io.c | 94 +
  74. drivers/elliptic/io_modules/userspace/Makefile | 2 +
  75. .../io_modules/userspace/elliptic_data_io.c | 208 +
  76. .../elliptic/io_modules/userspace_test/Makefile | 2 +
  77. .../io_modules/userspace_test/elliptic_data_io.c | 126 +
  78. drivers/firmware/qcom/tz_log.c | 4 +-
  79. drivers/gpu/msm/kgsl.h | 2 +-
  80. drivers/gpu/msm/kgsl_pwrctrl.c | 39 +-
  81. drivers/gpu/msm/kgsl_pwrctrl.h | 3 +
  82. drivers/hid/usbhid/hiddev.c | 18 +-
  83. drivers/input/Kconfig | 9 +
  84. drivers/input/Makefile | 1 +
  85. drivers/input/evdev.c | 113 +-
  86. drivers/input/fingerprint/Kconfig | 18 +
  87. drivers/input/fingerprint/Makefile | 9 +
  88. drivers/input/fingerprint/fpc1268_tee/Kconfig | 10 +
  89. drivers/input/fingerprint/fpc1268_tee/Makefile | 1 +
  90. .../input/fingerprint/fpc1268_tee/fpc1020_tee.c | 633 ++
  91. drivers/input/fingerprint/goodix/Kconfig | 10 +
  92. drivers/input/fingerprint/goodix/Makefile | 1 +
  93. drivers/input/fingerprint/goodix/gf_common.c | 331 +
  94. drivers/input/fingerprint/goodix/gf_common.h | 27 +
  95. drivers/input/fingerprint/goodix/gf_spi.c | 986 +++
  96. drivers/input/fingerprint/goodix/gf_spi.h | 102 +
  97. drivers/input/fingerprint/goodix/platform.c | 134 +
  98. drivers/input/fingerprint/goodix_ta/Kconfig | 10 +
  99. drivers/input/fingerprint/goodix_ta/Makefile | 1 +
  100. drivers/input/fingerprint/goodix_ta/gf_spi.c | 906 ++
  101. drivers/input/fingerprint/goodix_ta/gf_spi.h | 155 +
  102. drivers/input/fingerprint/goodix_ta/netlink.c | 98 +
  103. drivers/input/fingerprint/goodix_ta/platform.c | 98 +
  104. drivers/input/input.c | 135 +
  105. drivers/input/misc/qpnp-power-on.c | 107 +
  106. drivers/input/touchscreen/Kconfig | 2 +
  107. drivers/input/touchscreen/Makefile | 3 +
  108. drivers/input/touchscreen/ft5x46/Kconfig | 52 +
  109. drivers/input/touchscreen/ft5x46/Makefile | 8 +
  110. drivers/input/touchscreen/ft5x46/focaltech_test.c | 313 +
  111. drivers/input/touchscreen/ft5x46/focaltech_test.h | 119 +
  112. .../touchscreen/ft5x46/focaltech_test_ft5x46.c | 806 ++
  113. .../touchscreen/ft5x46/focaltech_test_ft5x46.h | 22 +
  114. drivers/input/touchscreen/ft5x46/ft5x46_ts.c | 3051 +++++++
  115. drivers/input/touchscreen/ft5x46/ft5x46_ts_i2c.c | 256 +
  116. drivers/input/touchscreen/ft5x46/ft5x46_ts_spi.c | 133 +
  117. .../input/touchscreen/synaptics_dsx_force/Kconfig | 124 +
  118. .../input/touchscreen/synaptics_dsx_force/Makefile | 17 +
  119. .../synaptics_dsx_force/synaptics_dsx_active_pen.c | 631 ++
  120. .../synaptics_dsx_force/synaptics_dsx_core.c | 5987 ++++++++++++++
  121. .../synaptics_dsx_force/synaptics_dsx_core.h | 541 ++
  122. .../synaptics_dsx_force/synaptics_dsx_fw_update.c | 5486 +++++++++++++
  123. .../synaptics_dsx_force/synaptics_dsx_gesture.c | 2312 ++++++
  124. .../synaptics_dsx_force/synaptics_dsx_i2c.c | 901 ++
  125. .../synaptics_dsx_force/synaptics_dsx_proximity.c | 693 ++
  126. .../synaptics_dsx_force/synaptics_dsx_rmi_dev.c | 1060 +++
  127. .../synaptics_dsx_rmi_hid_i2c.c | 1005 +++
  128. .../synaptics_dsx_force/synaptics_dsx_spi.c | 711 ++
  129. .../synaptics_dsx_test_reporting.c | 6884 ++++++++++++++++
  130. .../synaptics_dsx_force/synaptics_dsx_video.c | 417 +
  131. drivers/irqchip/irq-gic-v3.c | 14 +
  132. drivers/irqchip/msm_show_resume_irq.c | 2 +-
  133. drivers/leds/leds-qpnp-flash-v2.c | 34 +-
  134. drivers/leds/leds-qpnp-wled.c | 11 +-
  135. drivers/leds/leds-qpnp.c | 30 +
  136. drivers/md/dm-bufio.c | 14 +-
  137. .../media/platform/msm/camera_v2/camera/camera.c | 4 +-
  138. .../platform/msm/camera_v2/common/cam_smmu_api.c | 148 +-
  139. .../platform/msm/camera_v2/common/cam_smmu_api.h | 27 +-
  140. .../platform/msm/camera_v2/common/cam_soc_api.c | 9 +-
  141. .../msm/camera_v2/common/msm_camera_io_util.c | 6 +-
  142. .../media/platform/msm/camera_v2/isp/msm_buf_mgr.c | 77 +-
  143. drivers/media/platform/msm/camera_v2/isp/msm_isp.c | 20 +-
  144. drivers/media/platform/msm/camera_v2/isp/msm_isp.h | 32 +-
  145. .../media/platform/msm/camera_v2/isp/msm_isp32.c | 2 +-
  146. .../media/platform/msm/camera_v2/isp/msm_isp40.c | 3 +-
  147. .../media/platform/msm/camera_v2/isp/msm_isp44.c | 3 +-
  148. .../media/platform/msm/camera_v2/isp/msm_isp46.c | 3 +-
  149. .../media/platform/msm/camera_v2/isp/msm_isp47.c | 103 +-
  150. .../media/platform/msm/camera_v2/isp/msm_isp47.h | 6 +-
  151. .../media/platform/msm/camera_v2/isp/msm_isp48.c | 1 -
  152. .../platform/msm/camera_v2/isp/msm_isp_axi_util.c | 272 +-
  153. .../platform/msm/camera_v2/isp/msm_isp_axi_util.h | 9 +-
  154. .../msm/camera_v2/isp/msm_isp_stats_util.c | 41 +-
  155. .../platform/msm/camera_v2/isp/msm_isp_util.c | 155 +-
  156. .../media/platform/msm/camera_v2/ispif/msm_ispif.c | 16 +-
  157. .../platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c | 4 +-
  158. .../msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c | 56 +-
  159. drivers/media/platform/msm/camera_v2/msm.c | 23 +-
  160. .../camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c | 12 +-
  161. .../platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 309 +-
  162. .../platform/msm/camera_v2/pproc/cpp/msm_cpp.h | 12 +-
  163. .../msm/camera_v2/sensor/actuator/msm_actuator.c | 35 +-
  164. .../platform/msm/camera_v2/sensor/cci/msm_cci.c | 79 +-
  165. .../platform/msm/camera_v2/sensor/cci/msm_cci.h | 3 +-
  166. .../platform/msm/camera_v2/sensor/csid/msm_csid.c | 29 +-
  167. .../sensor/csiphy/include/msm_csiphy_5_0_1_hwreg.h | 3 +-
  168. .../sensor/csiphy/include/msm_csiphy_5_0_hwreg.h | 3 +-
  169. .../msm/camera_v2/sensor/csiphy/msm_csiphy.c | 48 +-
  170. .../msm/camera_v2/sensor/csiphy/msm_csiphy.h | 3 +-
  171. .../msm/camera_v2/sensor/eeprom/msm_eeprom.c | 117 +-
  172. .../msm/camera_v2/sensor/eeprom/msm_eeprom.h | 47 +
  173. .../msm/camera_v2/sensor/flash/msm_flash.c | 83 +
  174. .../platform/msm/camera_v2/sensor/msm_sensor.c | 176 +-
  175. .../msm/camera_v2/sensor/msm_sensor_driver.c | 51 +-
  176. .../msm/camera_v2/sensor/msm_sensor_init.c | 2 +-
  177. .../platform/msm/camera_v2/sensor/ois/OIS_coef.h | 497 ++
  178. .../msm/camera_v2/sensor/ois/OIS_coef_ST.h | 497 ++
  179. .../platform/msm/camera_v2/sensor/ois/OIS_defi.h | 1115 +++
  180. .../platform/msm/camera_v2/sensor/ois/OIS_func.c | 640 ++
  181. .../platform/msm/camera_v2/sensor/ois/OIS_head.h | 150 +
  182. .../platform/msm/camera_v2/sensor/ois/OIS_prog.h | 4631 +++++++++++
  183. .../msm/camera_v2/sensor/ois/OIS_prog_ST.h | 4631 +++++++++++
  184. .../platform/msm/camera_v2/sensor/ois/OIS_user.c | 282 +
  185. .../platform/msm/camera_v2/sensor/ois/msm_ois.c | 107 +-
  186. .../platform/msm/camera_v2/sensor/ois/msm_ois.h | 3 +
  187. drivers/media/rc/Kconfig | 25 +
  188. drivers/media/rc/Makefile | 4 +
  189. drivers/media/rc/ir-lirc-codec.c | 47 +-
  190. drivers/media/rc/lirc_dev.c | 3 +-
  191. drivers/media/rc/peelir.c | 515 ++
  192. drivers/media/rc/peelir.h | 81 +
  193. drivers/media/rc/pwm-ir.c | 391 +
  194. drivers/media/rc/rc-main.c | 20 +-
  195. drivers/mfd/Makefile | 1 +
  196. drivers/mfd/spk-id.c | 209 +
  197. drivers/misc/qseecom.c | 9 +-
  198. drivers/nfc/nq-nci.c | 11 +-
  199. drivers/of/fdt.c | 20 +
  200. drivers/of/of_batterydata.c | 12 +-
  201. drivers/pinctrl/qcom/pinctrl-msm.c | 125 +-
  202. drivers/pinctrl/qcom/pinctrl-msm.h | 1 -
  203. drivers/platform/msm/Kconfig | 6 +
  204. drivers/platform/msm/Makefile | 1 +
  205. drivers/platform/msm/gpio_rf.c | 298 +
  206. drivers/platform/msm/ipa/ipa_v3/ipa.c | 2 +
  207. .../platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c | 2 +-
  208. drivers/power/reset/msm-poweroff.c | 35 +-
  209. drivers/power/supply/qcom/battery.c | 14 +-
  210. drivers/power/supply/qcom/fg-core.h | 3 +
  211. drivers/power/supply/qcom/pmic-voter.c | 16 +-
  212. drivers/power/supply/qcom/qpnp-fg-gen3.c | 207 +-
  213. drivers/power/supply/qcom/qpnp-smb2.c | 203 +-
  214. drivers/power/supply/qcom/smb-lib.c | 695 +-
  215. drivers/power/supply/qcom/smb-lib.h | 34 +-
  216. drivers/power/supply/qcom/smb-reg.h | 9 +-
  217. drivers/power/supply/qcom/smb138x-charger.c | 4 +-
  218. drivers/pwm/core.c | 34 +-
  219. drivers/rtc/qpnp-rtc.c | 32 +
  220. drivers/scsi/scsi_lib.c | 11 +-
  221. drivers/scsi/ufs/ufs-debugfs.c | 158 +-
  222. drivers/scsi/ufs/ufs.h | 2 +
  223. drivers/scsi/ufs/ufshcd.c | 12 +
  224. drivers/scsi/ufs/ufshcd.h | 5 +
  225. drivers/soc/qcom/Kconfig | 5 +
  226. drivers/soc/qcom/Makefile | 2 +
  227. drivers/soc/qcom/avtimer.c | 2 +-
  228. drivers/soc/qcom/pil-q6v5-mss.c | 43 +-
  229. drivers/soc/qcom/qdsp6v2/apr.c | 42 +-
  230. drivers/soc/qcom/qdsp6v2/apr_tal_glink.c | 7 +
  231. drivers/soc/qcom/qdsp6v2/voice_svc.c | 2 +-
  232. drivers/soc/qcom/qpnp-haptic.c | 2063 +++--
  233. drivers/soc/qcom/scm.c | 2 +-
  234. drivers/soc/qcom/serial_num.c | 121 +
  235. drivers/soc/qcom/socinfo.c | 32 +
  236. drivers/soc/qcom/system_stats.c | 46 +
  237. drivers/soc/qcom/watchdog_v2.c | 32 +-
  238. drivers/spmi/spmi-pmic-arb.c | 3 +
  239. drivers/staging/android/Kconfig | 12 +
  240. drivers/staging/android/Makefile | 1 +
  241. drivers/staging/android/ion/ion.c | 2 +-
  242. drivers/staging/android/lowmemorykiller.c | 277 +-
  243. drivers/staging/android/memsw_state.c | 311 +
  244. drivers/staging/android/memsw_state.h | 48 +
  245. drivers/tty/serial/msm_serial.c | 50 +-
  246. drivers/usb/dwc3/dwc3-msm.c | 10 +-
  247. drivers/usb/dwc3/ep0.c | 5 +
  248. drivers/usb/dwc3/gadget.c | 10 +-
  249. drivers/usb/gadget/composite.c | 7 +-
  250. drivers/usb/pd/policy_engine.c | 3 +-
  251. drivers/usb/phy/phy-msm-qusb-v2.c | 16 +
  252. drivers/video/fbdev/msm/mdss_debug_xlog.c | 12 +-
  253. drivers/video/fbdev/msm/mdss_dsi.c | 48 +-
  254. drivers/video/fbdev/msm/mdss_dsi.h | 68 +
  255. drivers/video/fbdev/msm/mdss_dsi_host.c | 96 +
  256. drivers/video/fbdev/msm/mdss_dsi_panel.c | 606 +-
  257. drivers/video/fbdev/msm/mdss_fb.c | 51 +-
  258. drivers/video/fbdev/msm/mdss_mdp.h | 6 +-
  259. drivers/video/fbdev/msm/mdss_mdp_layer.c | 6 +-
  260. drivers/video/fbdev/msm/mdss_mdp_pp.c | 5 +-
  261. drivers/video/fbdev/msm/mdss_panel.h | 13 +
  262. firmware/Makefile | 9 +
  263. firmware/ft5216_biel.fw.ihex | 1245 +++
  264. firmware/st_fts_biel.ftb.ihex | 6270 ++++++++++++++
  265. firmware/st_fts_lens.ftb.ihex | 6270 ++++++++++++++
  266. firmware/st_fts_lg.ftb.ihex | 6126 ++++++++++++++
  267. firmware/synaptics_jdi_3330_c1.fw.ihex | 8618 +++++++++++++++++++
  268. firmware/synaptics_jdi_3331_c1.fw.ihex | 8624 ++++++++++++++++++++
  269. firmware/synaptics_lgd_4322_c1.fw.ihex | 8034 ++++++++++++++++++
  270. fs/dcache.c | 2 -
  271. fs/ecryptfs/keystore.c | 12 +-
  272. fs/eventpoll.c | 14 +-
  273. fs/f2fs/Kconfig | 6 +
  274. fs/f2fs/Makefile | 1 +
  275. fs/f2fs/crypto.c | 24 +-
  276. fs/f2fs/crypto_key.c | 65 +-
  277. fs/f2fs/data.c | 4 +-
  278. fs/f2fs/f2fs.h | 17 +
  279. fs/f2fs/f2fs_crypto.h | 5 +
  280. fs/f2fs/f2fs_ice.c | 110 +
  281. fs/f2fs/f2fs_ice.h | 105 +
  282. fs/pstore/Kconfig | 8 +
  283. fs/pstore/inode.c | 40 +
  284. fs/pstore/ram.c | 68 +
  285. fs/sdcardfs/main.c | 8 +
  286. include/linux/cJSON.h | 73 +
  287. include/linux/cpuset.h | 4 +
  288. include/linux/hwinfo.h | 18 +
  289. include/linux/input.h | 23 +
  290. include/linux/input/ft5x46_ts.h | 199 +
  291. include/linux/input/qpnp-power-on.h | 19 +
  292. include/linux/input/synaptics_dsx.h | 166 +
  293. include/linux/kernel.h | 4 +
  294. include/linux/mdss_io_util.h | 6 +
  295. include/linux/mfd/spk-id.h | 32 +
  296. include/linux/of_fdt.h | 3 +
  297. include/linux/pwm.h | 3 -
  298. include/linux/sched.h | 9 +-
  299. include/linux/zsmalloc.h | 3 +
  300. include/media/msm_cam_sensor.h | 10 +
  301. include/media/pwm-ir.h | 26 +
  302. include/media/rc-core.h | 4 +
  303. include/media/rc-map.h | 39 +-
  304. include/soc/qcom/socinfo.h | 9 +
  305. include/soc/qcom/watchdog.h | 5 +
  306. include/sound/apr_elliptic.h | 104 +
  307. include/uapi/media/msm_cam_sensor.h | 12 +
  308. include/uapi/media/msmb_isp.h | 13 -
  309. include/uapi/scsi/ufs/ufs.h | 3 +-
  310. init/Kconfig | 8 +
  311. kernel/cpuset.c | 40 +
  312. kernel/irq/pm.c | 15 +
  313. kernel/locking/spinlock_debug.c | 5 +
  314. kernel/printk/printk.c | 7 +
  315. kernel/sched/core.c | 5 +
  316. kernel/time/alarmtimer.c | 3 +
  317. lib/Kconfig | 5 +
  318. lib/Kconfig.debug | 15 +
  319. lib/Makefile | 2 +
  320. lib/cJSON.c | 871 ++
  321. mm/page_alloc.c | 7 +-
  322. mm/vmscan.c | 7 +
  323. net/dccp/input.c | 3 +-
  324. net/ipv4/ip_sockglue.c | 9 +-
  325. net/packet/af_packet.c | 8 +-
  326. security/pfe/Makefile | 4 +-
  327. security/pfe/pfk.c | 18 +-
  328. security/pfe/pfk_f2fs.c | 190 +
  329. security/pfe/pfk_f2fs.h | 38 +
  330. sound/soc/codecs/Kconfig | 11 +
  331. sound/soc/codecs/Makefile | 5 +
  332. sound/soc/codecs/tas2559/Makefile | 6 +
  333. sound/soc/codecs/tas2559/tas2559-codec.c | 1047 +++
  334. sound/soc/codecs/tas2559/tas2559-codec.h | 30 +
  335. sound/soc/codecs/tas2559/tas2559-core.c | 2936 +++++++
  336. sound/soc/codecs/tas2559/tas2559-core.h | 94 +
  337. sound/soc/codecs/tas2559/tas2559-misc.c | 653 ++
  338. sound/soc/codecs/tas2559/tas2559-misc.h | 61 +
  339. sound/soc/codecs/tas2559/tas2559-regmap.c | 1289 +++
  340. sound/soc/codecs/tas2559/tas2559.h | 527 ++
  341. sound/soc/codecs/tas2559/tas2560.h | 143 +
  342. sound/soc/codecs/tas2559/tiload.c | 428 +
  343. sound/soc/codecs/tas2559/tiload.h | 61 +
  344. sound/soc/codecs/tfa98xx/Makefile | 36 +
  345. sound/soc/codecs/tfa98xx/config.h | 141 +
  346. sound/soc/codecs/tfa98xx/tfa.h | 117 +
  347. sound/soc/codecs/tfa98xx/tfa1_tfafieldnames.h | 900 ++
  348. sound/soc/codecs/tfa98xx/tfa2_tfafieldnames_N1C.h | 1522 ++++
  349. sound/soc/codecs/tfa98xx/tfa9887B_init.c | 77 +
  350. sound/soc/codecs/tfa98xx/tfa9887_init.c | 57 +
  351. sound/soc/codecs/tfa98xx/tfa9887_tfafieldnames.h | 60 +
  352. sound/soc/codecs/tfa98xx/tfa9888_init.c | 188 +
  353. sound/soc/codecs/tfa98xx/tfa9890_init.c | 181 +
  354. sound/soc/codecs/tfa98xx/tfa9890_tfafieldnames.h | 76 +
  355. sound/soc/codecs/tfa98xx/tfa9891_genregs.h | 1125 +++
  356. sound/soc/codecs/tfa98xx/tfa9891_init.c | 51 +
  357. sound/soc/codecs/tfa98xx/tfa9891_tfafieldnames.h | 515 ++
  358. sound/soc/codecs/tfa98xx/tfa9897_init.c | 131 +
  359. sound/soc/codecs/tfa98xx/tfa98xx.c | 3489 ++++++++
  360. sound/soc/codecs/tfa98xx/tfa98xx_genregs_N1C.h | 3853 +++++++++
  361. sound/soc/codecs/tfa98xx/tfa98xx_parameters.h | 754 ++
  362. sound/soc/codecs/tfa98xx/tfa98xx_tfafieldnames.h | 90 +
  363. sound/soc/codecs/tfa98xx/tfa_container.c | 2462 ++++++
  364. sound/soc/codecs/tfa98xx/tfa_container.h | 403 +
  365. sound/soc/codecs/tfa98xx/tfa_container_crc32.c | 108 +
  366. sound/soc/codecs/tfa98xx/tfa_debug.c | 286 +
  367. sound/soc/codecs/tfa98xx/tfa_dsp.c | 3406 ++++++++
  368. sound/soc/codecs/tfa98xx/tfa_dsp_fw.h | 119 +
  369. sound/soc/codecs/tfa98xx/tfa_hal.c | 124 +
  370. sound/soc/codecs/tfa98xx/tfa_internal.h | 108 +
  371. sound/soc/codecs/tfa98xx/tfa_osal.c | 40 +
  372. sound/soc/codecs/tfa98xx/tfa_service.h | 1010 +++
  373. sound/soc/codecs/usb-headset.c | 342 +
  374. sound/soc/codecs/usb-headset.h | 9 +
  375. sound/soc/codecs/wcd-mbhc-v2.c | 53 +-
  376. sound/soc/codecs/wcd9335.c | 8 +-
  377. sound/soc/msm/Kconfig | 4 +
  378. sound/soc/msm/msm-dai-fe.c | 5 +-
  379. sound/soc/msm/msm8998.c | 703 +-
  380. sound/soc/msm/qdsp6v2/Makefile | 5 +-
  381. sound/soc/msm/qdsp6v2/apr_elliptic.c | 225 +
  382. sound/soc/msm/qdsp6v2/msm-elliptic.c | 602 ++
  383. sound/soc/msm/qdsp6v2/msm-elliptic.h | 12 +
  384. sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 4 +-
  385. sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c | 6 +
  386. sound/soc/msm/qdsp6v2/q6adm.c | 2 +-
  387. sound/soc/msm/qdsp6v2/q6afe.c | 26 +-
  388. sound/soc/msm/qdsp6v2/q6core.c | 2 +-
  389. sound/soc/msm/qdsp6v2/q6voice.c | 2 +-
  390. sound/soc/soc-core.c | 8 +-
  391. 379 files changed, 138864 insertions(+), 3493 deletions(-)
  392. create mode 100644 arch/arm/boot/dts/qcom/batterydata-c1-atl-3350mAh.dtsi
  393. create mode 100644 arch/arm/boot/dts/qcom/batterydata-c1-sdi-3440mAh.dtsi
  394. create mode 100644 arch/arm/boot/dts/qcom/batterydata-itech-3020mAh.dtsi
  395. create mode 100644 arch/arm/boot/dts/qcom/dsi-panel-jdi-fhd-r63452-cmd.dtsi
  396. create mode 100644 arch/arm/boot/dts/qcom/dsi-panel-lgd-fhd-td4322-cmd.dtsi
  397. create mode 100644 arch/arm/boot/dts/qcom/dsi-panel-lgd-sw43401-wqhd-cmd.dtsi
  398. create mode 100644 arch/arm/boot/dts/qcom/sagit-camera-sensor-mtp.dtsi
  399. create mode 100644 arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dts
  400. create mode 100644 arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dtsi
  401. create mode 100644 arch/arm/boot/dts/qcom/sagit-msm8998-v2-mtp.dts
  402. create mode 100644 arch/arm/boot/dts/qcom/sagit-msm8998-v2.1-mtp.dts
  403. create mode 100644 arch/arm64/configs/sagit_user_defconfig
  404. create mode 100644 arch/arm64/include/asm/bootinfo.h
  405. create mode 100644 arch/arm64/include/asm/hwconf_manager.h
  406. create mode 100644 arch/arm64/kernel/bootinfo.c
  407. create mode 100644 arch/arm64/kernel/hwconf_manager.c
  408. create mode 100644 drivers/elliptic/Makefile
  409. create mode 100644 drivers/elliptic/elliptic.c
  410. create mode 100644 drivers/elliptic/elliptic_data_io.h
  411. create mode 100644 drivers/elliptic/elliptic_device.h
  412. create mode 100644 drivers/elliptic/elliptic_mixer_controls.h
  413. create mode 100644 drivers/elliptic/elliptic_sysfs.c
  414. create mode 100644 drivers/elliptic/elliptic_sysfs.h
  415. create mode 100644 drivers/elliptic/io_modules/Makefile
  416. create mode 100644 drivers/elliptic/io_modules/msm/elliptic_data_io.c
  417. create mode 100644 drivers/elliptic/io_modules/userspace/Makefile
  418. create mode 100644 drivers/elliptic/io_modules/userspace/elliptic_data_io.c
  419. create mode 100644 drivers/elliptic/io_modules/userspace_test/Makefile
  420. create mode 100644 drivers/elliptic/io_modules/userspace_test/elliptic_data_io.c
  421. create mode 100644 drivers/input/fingerprint/Kconfig
  422. create mode 100644 drivers/input/fingerprint/Makefile
  423. create mode 100644 drivers/input/fingerprint/fpc1268_tee/Kconfig
  424. create mode 100644 drivers/input/fingerprint/fpc1268_tee/Makefile
  425. create mode 100644 drivers/input/fingerprint/fpc1268_tee/fpc1020_tee.c
  426. create mode 100644 drivers/input/fingerprint/goodix/Kconfig
  427. create mode 100644 drivers/input/fingerprint/goodix/Makefile
  428. create mode 100644 drivers/input/fingerprint/goodix/gf_common.c
  429. create mode 100644 drivers/input/fingerprint/goodix/gf_common.h
  430. create mode 100644 drivers/input/fingerprint/goodix/gf_spi.c
  431. create mode 100644 drivers/input/fingerprint/goodix/gf_spi.h
  432. create mode 100644 drivers/input/fingerprint/goodix/platform.c
  433. create mode 100644 drivers/input/fingerprint/goodix_ta/Kconfig
  434. create mode 100644 drivers/input/fingerprint/goodix_ta/Makefile
  435. create mode 100644 drivers/input/fingerprint/goodix_ta/gf_spi.c
  436. create mode 100644 drivers/input/fingerprint/goodix_ta/gf_spi.h
  437. create mode 100644 drivers/input/fingerprint/goodix_ta/netlink.c
  438. create mode 100644 drivers/input/fingerprint/goodix_ta/platform.c
  439. create mode 100644 drivers/input/touchscreen/ft5x46/Kconfig
  440. create mode 100644 drivers/input/touchscreen/ft5x46/Makefile
  441. create mode 100644 drivers/input/touchscreen/ft5x46/focaltech_test.c
  442. create mode 100644 drivers/input/touchscreen/ft5x46/focaltech_test.h
  443. create mode 100644 drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.c
  444. create mode 100644 drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.h
  445. create mode 100644 drivers/input/touchscreen/ft5x46/ft5x46_ts.c
  446. create mode 100644 drivers/input/touchscreen/ft5x46/ft5x46_ts_i2c.c
  447. create mode 100644 drivers/input/touchscreen/ft5x46/ft5x46_ts_spi.c
  448. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/Kconfig
  449. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/Makefile
  450. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_active_pen.c
  451. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.c
  452. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.h
  453. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_fw_update.c
  454. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_gesture.c
  455. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_i2c.c
  456. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_proximity.c
  457. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_rmi_dev.c
  458. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_rmi_hid_i2c.c
  459. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_spi.c
  460. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_test_reporting.c
  461. create mode 100644 drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_video.c
  462. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_coef.h
  463. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_coef_ST.h
  464. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_defi.h
  465. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_func.c
  466. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_head.h
  467. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_prog.h
  468. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_prog_ST.h
  469. create mode 100644 drivers/media/platform/msm/camera_v2/sensor/ois/OIS_user.c
  470. create mode 100644 drivers/media/rc/peelir.c
  471. create mode 100644 drivers/media/rc/peelir.h
  472. create mode 100644 drivers/media/rc/pwm-ir.c
  473. create mode 100644 drivers/mfd/spk-id.c
  474. create mode 100644 drivers/platform/msm/gpio_rf.c
  475. mode change 100644 => 100755 drivers/power/supply/qcom/smb-lib.c
  476. mode change 100644 => 100755 drivers/power/supply/qcom/smb-lib.h
  477. mode change 100644 => 100755 drivers/soc/qcom/pil-q6v5-mss.c
  478. create mode 100644 drivers/soc/qcom/serial_num.c
  479. create mode 100644 drivers/staging/android/memsw_state.c
  480. create mode 100644 drivers/staging/android/memsw_state.h
  481. create mode 100644 firmware/ft5216_biel.fw.ihex
  482. create mode 100644 firmware/st_fts_biel.ftb.ihex
  483. create mode 100644 firmware/st_fts_lens.ftb.ihex
  484. create mode 100644 firmware/st_fts_lg.ftb.ihex
  485. create mode 100644 firmware/synaptics_jdi_3330_c1.fw.ihex
  486. create mode 100644 firmware/synaptics_jdi_3331_c1.fw.ihex
  487. create mode 100644 firmware/synaptics_lgd_4322_c1.fw.ihex
  488. create mode 100644 fs/f2fs/f2fs_ice.c
  489. create mode 100644 fs/f2fs/f2fs_ice.h
  490. create mode 100644 include/linux/cJSON.h
  491. create mode 100644 include/linux/hwinfo.h
  492. create mode 100644 include/linux/input/ft5x46_ts.h
  493. create mode 100644 include/linux/input/synaptics_dsx.h
  494. create mode 100644 include/linux/mfd/spk-id.h
  495. create mode 100644 include/media/pwm-ir.h
  496. create mode 100644 include/sound/apr_elliptic.h
  497. create mode 100644 lib/cJSON.c
  498. create mode 100644 security/pfe/pfk_f2fs.c
  499. create mode 100644 security/pfe/pfk_f2fs.h
  500. create mode 100644 sound/soc/codecs/tas2559/Makefile
  501. create mode 100644 sound/soc/codecs/tas2559/tas2559-codec.c
  502. create mode 100644 sound/soc/codecs/tas2559/tas2559-codec.h
  503. create mode 100644 sound/soc/codecs/tas2559/tas2559-core.c
  504. create mode 100644 sound/soc/codecs/tas2559/tas2559-core.h
  505. create mode 100644 sound/soc/codecs/tas2559/tas2559-misc.c
  506. create mode 100644 sound/soc/codecs/tas2559/tas2559-misc.h
  507. create mode 100644 sound/soc/codecs/tas2559/tas2559-regmap.c
  508. create mode 100644 sound/soc/codecs/tas2559/tas2559.h
  509. create mode 100644 sound/soc/codecs/tas2559/tas2560.h
  510. create mode 100644 sound/soc/codecs/tas2559/tiload.c
  511. create mode 100644 sound/soc/codecs/tas2559/tiload.h
  512. create mode 100644 sound/soc/codecs/tfa98xx/Makefile
  513. create mode 100644 sound/soc/codecs/tfa98xx/config.h
  514. create mode 100644 sound/soc/codecs/tfa98xx/tfa.h
  515. create mode 100644 sound/soc/codecs/tfa98xx/tfa1_tfafieldnames.h
  516. create mode 100644 sound/soc/codecs/tfa98xx/tfa2_tfafieldnames_N1C.h
  517. create mode 100644 sound/soc/codecs/tfa98xx/tfa9887B_init.c
  518. create mode 100644 sound/soc/codecs/tfa98xx/tfa9887_init.c
  519. create mode 100644 sound/soc/codecs/tfa98xx/tfa9887_tfafieldnames.h
  520. create mode 100644 sound/soc/codecs/tfa98xx/tfa9888_init.c
  521. create mode 100644 sound/soc/codecs/tfa98xx/tfa9890_init.c
  522. create mode 100644 sound/soc/codecs/tfa98xx/tfa9890_tfafieldnames.h
  523. create mode 100644 sound/soc/codecs/tfa98xx/tfa9891_genregs.h
  524. create mode 100644 sound/soc/codecs/tfa98xx/tfa9891_init.c
  525. create mode 100644 sound/soc/codecs/tfa98xx/tfa9891_tfafieldnames.h
  526. create mode 100644 sound/soc/codecs/tfa98xx/tfa9897_init.c
  527. create mode 100644 sound/soc/codecs/tfa98xx/tfa98xx.c
  528. create mode 100644 sound/soc/codecs/tfa98xx/tfa98xx_genregs_N1C.h
  529. create mode 100644 sound/soc/codecs/tfa98xx/tfa98xx_parameters.h
  530. create mode 100644 sound/soc/codecs/tfa98xx/tfa98xx_tfafieldnames.h
  531. create mode 100644 sound/soc/codecs/tfa98xx/tfa_container.c
  532. create mode 100644 sound/soc/codecs/tfa98xx/tfa_container.h
  533. create mode 100644 sound/soc/codecs/tfa98xx/tfa_container_crc32.c
  534. create mode 100644 sound/soc/codecs/tfa98xx/tfa_debug.c
  535. create mode 100644 sound/soc/codecs/tfa98xx/tfa_dsp.c
  536. create mode 100644 sound/soc/codecs/tfa98xx/tfa_dsp_fw.h
  537. create mode 100644 sound/soc/codecs/tfa98xx/tfa_hal.c
  538. create mode 100644 sound/soc/codecs/tfa98xx/tfa_internal.h
  539. create mode 100644 sound/soc/codecs/tfa98xx/tfa_osal.c
  540. create mode 100644 sound/soc/codecs/tfa98xx/tfa_service.h
  541. create mode 100644 sound/soc/codecs/usb-headset.c
  542. create mode 100644 sound/soc/codecs/usb-headset.h
  543. create mode 100644 sound/soc/msm/qdsp6v2/apr_elliptic.c
  544. create mode 100644 sound/soc/msm/qdsp6v2/msm-elliptic.c
  545. create mode 100644 sound/soc/msm/qdsp6v2/msm-elliptic.h
  546.  
  547. diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
  548. index 1ca89b5..a5ee614 100644
  549. --- a/Documentation/devicetree/bindings/gpu/adreno.txt
  550. +++ b/Documentation/devicetree/bindings/gpu/adreno.txt
  551. @@ -83,6 +83,9 @@ DCVS Core info
  552. Optional Properties:
  553. - qcom,initial-powerlevel: This value indicates which qcom,gpu-pwrlevel should be used at start time
  554. and when coming back out of resume
  555. +- qcom,restrict-powerlevel: This value to limit max GPU power level jump during the clock switch and
  556. + while coming back out of slumber. Max GPU power level jump still allowed
  557. + from the restricted-pwerlevel.
  558. - qcom,bus-control: Boolean. Enables an independent bus vote from the gpu frequency
  559. - qcom,bus-width: Bus width in number of bytes. This enables dynamic AB bus voting based on
  560. bus width and actual bus transactions.
  561. diff --git a/arch/Kconfig b/arch/Kconfig
  562. index 98f64ad..2156b1b 100644
  563. --- a/arch/Kconfig
  564. +++ b/arch/Kconfig
  565. @@ -527,6 +527,13 @@ config HAVE_COPY_THREAD_TLS
  566. normal C parameter passing, rather than extracting the syscall
  567. argument from pt_regs.
  568.  
  569. +config ARCH_HAS_ELF_RANDOMIZE
  570. + bool
  571. + help
  572. + An architecture supports choosing randomized locations for
  573. + stack, mmap, brk, and ET_DYN. Defined functions:
  574. + - arch_mmap_rnd()
  575. +
  576. config HAVE_ARCH_MMAP_RND_BITS
  577. bool
  578. help
  579. diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
  580. index 92e8ec5..1ded211 100644
  581. --- a/arch/arm/boot/dts/qcom/Makefile
  582. +++ b/arch/arm/boot/dts/qcom/Makefile
  583. @@ -102,39 +102,13 @@ dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-cdp.dtb \
  584. apq8096-v3-pmi8996-mdm9x55-slimbus-mtp.dtb \
  585. apq8096-v3-pmi8996-dragonboard.dtb
  586.  
  587. -dtb-$(CONFIG_ARCH_MSM8998) += msm8998-sim.dtb \
  588. - msm8998-rumi.dtb \
  589. - msm8998-cdp.dtb \
  590. - msm8998-mtp.dtb \
  591. - msm8998-qrd.dtb \
  592. - msm8998-v2-sim.dtb \
  593. - msm8998-v2-rumi.dtb \
  594. +dtb-$(CONFIG_ARCH_MSM8998) += msm8998-mtp.dtb \
  595. msm8998-v2-mtp.dtb \
  596. - msm8998-v2-cdp.dtb \
  597. - msm8998-v2-qrd.dtb \
  598. - msm8998-qrd-skuk.dtb \
  599. - msm8998-v2-qrd-skuk.dtb \
  600. - msm8998-qrd-vr1.dtb \
  601. - msm8998-v2-qrd-vr1.dtb \
  602. - msm8998-v2-qrd-skuk-evt3.dtb \
  603. - msm8998-v2-qrd-skuk-hdk.dtb \
  604. - apq8998-mtp.dtb \
  605. - apq8998-cdp.dtb \
  606. - apq8998-v2-mtp.dtb \
  607. - apq8998-v2-cdp.dtb \
  608. - apq8998-v2-qrd.dtb \
  609. - apq8998-v2-qrd-skuk-hdk.dtb \
  610. msm8998-v2.1-mtp.dtb \
  611. msm8998-v2.1-mtp-4k-display.dtb \
  612. - msm8998-v2.1-cdp.dtb \
  613. - msm8998-v2.1-qrd.dtb \
  614. - apq8998-v2.1-mtp.dtb \
  615. - apq8998-v2.1-cdp.dtb \
  616. - apq8998-v2.1-qrd.dtb \
  617. - apq8998-v2.1-mediabox.dtb \
  618. - msm8998-v2.1-interposer-sdm660-cdp.dtb \
  619. - msm8998-v2.1-interposer-sdm660-mtp.dtb \
  620. - msm8998-v2.1-interposer-sdm660-qrd.dtb
  621. + sagit-msm8998-mtp.dtb \
  622. + sagit-msm8998-v2-mtp.dtb \
  623. + sagit-msm8998-v2.1-mtp.dtb
  624.  
  625. dtb-$(CONFIG_ARCH_MSMHAMSTER) += msmhamster-rumi.dtb
  626.  
  627. diff --git a/arch/arm/boot/dts/qcom/batterydata-c1-atl-3350mAh.dtsi b/arch/arm/boot/dts/qcom/batterydata-c1-atl-3350mAh.dtsi
  628. new file mode 100644
  629. index 0000000..dbcdd24
  630. --- /dev/null
  631. +++ b/arch/arm/boot/dts/qcom/batterydata-c1-atl-3350mAh.dtsi
  632. @@ -0,0 +1,69 @@
  633. +
  634. +qcom,c1_atl_3350mah {
  635. + qcom,max-voltage-uv = <4400000>;
  636. + qcom,nom-batt-capacity-mah = <3350>;
  637. + qcom,fg-cc-cv-threshold-mv = <4390>;
  638. + qcom,batt-id-kohm = <68>;
  639. + qcom,battery-beta = <3435>;
  640. + qcom,battery-type = "c1_atl";
  641. + qcom,checksum = <0x23EB>;
  642. + qcom,gui-version = "PMI8998GUI - 2.0.0.54";
  643. + qcom,fg-profile-data = [
  644. + 66 1F B6 05
  645. + 70 0A 9D FC
  646. + 73 1D 37 F5
  647. + 41 12 2B 14
  648. + BF 18 D7 22
  649. + AD 45 96 52
  650. + 57 00 00 00
  651. + 0F 00 00 00
  652. + 00 00 8C C4
  653. + 9C CD 72 CB
  654. + 22 00 08 00
  655. + 41 E3 A1 07
  656. + 4D FD 6F F3
  657. + 45 E4 8F 12
  658. + FC 0C 23 33
  659. + 19 06 09 20
  660. + 27 00 14 00
  661. + F9 1F 4E 05
  662. + A9 0A 27 06
  663. + 2B 1D 43 01
  664. + 45 00 99 04
  665. + 38 19 CA 22
  666. + 98 45 CF 52
  667. + 59 00 00 00
  668. + 0C 00 00 00
  669. + 00 00 82 CC
  670. + 20 C2 57 AD
  671. + 1C 00 00 00
  672. + 29 F2 A1 07
  673. + 27 07 A3 EB
  674. + FB E4 FD 02
  675. + 59 D5 D2 1A
  676. + AD 33 CC FF
  677. + 07 10 00 00
  678. + 15 0D 66 46
  679. + 1C 00 40 00
  680. + 7E 01 0A FA
  681. + FF 00 00 00
  682. + 00 00 00 00
  683. + 00 00 00 00
  684. + 00 00 00 00
  685. + 00 00 00 00
  686. + 00 00 00 00
  687. + 00 00 00 00
  688. + 00 00 00 00
  689. + 00 00 00 00
  690. + 00 00 00 00
  691. + 00 00 00 00
  692. + 00 00 00 00
  693. + 00 00 00 00
  694. + 00 00 00 00
  695. + 00 00 00 00
  696. + 00 00 00 00
  697. + 00 00 00 00
  698. + 00 00 00 00
  699. + 00 00 00 00
  700. + ];
  701. +};
  702. diff --git a/arch/arm/boot/dts/qcom/batterydata-c1-sdi-3440mAh.dtsi b/arch/arm/boot/dts/qcom/batterydata-c1-sdi-3440mAh.dtsi
  703. new file mode 100644
  704. index 0000000..b9664d6
  705. --- /dev/null
  706. +++ b/arch/arm/boot/dts/qcom/batterydata-c1-sdi-3440mAh.dtsi
  707. @@ -0,0 +1,69 @@
  708. +
  709. +qcom,c1_sdi_3440mah {
  710. + qcom,max-voltage-uv = <4400000>;
  711. + qcom,nom-batt-capacity-mah = <3350>;
  712. + qcom,fg-cc-cv-threshold-mv = <4390>;
  713. + qcom,batt-id-kohm = <30>;
  714. + qcom,battery-beta = <3435>;
  715. + qcom,battery-type = "c1_sdi";
  716. + qcom,checksum = <0x623E>;
  717. + qcom,gui-version = "PMI8998GUI - 2.0.0.54";
  718. + qcom,fg-profile-data = [
  719. + A8 1F 68 05
  720. + B2 0A 09 FC
  721. + 4F 1D 2C E2
  722. + 27 0A 46 0C
  723. + 8A 18 4F 23
  724. + F7 44 CB 53
  725. + 5B 00 00 00
  726. + 0E 00 00 00
  727. + 00 00 08 B5
  728. + 30 C4 85 AC
  729. + 2E 00 08 00
  730. + 22 00 E1 ED
  731. + 10 06 79 FA
  732. + 37 04 EC 03
  733. + BE E5 33 22
  734. + 36 06 09 20
  735. + 27 00 14 00
  736. + EE 1F 48 05
  737. + C4 0A F9 05
  738. + 70 1D E7 D2
  739. + 4E 0B A9 14
  740. + EE 19 07 22
  741. + FC 3C 06 4B
  742. + 52 00 00 00
  743. + 13 00 00 00
  744. + 00 00 C3 CC
  745. + 41 AA 41 C3
  746. + 21 00 00 00
  747. + 66 00 E1 ED
  748. + F7 06 2A F2
  749. + F6 F4 FF FA
  750. + 9B F5 1B 1A
  751. + 99 33 CC FF
  752. + 07 10 00 00
  753. + 1A 0D 66 46
  754. + 21 00 40 00
  755. + 6C 01 0A FA
  756. + FF 00 00 00
  757. + 00 00 00 00
  758. + 00 00 00 00
  759. + 00 00 00 00
  760. + 00 00 00 00
  761. + 00 00 00 00
  762. + 00 00 00 00
  763. + 00 00 00 00
  764. + 00 00 00 00
  765. + 00 00 00 00
  766. + 00 00 00 00
  767. + 00 00 00 00
  768. + 00 00 00 00
  769. + 00 00 00 00
  770. + 00 00 00 00
  771. + 00 00 00 00
  772. + 00 00 00 00
  773. + 00 00 00 00
  774. + 00 00 00 00
  775. + ];
  776. +};
  777. diff --git a/arch/arm/boot/dts/qcom/batterydata-itech-3020mAh.dtsi b/arch/arm/boot/dts/qcom/batterydata-itech-3020mAh.dtsi
  778. new file mode 100644
  779. index 0000000..bf5a301
  780. --- /dev/null
  781. +++ b/arch/arm/boot/dts/qcom/batterydata-itech-3020mAh.dtsi
  782. @@ -0,0 +1,54 @@
  783. +/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  784. + * Copyright (C) 2017 XiaoMi, Inc.
  785. + *
  786. + * This program is free software; you can redistribute it and/or modify
  787. + * it under the terms of the GNU General Public License version 2 and
  788. + * only version 2 as published by the Free Software Foundation.
  789. + *
  790. + * This program is distributed in the hope that it will be useful,
  791. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  792. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  793. + * GNU General Public License for more details.
  794. + */
  795. +
  796. +qcom,itech-3020mah {
  797. + qcom,max-voltage-uv = <4400000>;
  798. + qcom,v-cutoff-uv = <3400000>;
  799. + qcom,chg-term-ua = <100000>;
  800. + qcom,batt-id-kohm = <150>;
  801. + qcom,battery-type = "itech_3020mah";
  802. + qcom,fg-profile-data = [
  803. + E8 83 0C 7D
  804. + E9 80 B2 76
  805. + 20 83 40 73
  806. + D7 6C 59 7E
  807. + FB 81 58 93
  808. + 0D AE 02 B1
  809. + 5B 12 D7 82
  810. + 86 78 F3 76
  811. + 4A 71 0C 83
  812. + 1B 80 73 8D
  813. + 49 89 07 82
  814. + D8 99 79 BC
  815. + AA C8 7C 17
  816. + F8 0B F4 5B
  817. + CE 6E 71 FD
  818. + 09 2E 79 44
  819. + 52 43 00 00
  820. + DE 3D 2A 37
  821. + D3 46 00 00
  822. + 00 00 00 00
  823. + 00 00 00 00
  824. + 3A 6B B7 69
  825. + DD 6C 83 83
  826. + 42 76 CA 68
  827. + 78 75 EF 80
  828. + D4 74 56 5B
  829. + 00 00 00 00
  830. + 0A A5 5A D2
  831. + 54 A0 71 0C
  832. + 28 00 FF 36
  833. + F0 11 30 03
  834. + 00 00 00 00
  835. + ];
  836. +};
  837. diff --git a/arch/arm/boot/dts/qcom/dsi-panel-jdi-fhd-r63452-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-jdi-fhd-r63452-cmd.dtsi
  838. new file mode 100644
  839. index 0000000..6d5eb05
  840. --- /dev/null
  841. +++ b/arch/arm/boot/dts/qcom/dsi-panel-jdi-fhd-r63452-cmd.dtsi
  842. @@ -0,0 +1,272 @@
  843. +/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
  844. + * Copyright (C) 2017 XiaoMi, Inc.
  845. + *
  846. + * This program is free software; you can redistribute it and/or modify
  847. + * it under the terms of the GNU General Public License version 2 and
  848. + * only version 2 as published by the Free Software Foundation.
  849. + *
  850. + * This program is distributed in the hope that it will be useful,
  851. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  852. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  853. + * GNU General Public License for more details.
  854. + */
  855. +
  856. +/*---------------------------------------------------------------------------
  857. + * This file is autogenerated file using gcdb parser. Please do not edit it.
  858. + * Update input XML file to add a new entry or update variable in this file
  859. + * VERSION = "1.0"
  860. + *---------------------------------------------------------------------------*/
  861. +&soc {
  862. + dsi_jdi_fhd_r63452_cmd: qcom,mdss_dsi_jdi_fhd_r63452_cmd {
  863. + qcom,mdss-dsi-panel-name = "jdi fhd cmd incell dsi panel";
  864. + qcom,mdss-dsi-panel-id = <0>;
  865. + qcom,mdss-dsi-panel-model = "JDI FHD R63452 CMD PANEL";
  866. + qcom,mdss-dsi-panel-sleepwrmod = <0>;
  867. + qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
  868. + qcom,mdss-dsi-panel-framerate = <60>;
  869. + qcom,mdss-dsi-virtual-channel-id = <0>;
  870. + qcom,mdss-dsi-stream = <0>;
  871. + qcom,mdss-dsi-panel-width = <1080>;
  872. + qcom,mdss-dsi-panel-height = <1920>;
  873. + qcom,mdss-dsi-h-front-porch = <120>;
  874. + qcom,mdss-dsi-h-back-porch = <40>;
  875. + qcom,mdss-dsi-h-pulse-width = <16>;
  876. + qcom,mdss-dsi-h-sync-skew = <0>;
  877. + qcom,mdss-dsi-v-back-porch = <4>;
  878. + qcom,mdss-dsi-v-front-porch = <4>;
  879. + qcom,mdss-dsi-v-pulse-width = <2>;
  880. + qcom,mdss-dsi-h-left-border = <0>;
  881. + qcom,mdss-dsi-h-right-border = <0>;
  882. + qcom,mdss-dsi-v-top-border = <0>;
  883. + qcom,mdss-dsi-v-bottom-border = <0>;
  884. + qcom,mdss-dsi-bpp = <24>;
  885. + qcom,mdss-dsi-color-order = <0>;
  886. + qcom,mdss-dsi-underflow-color = <0xff>;
  887. + qcom,mdss-dsi-border-color = <0>;
  888. + qcom,mdss-dsi-on-command = [
  889. + 29 00 00 00 00 00 02 b0 00
  890. + 29 00 00 00 00 00 02 d6 01
  891. + 29 00 00 00 00 00 0E EC 64 DC EC 3B 52 00 0B 0B 13 15 68 0B B5
  892. + 29 00 00 00 00 00 02 b0 03
  893. + 39 00 00 00 00 00 02 35 00
  894. + 39 00 00 00 00 00 02 36 00
  895. + 39 00 00 00 00 00 02 3A 77
  896. + 39 00 00 00 00 00 05 2A 00 00 04 37
  897. + 39 00 00 00 00 00 05 2B 00 00 07 7F
  898. + 39 00 00 00 00 00 03 44 00 00
  899. + 39 00 00 00 00 00 02 51 FF
  900. + 39 00 00 00 00 00 02 53 24
  901. + 39 00 00 00 00 00 02 55 00
  902. + 39 00 00 00 00 00 02 5E 00
  903. + 39 00 00 00 00 00 02 84 00
  904. + 05 01 00 00 14 00 02 29 00
  905. + 05 01 00 00 50 00 02 11 00
  906. + 29 00 00 00 00 00 02 B0 04
  907. + 39 00 00 00 00 00 02 84 00
  908. + 29 00 00 00 00 00 02 C8 11
  909. + 29 01 00 00 00 00 02 B0 03
  910. +];
  911. + qcom,mdss-dsi-off-command = [
  912. + 29 00 00 00 00 00 02 b0 00
  913. + 29 00 00 00 00 00 02 d6 01
  914. + 29 00 00 00 00 00 0E EC 64 DC EC 3B 52 00 0B 0B 13 15 68 0B 95
  915. + 29 00 00 00 00 00 02 b0 03
  916. + 05 01 00 00 02 00 02 28 00
  917. + 05 01 00 00 78 00 02 10 00];
  918. + qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
  919. + qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
  920. + qcom,mdss-dsi-h-sync-pulse = <0>;
  921. + qcom,mdss-dsi-traffic-mode = "burst_mode";
  922. + qcom,mdss-dsi-bllp-eof-power-mode;
  923. + qcom,mdss-dsi-bllp-power-mode;
  924. + qcom,mdss-dsi-lp11-init;
  925. + qcom,mdss-dsi-lane-0-state;
  926. + qcom,mdss-dsi-lane-1-state;
  927. + qcom,mdss-dsi-lane-2-state;
  928. + qcom,mdss-dsi-lane-3-state;
  929. + qcom,mdss-dsi-panel-timings = [e3 50 36 00 a9 a3 3a 50 3d 03 04 00];
  930. + qcom,mdss-dsi-t-clk-post = <0x20>;
  931. + qcom,mdss-dsi-t-clk-pre = <0x36>;
  932. + qcom,mdss-dsi-bl-min-level = <1>;
  933. + qcom,mdss-dsi-bl-max-level = <4095>;
  934. + qcom,mdss-brightness-max-level = <4095>;
  935. + qcom,mdss-dsi-dma-trigger = "trigger_sw";
  936. + qcom,mdss-dsi-mdp-trigger = "none";
  937. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  938. + qcom,mdss-dsi-reset-sequence = <1 10>, <0 1>, <1 10>;
  939. + qcom,mdss-pan-physical-width-dimension = <64>;
  940. + qcom,mdss-pan-physical-height-dimension = <114>;
  941. + qcom,mdss-dsi-te-pin-select = <1>;
  942. + qcom,mdss-dsi-wr-mem-start = <0x2c>;
  943. + qcom,mdss-dsi-wr-mem-continue = <0x3c>;
  944. + qcom,mdss-dsi-te-dcs-command = <1>;
  945. + qcom,mdss-dsi-te-check-enable;
  946. + qcom,mdss-dsi-te-using-te-pin;
  947. + qcom,mdss-dsi-tx-eot-append;
  948. + qcom,mdss-panel-on-dimming-delay = <120>;
  949. + qcom,dispparam-enabled;
  950. + qcom,mdss-night-brightness = <7 25 43 61>;
  951. + qcom,mdss-dsi-dispparam-cabcon-command = [
  952. + 29 01 00 00 00 00 02 B0 04
  953. + 15 01 00 00 00 00 02 55 81
  954. + 29 01 00 00 00 00 08 B8 AB 51 09 00 10 00 00
  955. + 29 01 00 00 00 00 1A CE 55 40 56 6E 87 A0 B6 CF E8 E9 EA EB EC ED EE EF FF 04 00 04 04 42 00 69 5A
  956. + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00
  957. + 29 01 00 00 00 00 02 B0 03
  958. + ];
  959. + qcom,mdss-dsi-dispparam-cabcguion-command = [
  960. + 29 01 00 00 00 00 02 B0 04
  961. + 15 01 00 00 00 00 02 55 81
  962. + 29 01 00 00 00 00 08 B8 AB 51 09 00 10 00 00
  963. + 29 01 00 00 00 00 1A CE 55 40 56 6E 87 A0 B6 CF E8 E9 EA EB EC ED EE EF FF 04 00 04 04 42 00 69 5A
  964. + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00
  965. + 29 01 00 00 00 00 02 B0 03
  966. + ];
  967. + qcom,mdss-dsi-dispparam-cabcstillon-command = [
  968. + 29 01 00 00 00 00 02 B0 04
  969. + 15 01 00 00 00 00 02 55 82
  970. + 29 01 00 00 00 00 08 B9 89 27 41 00 2E 00 00
  971. + 29 01 00 00 00 00 1A CE 55 40 46 4E 57 60 6A 75 81 8E 9B A8 B6 C3 D1 E2 FF 04 00 04 04 42 04 69 5A
  972. + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00
  973. + 29 01 00 00 00 00 02 B0 03
  974. + ];
  975. + qcom,mdss-dsi-dispparam-cabcmovieon-command = [
  976. + 29 01 00 00 00 00 02 B0 04
  977. + 15 01 00 00 00 00 02 55 83
  978. + 29 01 00 00 00 00 08 BA B7 27 3E 00 1F 00 00
  979. + 29 01 00 00 00 00 1A CE 55 40 46 4E 57 60 6A 75 81 8E 9B A8 B6 C3 D1 E2 FF 04 00 04 04 42 04 69 5A
  980. + 29 01 00 00 00 00 0A F9 64 3F E0 BE 00 8D BF 80 00
  981. + 29 01 00 00 00 00 02 B0 03
  982. + ];
  983. + qcom,mdss-dsi-dispparam-cabcoff-command = [
  984. + 39 01 00 00 01 00 02 55 00
  985. + ];
  986. + qcom,mdss-dsi-dispparam-dimmingon-command = [
  987. + 39 01 00 00 01 00 02 53 2C
  988. + ];
  989. + qcom,mdss-dsi-dispparam-idleon-command = [
  990. + 39 01 00 00 01 00 02 39 00
  991. + ];
  992. + qcom,mdss-dsi-dispparam-idleoff-command = [
  993. + 39 01 00 00 01 00 02 38 00
  994. + ];
  995. + qcom,mdss-dsi-dispparam-warm-command = [
  996. + 29 01 00 00 00 00 02 B0 04
  997. + 39 01 00 00 00 00 02 84 80
  998. + 29 01 00 00 00 00 32 C8 01 00 FB 05 FD FC E0 00 FA 02 F6 FC F0 00 F8 FF ED FC 01 00 FA 05 F9 BC 00 FA 02 F4 EB 00 FB FE EC FC 00 FA 05 FC FC 00 F9 03 F6 DB 00 FA 00 F6 AB
  999. + 29 01 00 00 00 00 02 CA 1C
  1000. + 29 01 00 00 00 00 02 B0 03
  1001. + ];
  1002. + qcom,mdss-dsi-dispparam-warm-command-state = "dsi_hs_mode";
  1003. + qcom,mdss-dsi-dispparam-cold-command = [
  1004. + 29 01 00 00 00 00 02 B0 04
  1005. + 39 01 00 00 00 00 02 84 7F
  1006. + 29 01 00 00 00 00 32 C8 01 00 FB 05 FD FC E0 00 FA 02 F6 FC F0 00 F8 FF ED FC 01 00 FA 05 F9 BC 00 FA 02 F4 EB 00 FB FE EC FC 00 FA 05 FC FC 00 F9 03 F6 DB 00 FA 00 F6 AB
  1007. + 29 01 00 00 00 00 02 CA 1C
  1008. + 29 01 00 00 00 00 02 B0 03
  1009. + ];
  1010. + qcom,mdss-dsi-dispparam-cold-command-state = "dsi_hs_mode";
  1011. + qcom,mdss-dsi-dispparam-default-command = [
  1012. + 29 01 00 00 00 00 02 B0 04
  1013. + 39 01 00 00 00 00 02 84 00
  1014. + 29 01 00 00 00 00 02 C8 11
  1015. + 29 01 00 00 00 00 02 CA 1C
  1016. + 29 01 00 00 00 00 02 B0 03
  1017. + ];
  1018. + qcom,mdss-dsi-dispparam-default-command-state = "dsi_hs_mode";
  1019. + qcom,mdss-dsi-dispparam-papermode-command = [
  1020. + 29 01 00 00 00 00 02 55 80
  1021. + 29 01 00 00 00 00 02 B0 04
  1022. + 39 01 00 00 00 00 02 84 00
  1023. + 29 01 00 00 00 00 14 c8 01 00 f4 07 fc e3 f3 00 f6 04 f7 fc f2 00 fd ff 02 00 12
  1024. + 29 01 00 00 00 00 2C CA 1D FC FC 48 00 00 D3 00 00 D3 00 00 D3 00 00 D3 00 00 D3 00 00 D3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1025. + 29 01 00 00 00 00 02 B0 03
  1026. + ];
  1027. + qcom,mdss-dsi-dispparam-papermode-command-state = "dsi_hs_mode";
  1028. + qcom,mdss-dsi-dispparam-papermode1-command = [
  1029. + 29 01 00 00 00 00 02 B0 04
  1030. + 39 01 00 00 00 00 02 84 00
  1031. + 29 01 00 00 00 00 32 C8 01 00 F8 07 FB D7 F1 00 F8 01 F7 FC F1 00 F6 01 F2 C0 02 00 F9 05 01 59 00 F8 01 F9 B1 00 F7 FE ED FC 00 F9 06 FC ED 00 F8 01 F7 FC 00 F7 01 F6 82
  1032. + 29 01 00 00 00 00 02 CA 1C
  1033. + 29 01 00 00 00 00 02 B0 03
  1034. + ];
  1035. + qcom,mdss-dsi-dispparam-papermode1-command-state = "dsi_hs_mode";
  1036. + qcom,mdss-dsi-dispparam-papermode2-command = [
  1037. + 29 01 00 00 00 00 02 B0 04
  1038. + 39 01 00 00 00 00 02 84 00
  1039. + 29 01 00 00 00 00 32 C8 01 00 FC 03 F8 FC 00 00 FC FF F5 BB 00 00 02 FF F9 76 00 00 FC 03 F8 FC 00 FC FF F5 BB 00 02 FF F9 76 00 FC 03 F8 FC 00 FC FF F5 BB 00 02 FF F9 76
  1040. + 29 01 00 00 00 00 02 CA 1C
  1041. + 29 01 00 00 00 00 02 B0 03
  1042. + ];
  1043. + qcom,mdss-dsi-dispparam-papermode2-command-state = "dsi_hs_mode";
  1044. + qcom,mdss-dsi-dispparam-papermode3-command = [
  1045. + 29 01 00 00 00 00 02 B0 04
  1046. + 39 01 00 00 00 00 02 84 00
  1047. + 29 01 00 00 00 00 32 c8 01 00 FC 03 F8 FC 00 00 FB FF F6 AA 00 00 FE 01 FA 4B 00 00 FC 03 F8 FC 00 FB FF F6 AA 00 FE 01 FA 4B 00 FC 03 F8 FC 00 FB FF F6 AA 00 FE 01 FA 4B
  1048. + 29 01 00 00 00 00 02 CA 1C
  1049. + 29 01 00 00 00 00 02 B0 03
  1050. + ];
  1051. + qcom,mdss-dsi-dispparam-papermode3-command-state = "dsi_hs_mode";
  1052. + qcom,mdss-dsi-dispparam-papermode4-command = [
  1053. + 29 01 00 00 00 00 02 B0 04
  1054. + 39 01 00 00 00 00 02 84 00
  1055. + 29 01 00 00 00 00 32 c8 01 00 FC 03 F8 FC 00 00 FD FF F7 9A 00 00 03 01 FC 27 00 00 FC 03 F8 FC 00 FD FF F7 9A 00 03 01 FC 27 00 FC 03 F8 FC 00 FD FF F7 9A 00 03 01 FC 27
  1056. + 29 01 00 00 00 00 02 CA 1C
  1057. + 29 01 00 00 00 00 02 B0 03
  1058. + ];
  1059. + qcom,mdss-dsi-dispparam-papermode4-command-state = "dsi_hs_mode";
  1060. + qcom,mdss-dsi-dispparam-papermode5-command = [
  1061. + 29 01 00 00 00 00 02 55 80
  1062. + 29 01 00 00 00 00 02 B0 04
  1063. + 39 01 00 00 00 00 02 84 00
  1064. + 29 01 00 00 00 00 14 c8 01 00 f4 08 fb d5 f3 00 f5 04 f7 fc f1 00 fd ff 02 00 22
  1065. + 29 01 00 00 00 00 2C CA 1D FC FC E4 00 00 FA 00 00 FA 00 00 FA 00 00 FA 00 00 FA 00 00 FA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1066. + 29 01 00 00 00 00 02 B0 03
  1067. + ];
  1068. + qcom,mdss-dsi-dispparam-papermode5-command-state = "dsi_hs_mode";
  1069. + qcom,mdss-dsi-dispparam-papermode6-command = [
  1070. + 29 01 00 00 00 00 02 55 80
  1071. + 29 01 00 00 00 00 02 B0 04
  1072. + 39 01 00 00 00 00 02 84 00
  1073. + 29 01 00 00 00 00 14 c8 01 00 f4 08 fb db f2 00 f6 04 f7 fc f3 00 fd ff 02 00 22
  1074. + 29 01 00 00 00 00 2C CA 1D FC FC B0 00 00 ED 00 00 ED 00 00 ED 00 00 ED 00 00 ED 00 00 ED 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1075. + 29 01 00 00 00 00 02 B0 03
  1076. + ];
  1077. + qcom,mdss-dsi-dispparam-papermode6-command-state = "dsi_hs_mode";
  1078. + qcom,mdss-dsi-dispparam-papermode7-command = [
  1079. + 29 01 00 00 00 00 02 55 80
  1080. + 29 01 00 00 00 00 02 B0 04
  1081. + 39 01 00 00 00 00 02 84 00
  1082. + 29 01 00 00 00 00 14 c8 01 00 f4 08 fc df f2 00 f6 04 f7 fc f1 00 fd ff 02 00 12
  1083. + 29 01 00 00 00 00 2C CA 1D FC FC 7C 00 00 E0 00 00 E0 00 00 E0 00 00 E0 00 00 E0 00 00 E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1084. + 29 01 00 00 00 00 02 B0 03
  1085. + ];
  1086. + qcom,mdss-dsi-dispparam-papermode7-command-state = "dsi_hs_mode";
  1087. + qcom,mdss-dsi-dispparam-normal1-command = [
  1088. + 29 01 00 00 00 00 02 B0 04
  1089. + 39 01 00 00 00 00 02 84 00
  1090. + 29 01 00 00 00 00 32 C8 01 00 FD FE FC D8 00 00 FC FE FB DC 00 00 01 F3 F0 FC 00 00 FE FD F9 99 00 FE FC FB C8 00 FF F4 EB FC 00 FE FA FD FC 00 FE FB FA E5 00 FF F6 F2 D3
  1091. + 29 01 00 00 00 00 02 CA 1C
  1092. + 29 01 00 00 00 00 02 B0 03
  1093. + ];
  1094. + qcom,mdss-dsi-dispparam-normal1-command-state = "dsi_hs_mode";
  1095. + qcom,mdss-dsi-dispparam-normal2-command = [
  1096. + 29 01 00 00 00 00 02 B0 04
  1097. + 39 01 00 00 00 00 02 84 00
  1098. + 29 01 00 00 00 00 02 C8 11
  1099. + 29 01 00 00 00 00 02 CA 1C
  1100. + 29 01 00 00 00 00 02 B0 03
  1101. + ];
  1102. + qcom,mdss-dsi-dispparam-normal2-command-state = "dsi_hs_mode";
  1103. + qcom,mdss-dsi-dispparam-srgb-command = [
  1104. + 05 01 00 00 10 00 02 11 00
  1105. + 29 01 00 00 00 00 02 B0 00
  1106. + 29 01 00 00 00 00 02 D6 01
  1107. + 29 01 00 00 00 00 13 C8 01 00 FD FE FC FC 00 00 FC FE FB FC 00 00 01 F3 F0 FC
  1108. + 29 01 00 00 00 00 02 CA 1D
  1109. + 29 01 00 00 00 00 02 84 00
  1110. + 29 01 00 00 00 00 02 B0 03
  1111. + ];
  1112. + qcom,mdss-dsi-dispparam-srgb-command-state = "dsi_hs_mode";
  1113. + };
  1114. +};
  1115. diff --git a/arch/arm/boot/dts/qcom/dsi-panel-lgd-fhd-td4322-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-lgd-fhd-td4322-cmd.dtsi
  1116. new file mode 100644
  1117. index 0000000..3c32b6c
  1118. --- /dev/null
  1119. +++ b/arch/arm/boot/dts/qcom/dsi-panel-lgd-fhd-td4322-cmd.dtsi
  1120. @@ -0,0 +1,270 @@
  1121. +/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
  1122. + * Copyright (C) 2017 XiaoMi, Inc.
  1123. + *
  1124. + * This program is free software; you can redistribute it and/or modify
  1125. + * it under the terms of the GNU General Public License version 2 and
  1126. + * only version 2 as published by the Free Software Foundation.
  1127. + *
  1128. + * This program is distributed in the hope that it will be useful,
  1129. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1130. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1131. + * GNU General Public License for more details.
  1132. + */
  1133. +
  1134. +/*---------------------------------------------------------------------------
  1135. + * This file is autogenerated file using gcdb parser. Please do not edit it.
  1136. + * Update input XML file to add a new entry or update variable in this file
  1137. + * VERSION = "1.0"
  1138. + *---------------------------------------------------------------------------*/
  1139. +&soc {
  1140. + dsi_lgd_fhd_td4322_cmd: qcom,mdss_dsi_lgd_fhd_td4322_cmd {
  1141. + qcom,mdss-dsi-panel-name = "lgd fhd cmd incell dsi panel";
  1142. + qcom,mdss-dsi-panel-id = <1>;
  1143. + qcom,mdss-dsi-panel-model = "LGD FHD TD4322 CMD PANEL";
  1144. + qcom,mdss-dsi-panel-sleepwrmod = <0>;
  1145. + qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
  1146. + qcom,mdss-dsi-panel-framerate = <60>;
  1147. + qcom,mdss-dsi-virtual-channel-id = <0>;
  1148. + qcom,mdss-dsi-stream = <0>;
  1149. + qcom,mdss-dsi-panel-width = <1080>;
  1150. + qcom,mdss-dsi-panel-height = <1920>;
  1151. + qcom,mdss-dsi-h-front-porch = <120>;
  1152. + qcom,mdss-dsi-h-back-porch = <40>;
  1153. + qcom,mdss-dsi-h-pulse-width = <16>;
  1154. + qcom,mdss-dsi-h-sync-skew = <0>;
  1155. + qcom,mdss-dsi-v-back-porch = <4>;
  1156. + qcom,mdss-dsi-v-front-porch = <4>;
  1157. + qcom,mdss-dsi-v-pulse-width = <2>;
  1158. + qcom,mdss-dsi-h-left-border = <0>;
  1159. + qcom,mdss-dsi-h-right-border = <0>;
  1160. + qcom,mdss-dsi-v-top-border = <0>;
  1161. + qcom,mdss-dsi-v-bottom-border = <0>;
  1162. + qcom,mdss-dsi-bpp = <24>;
  1163. + qcom,mdss-dsi-color-order = <0>;
  1164. + qcom,mdss-dsi-underflow-color = <0xff>;
  1165. + qcom,mdss-dsi-border-color = <0>;
  1166. + qcom,mdss-dsi-on-command = [
  1167. + 15 00 00 00 00 00 02 51 ff
  1168. + 15 00 00 00 00 00 02 53 24
  1169. + 15 00 00 00 00 00 02 55 00
  1170. + 15 00 00 00 00 00 02 35 00
  1171. + 39 01 00 00 00 00 05 30 00 00 02 A7
  1172. + 05 01 00 00 46 00 02 11 00
  1173. + 05 01 00 00 14 00 02 29 00
  1174. + 29 00 00 00 00 00 02 B0 04
  1175. + 39 00 00 00 00 00 02 84 00
  1176. + 29 00 00 00 00 00 02 C8 11
  1177. + 29 00 00 00 00 00 02 CA 1C
  1178. + 29 00 00 00 00 00 02 EA 0F
  1179. + 29 01 00 00 00 00 02 B0 03];
  1180. + qcom,mdss-dsi-off-command = [
  1181. + 05 01 00 00 14 00 02 28 00
  1182. + 05 01 00 00 78 00 02 10 00];
  1183. + qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
  1184. + qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
  1185. + qcom,esd-check-enabled;
  1186. + qcom,mdss-dsi-panel-status-check-mode = "reg_multi_read";
  1187. + /* mdss-dsi-panel-status-command store all ESD releated commands and expected
  1188. + status values, and every command can have more than one returned values */
  1189. + qcom,mdss-dsi-panel-status-command = [
  1190. + 06 01 00 00 00 00 02 0A 1c
  1191. + 06 01 00 00 00 00 02 EB 00];
  1192. + qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
  1193. + qcom,mdss-dsi-panel-mcap-off-cmds = [29 01 00 00 00 00 02 B0 00];
  1194. + qcom,mdss-dsi-panel-mcap-on-cmds = [29 01 00 00 00 00 02 B0 03];
  1195. + qcom,mdss-dsi-panel-mcap-off-cmds-state = "dsi_lp_mode";
  1196. + qcom,mdss-dsi-panel-mcap-on-cmds-state = "dsi_lp_mode";
  1197. + qcom,mdss-dsi-tx-eot-append;
  1198. + qcom,mdss-dsi-h-sync-pulse = <0>;
  1199. + qcom,mdss-dsi-traffic-mode = "burst_mode";
  1200. + qcom,mdss-dsi-bllp-eof-power-mode;
  1201. + qcom,mdss-dsi-bllp-power-mode;
  1202. + qcom,mdss-dsi-lp11-init;
  1203. + qcom,mdss-dsi-lane-0-state;
  1204. + qcom,mdss-dsi-lane-1-state;
  1205. + qcom,mdss-dsi-lane-2-state;
  1206. + qcom,mdss-dsi-lane-3-state;
  1207. + qcom,mdss-dsi-panel-timings = [e3 50 36 00 a9 a3 3a 50 3d 03 04 00];
  1208. + qcom,mdss-dsi-t-clk-post = <0x20>;
  1209. + qcom,mdss-dsi-t-clk-pre = <0x36>;
  1210. + qcom,mdss-dsi-bl-min-level = <1>;
  1211. + qcom,mdss-dsi-bl-max-level = <4095>;
  1212. + qcom,mdss-brightness-max-level = <4095>;
  1213. + qcom,mdss-dsi-dma-trigger = "trigger_sw";
  1214. + qcom,mdss-dsi-mdp-trigger = "none";
  1215. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  1216. + qcom,mdss-dsi-reset-sequence = <0 1>, <1 20>;
  1217. + qcom,mdss-pan-physical-width-dimension = <64>;
  1218. + qcom,mdss-pan-physical-height-dimension = <114>;
  1219. + qcom,mdss-dsi-te-pin-select = <1>;
  1220. + qcom,mdss-dsi-wr-mem-start = <0x2c>;
  1221. + qcom,mdss-dsi-wr-mem-continue = <0x3c>;
  1222. + qcom,mdss-dsi-te-dcs-command = <1>;
  1223. + qcom,mdss-dsi-te-check-enable;
  1224. + qcom,mdss-dsi-te-using-te-pin;
  1225. + qcom,mdss-panel-on-dimming-delay = <120>;
  1226. + qcom,dispparam-enabled;
  1227. + qcom,mdss-night-brightness = <7 25 43 61>;
  1228. + qcom,mdss-dsi-dispparam-cabcon-command = [
  1229. + 29 01 00 00 00 00 02 B0 04
  1230. + 15 01 00 00 00 00 02 55 81
  1231. + 29 01 00 00 00 00 08 B8 AB 51 09 00 10 00 00
  1232. + 29 01 00 00 00 00 1A CE 55 40 56 6E 87 A0 B6 CF E8 E9 EA EB EC ED EE EF FF 04 00 04 04 42 00 69 5A
  1233. + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00
  1234. + 29 01 00 00 00 00 02 B0 03
  1235. + ];
  1236. + qcom,mdss-dsi-dispparam-cabcguion-command = [
  1237. + 29 01 00 00 00 00 02 B0 04
  1238. + 15 01 00 00 00 00 02 55 81
  1239. + 29 01 00 00 00 00 08 B8 AB 51 09 00 10 00 00
  1240. + 29 01 00 00 00 00 1A CE 55 40 56 6E 87 A0 B6 CF E8 E9 EA EB EC ED EE EF FF 04 00 04 04 42 00 69 5A
  1241. + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00
  1242. + 29 01 00 00 00 00 02 B0 03
  1243. + ];
  1244. + qcom,mdss-dsi-dispparam-cabcstillon-command = [
  1245. + 29 01 00 00 00 00 02 B0 04
  1246. + 15 01 00 00 00 00 02 55 82
  1247. + 29 01 00 00 00 00 08 B9 89 27 41 00 2E 00 00
  1248. + 29 01 00 00 00 00 1A CE 55 40 46 4E 57 60 6A 75 81 8E 9B A8 B6 C3 D1 E2 FF 04 00 04 04 42 04 69 5A
  1249. + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00
  1250. + 29 01 00 00 00 00 02 B0 03
  1251. + ];
  1252. + qcom,mdss-dsi-dispparam-cabcmovieon-command = [
  1253. + 29 01 00 00 00 00 02 B0 04
  1254. + 15 01 00 00 00 00 02 55 83
  1255. + 29 01 00 00 00 00 08 BA B7 27 3E 00 1F 00 00
  1256. + 29 01 00 00 00 00 1A CE 55 40 46 4E 57 60 6A 75 81 8E 9B A8 B6 C3 D1 E2 FF 04 00 04 04 42 04 69 5A
  1257. + 29 01 00 00 00 00 0A F9 64 3F E0 BE 00 8D BF 80 00
  1258. + 29 01 00 00 00 00 02 B0 03
  1259. + ];
  1260. + qcom,mdss-dsi-dispparam-cabcoff-command = [
  1261. + 39 01 00 00 01 00 02 55 00
  1262. + ];
  1263. + qcom,mdss-dsi-dispparam-dimmingon-command = [
  1264. + 39 01 00 00 01 00 02 53 2C
  1265. + ];
  1266. + qcom,mdss-dsi-dispparam-idleon-command = [
  1267. + 39 01 00 00 01 00 02 39 00
  1268. + ];
  1269. + qcom,mdss-dsi-dispparam-idleoff-command = [
  1270. + 39 01 00 00 01 00 02 38 00
  1271. + ];
  1272. + qcom,mdss-dsi-dispparam-warm-command = [
  1273. + 29 01 00 00 00 00 02 B0 04
  1274. + 39 01 00 00 00 00 02 84 80
  1275. + 29 01 00 00 00 00 38 C8 01 00 11 04 0A FC F0 00 0E 01 07 FC F0 00 10 01 01 FC 00 00 0E 04 02 BE F0 00 0D 01 05 DB F0 00 10 01 01 FC 00 00 11 04 0A FC F0 00 0E 00 06 E0 F0 00 10 01 01 B9 00
  1276. + 29 01 00 00 00 00 02 CA 1C
  1277. + 29 01 00 00 00 00 02 B0 03
  1278. + ];
  1279. + qcom,mdss-dsi-dispparam-warm-command-state = "dsi_hs_mode";
  1280. + qcom,mdss-dsi-dispparam-cold-command = [
  1281. + 29 01 00 00 00 00 02 B0 04
  1282. + 39 01 00 00 00 00 02 84 7F
  1283. + 29 01 00 00 00 00 38 C8 01 00 11 04 0A FC F0 00 0E 01 07 FC F0 00 10 01 01 FC 00 00 0E 04 02 BE F0 00 0D 01 05 DB F0 00 10 01 01 FC 00 00 11 04 0A FC F0 00 0E 00 06 E0 F0 00 10 01 01 B9 00
  1284. + 29 01 00 00 00 00 02 CA 1C
  1285. + 29 01 00 00 00 00 02 B0 03
  1286. + ];
  1287. + qcom,mdss-dsi-dispparam-cold-command-state = "dsi_hs_mode";
  1288. + qcom,mdss-dsi-dispparam-default-command = [
  1289. + 29 01 00 00 00 00 02 B0 04
  1290. + 39 01 00 00 00 00 02 84 00
  1291. + 29 01 00 00 00 00 02 C8 11
  1292. + 29 01 00 00 00 00 02 CA 1C
  1293. + 29 01 00 00 00 00 02 B0 03
  1294. + ];
  1295. + qcom,mdss-dsi-dispparam-default-command-state = "dsi_hs_mode";
  1296. + qcom,mdss-dsi-dispparam-papermode-command = [
  1297. + 29 01 00 00 00 00 02 55 80
  1298. + 29 01 00 00 00 00 02 B0 04
  1299. + 39 01 00 00 00 00 02 84 00
  1300. + 29 01 00 00 00 00 14 C8 01 00 FF 01 FF FC 00 00 FD FF FF F9 00 00 FE 01 FB 00 00
  1301. + 29 01 00 00 00 00 2C CA 1D FC FC 50 00 00 D5 00 00 D5 00 00 D5 00 00 D5 00 00 D5 00 00 D5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1302. + 29 01 00 00 00 00 02 B0 03
  1303. + ];
  1304. + qcom,mdss-dsi-dispparam-papermode-command-state = "dsi_hs_mode";
  1305. + qcom,mdss-dsi-dispparam-papermode1-command = [
  1306. + 29 01 00 00 00 00 02 B0 04
  1307. + 39 01 00 00 00 00 02 84 00
  1308. + 29 01 00 00 00 00 14 C8 01 00 FF 01 02 FC 00 00 FA 01 FF F7 00 00 FE 01 FA C2 00
  1309. + 29 01 00 00 00 00 02 CA 1C
  1310. + 29 01 00 00 00 00 02 B0 03
  1311. + ];
  1312. + qcom,mdss-dsi-dispparam-papermode1-command-state = "dsi_hs_mode";
  1313. + qcom,mdss-dsi-dispparam-papermode2-command = [
  1314. + 29 01 00 00 00 00 02 B0 04
  1315. + 39 01 00 00 00 00 02 84 00
  1316. + 29 01 00 00 00 00 32 C8 01 00 FC 03 F8 FC 00 00 FC FF F5 BB 00 00 02 FF F9 76 00 00 FC 03 F8 FC 00 FC FF F5 BB 00 02 FF F9 76 00 FC 03 F8 FC 00 FC FF F5 BB 00 02 FF F9 76
  1317. + 29 01 00 00 00 00 02 CA 1C
  1318. + 29 01 00 00 00 00 02 B0 03
  1319. + ];
  1320. + qcom,mdss-dsi-dispparam-papermode2-command-state = "dsi_hs_mode";
  1321. + qcom,mdss-dsi-dispparam-papermode3-command = [
  1322. + 29 01 00 00 00 00 02 B0 04
  1323. + 39 01 00 00 00 00 02 84 00
  1324. + 29 01 00 00 00 00 32 C8 01 00 FC 03 F8 FC 00 00 FB FF F6 AA 00 00 FE 01 FA 4B 00 00 FC 03 F8 FC 00 FB FF F6 AA 00 FE 01 FA 4B 00 FC 03 F8 FC 00 FB FF F6 AA 00 FE 01 FA 4B
  1325. + 29 01 00 00 00 00 02 CA 1C
  1326. + 29 01 00 00 00 00 02 B0 03
  1327. + ];
  1328. + qcom,mdss-dsi-dispparam-papermode3-command-state = "dsi_hs_mode";
  1329. + qcom,mdss-dsi-dispparam-papermode4-command = [
  1330. + 29 01 00 00 00 00 02 B0 04
  1331. + 39 01 00 00 00 00 02 84 00
  1332. + 29 01 00 00 00 00 32 C8 01 00 FC 03 F8 FC 00 00 FD FF F7 9A 00 00 03 01 FC 27 00 00 FC 03 F8 FC 00 FD FF F7 9A 00 03 01 FC 27 00 FC 03 F8 FC 00 FD FF F7 9A 00 03 01 FC 27
  1333. + 29 01 00 00 00 00 02 CA 1C
  1334. + 29 01 00 00 00 00 02 B0 03
  1335. + ];
  1336. + qcom,mdss-dsi-dispparam-papermode4-command-state = "dsi_hs_mode";
  1337. + qcom,mdss-dsi-dispparam-papermode5-command = [
  1338. + 29 01 00 00 00 00 02 55 80
  1339. + 29 01 00 00 00 00 02 B0 04
  1340. + 39 01 00 00 00 00 02 84 00
  1341. + 29 01 00 00 00 00 14 C8 01 00 FF 01 FF FC 00 00 F9 01 FE F8 00 00 FE 01 FC 00 00
  1342. + 29 01 00 00 00 00 2C CA 1D FC FC E4 00 00 FA 00 00 FA 00 00 FA 00 00 FA 00 00 FA 00 00 FA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1343. + 29 01 00 00 00 00 02 B0 03
  1344. + ];
  1345. + qcom,mdss-dsi-dispparam-papermode5-command-state = "dsi_hs_mode";
  1346. + qcom,mdss-dsi-dispparam-papermode6-command = [
  1347. + 29 01 00 00 00 00 02 55 80
  1348. + 29 01 00 00 00 00 02 B0 04
  1349. + 39 01 00 00 00 00 02 84 00
  1350. + 29 01 00 00 00 00 14 C8 01 00 FF 01 FF FC 00 00 F9 01 FE F8 00 00 FE 01 FC 00 00
  1351. + 29 01 00 00 00 00 2C CA 1D FC FC C4 00 00 F2 00 00 F2 00 00 F2 00 00 F2 00 00 F2 00 00 F2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1352. + 29 01 00 00 00 00 02 B0 03
  1353. + ];
  1354. + qcom,mdss-dsi-dispparam-papermode6-command-state = "dsi_hs_mode";
  1355. + qcom,mdss-dsi-dispparam-papermode7-command = [
  1356. + 29 01 00 00 00 00 02 55 80
  1357. + 29 01 00 00 00 00 02 B0 04
  1358. + 39 01 00 00 00 00 02 84 00
  1359. + 29 01 00 00 00 00 14 C8 01 00 FF 01 FF FC 00 00 FD FF FF F9 00 00 FE 01 FB 00 00
  1360. + 29 01 00 00 00 00 2C CA 1D FC FC 84 00 00 E2 00 00 E2 00 00 E2 00 00 E2 00 00 E2 00 00 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  1361. + 29 01 00 00 00 00 02 B0 03
  1362. + ];
  1363. + qcom,mdss-dsi-dispparam-papermode7-command-state = "dsi_hs_mode";
  1364. + qcom,mdss-dsi-dispparam-normal1-command = [
  1365. + 29 01 00 00 00 00 02 B0 04
  1366. + 39 01 00 00 00 00 02 84 00
  1367. + 29 01 00 00 00 00 38 C8 01 00 11 04 0A FC F0 00 0E 01 07 FC F0 00 10 01 01 FC 00 00 0E 04 02 BE F0 00 0D 01 05 DB F0 00 10 01 01 FC 00 00 11 04 0A FC F0 00 0E 00 06 E0 F0 00 10 01 01 B9 00
  1368. + 29 01 00 00 00 00 02 CA 1C
  1369. + 29 01 00 00 00 00 02 B0 03
  1370. + ];
  1371. + qcom,mdss-dsi-dispparam-normal1-command-state = "dsi_hs_mode";
  1372. + qcom,mdss-dsi-dispparam-normal2-command = [
  1373. + 29 01 00 00 00 00 02 B0 04
  1374. + 39 01 00 00 00 00 02 84 00
  1375. + 29 01 00 00 00 00 02 C8 11
  1376. + 29 01 00 00 00 00 02 CA 1C
  1377. + 29 01 00 00 00 00 02 B0 03
  1378. + ];
  1379. + qcom,mdss-dsi-dispparam-normal2-command-state = "dsi_hs_mode";
  1380. + qcom,mdss-dsi-dispparam-srgb-command = [
  1381. + 05 01 00 00 10 00 02 11 00
  1382. + 29 01 00 00 00 00 02 B0 00
  1383. + 29 01 00 00 00 00 02 84 00
  1384. + 29 01 00 00 00 00 02 C8 00
  1385. + 29 01 00 00 00 00 02 CA 1D
  1386. + 29 01 00 00 00 00 02 B0 03
  1387. + ];
  1388. + qcom,mdss-dsi-dispparam-srgb-command-state = "dsi_hs_mode";
  1389. + };
  1390. +};
  1391. diff --git a/arch/arm/boot/dts/qcom/dsi-panel-lgd-sw43401-wqhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-lgd-sw43401-wqhd-cmd.dtsi
  1392. new file mode 100644
  1393. index 0000000..bf81aae
  1394. --- /dev/null
  1395. +++ b/arch/arm/boot/dts/qcom/dsi-panel-lgd-sw43401-wqhd-cmd.dtsi
  1396. @@ -0,0 +1,111 @@
  1397. +/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
  1398. + * Copyright (C) 2017 XiaoMi, Inc.
  1399. + *
  1400. + * This program is free software; you can redistribute it and/or modify
  1401. + * it under the terms of the GNU General Public License version 2 and
  1402. + * only version 2 as published by the Free Software Foundation.
  1403. + *
  1404. + * This program is distributed in the hope that it will be useful,
  1405. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1406. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1407. + * GNU General Public License for more details.
  1408. + */
  1409. +
  1410. +/*---------------------------------------------------------------------------
  1411. + * This file is autogenerated file using gcdb parser. Please do not edit it.
  1412. + * Update input XML file to add a new entry or update variable in this file
  1413. + * VERSION = "1.0"
  1414. + *---------------------------------------------------------------------------*/
  1415. +&soc {
  1416. + dsi_lgd_sw43401_wqhd_cmd: qcom,mdss_dsi_lgd_sw43401_wqhd_cmd {
  1417. + qcom,mdss-dsi-panel-name = "lgd sw43401 cmd wqhd oled panel";
  1418. + qcom,mdss-dsi-panel-sleepwrmod = <0>;
  1419. + qcom,mdss-dsi-panel-id = <4>;
  1420. + qcom,mdss-dsi-panel-model = "LGD SW43401 WQHD DSC CMD";
  1421. + qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
  1422. + qcom,mdss-dsi-panel-framerate = <60>;
  1423. + qcom,mdss-dsi-virtual-channel-id = <0>;
  1424. + qcom,mdss-dsi-stream = <0>;
  1425. + qcom,mdss-dsi-panel-width = <1440>;
  1426. + qcom,mdss-dsi-panel-height = <2560>;
  1427. + qcom,mdss-dsi-h-front-porch = <120>;
  1428. + qcom,mdss-dsi-h-back-porch = <120>;
  1429. + qcom,mdss-dsi-h-pulse-width = <16>;
  1430. + qcom,mdss-dsi-h-sync-skew = <0>;
  1431. + qcom,mdss-dsi-v-back-porch = <48>;
  1432. + qcom,mdss-dsi-v-front-porch = <40>;
  1433. + qcom,mdss-dsi-v-pulse-width = <8>;
  1434. + qcom,mdss-dsi-h-left-border = <0>;
  1435. + qcom,mdss-dsi-h-right-border = <0>;
  1436. + qcom,mdss-dsi-v-top-border = <0>;
  1437. + qcom,mdss-dsi-v-bottom-border = <0>;
  1438. + qcom,mdss-dsi-bpp = <24>;
  1439. + qcom,mdss-dsi-color-order = <0>;
  1440. + qcom,mdss-dsi-underflow-color = <0xff>;
  1441. + qcom,mdss-dsi-border-color = <0>;
  1442. + qcom,mdss-dsi-on-command = [
  1443. + 15 01 00 00 14 00 02 B0 5A
  1444. + 39 01 00 00 00 00 03 51 00 00 /* b3 */
  1445. + 15 01 00 00 00 00 02 53 20
  1446. + 15 01 00 00 00 00 02 55 0C
  1447. + 05 01 00 00 00 00 02 35 00
  1448. + 15 01 00 00 00 00 02 FA 16
  1449. + 05 01 00 00 14 00 02 11 00
  1450. + 15 01 00 00 14 00 02 B0 5A
  1451. + 39 01 00 00 00 00 07 B1 8A FF 4A 14 14 14
  1452. + 39 01 00 00 00 00 0C B2 3D 41 02 80 FF FF 15 00 00 00 00
  1453. + 39 01 00 00 00 00 06 B3 00 08 00 00 00
  1454. + 39 01 00 00 00 00 0e B4 21 12 81 00 ff 00 78 00 ff 80 00 68 02
  1455. + 39 01 00 00 00 00 0e B5 9a 80 00 a0 05 00 0a d0 02 00 05 d0 02
  1456. + 39 01 00 00 00 00 0e B6 a6 89 0a c0 20 14 00 10 00 00 18 f0 10
  1457. + 39 01 00 00 00 00 03 B7 33 A6
  1458. + 39 01 00 00 0a 00 03 D3 24 0C
  1459. + 15 01 00 00 01 00 02 B0 00
  1460. + 05 01 00 00 78 00 02 29 00
  1461. + ];
  1462. + qcom,mdss-dsi-off-command = [
  1463. + 05 01 00 00 02 00 02 28 00
  1464. + 05 01 00 00 80 00 02 10 00];
  1465. + qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
  1466. + qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
  1467. + qcom,mdss-dsi-h-sync-pulse = <0>;
  1468. + qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
  1469. + qcom,mdss-dsi-bllp-eof-power-mode;
  1470. + qcom,mdss-dsi-bllp-power-mode;
  1471. + qcom,mdss-dsi-lp11-init;
  1472. + qcom,mdss-dsi-lane-0-state;
  1473. + qcom,mdss-dsi-lane-1-state;
  1474. + qcom,mdss-dsi-lane-2-state;
  1475. + qcom,mdss-dsi-lane-3-state;
  1476. + qcom,mdss-dsi-panel-timings = [00 15 05 05 08 0d 05 05 04 03 04 00];
  1477. + qcom,mdss-dsi-t-clk-post = <0x05>;
  1478. + qcom,mdss-dsi-t-clk-pre = <0x1b>;
  1479. + qcom,mdss-dsi-bl-min-level = <10>;
  1480. + qcom,mdss-dsi-bl-max-level = <255>;
  1481. + qcom,mdss-dsi-dma-trigger = "trigger_sw";
  1482. + qcom,mdss-dsi-mdp-trigger = "none";
  1483. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
  1484. + qcom,mdss-dsi-reset-sequence = <1 20>, <0 10>, <1 100>;
  1485. + qcom,mdss-pan-physical-width-dimension = <64>;
  1486. + qcom,mdss-pan-physical-height-dimension = <114>;
  1487. + qcom,mdss-dsi-tx-eot-append;
  1488. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply_amoled>;
  1489. + qcom,mdss-dsi-te-pin-select = <1>;
  1490. + qcom,mdss-dsi-te-dcs-command = <1>;
  1491. + qcom,mdss-dsi-te-check-enable;
  1492. + qcom,mdss-dsi-te-using-te-pin;
  1493. + qcom,mdss-dsi-wr-mem-start = <0x2c>;
  1494. + qcom,mdss-dsi-wr-mem-continue = <0x3c>;
  1495. + qcom,compression-mode = "dsc";
  1496. + qcom,config-select = <&dsi_lgd_dsc_cmd_config0>;
  1497. + dsi_lgd_dsc_cmd_config0: config0 {
  1498. + qcom,mdss-dsc-encoders = <1>;
  1499. + qcom,mdss-dsc-slice-height = <1280>;
  1500. + qcom,mdss-dsc-slice-width = <720>;
  1501. + qcom,mdss-dsc-slice-per-pkt = <2>;
  1502. + qcom,mdss-dsc-bit-per-component = <8>;
  1503. + qcom,mdss-dsc-bit-per-pixel = <8>;
  1504. + qcom,mdss-dsc-block-prediction-enable;
  1505. + };
  1506. + };
  1507. +};
  1508. diff --git a/arch/arm/boot/dts/qcom/msm-pm8998.dtsi b/arch/arm/boot/dts/qcom/msm-pm8998.dtsi
  1509. index e13cdf4..a458241 100644
  1510. --- a/arch/arm/boot/dts/qcom/msm-pm8998.dtsi
  1511. +++ b/arch/arm/boot/dts/qcom/msm-pm8998.dtsi
  1512. @@ -1,4 +1,5 @@
  1513. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  1514. + * Copyright (C) 2017 XiaoMi, Inc.
  1515. *
  1516. * This program is free software; you can redistribute it and/or modify
  1517. * it under the terms of the GNU General Public License version 2 and
  1518. @@ -36,6 +37,7 @@
  1519. interrupt-names = "kpdpwr", "resin",
  1520. "resin-bark", "kpdpwr-resin-bark";
  1521. qcom,pon-dbc-delay = <15625>;
  1522. + qcom,kpdpwr-sw-debounce;
  1523. qcom,system-reset;
  1524. qcom,store-hard-reset-reason;
  1525.  
  1526. @@ -55,9 +57,9 @@
  1527. qcom,pon-type = <3>;
  1528. qcom,support-reset = <1>;
  1529. qcom,pull-up = <1>;
  1530. - qcom,s1-timer = <6720>;
  1531. + qcom,s1-timer = <1352>;
  1532. qcom,s2-timer = <2000>;
  1533. - qcom,s2-type = <PON_POWER_OFF_DVDD_HARD_RESET>;
  1534. + qcom,s2-type = <PON_POWER_OFF_WARM_RESET>;
  1535. qcom,use-bark;
  1536. };
  1537. };
  1538. diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
  1539. index ad32ab0..35a7bdf 100644
  1540. --- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
  1541. +++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
  1542. @@ -1,4 +1,5 @@
  1543. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  1544. + * Copyright (C) 2017 XiaoMi, Inc.
  1545. *
  1546. * This program is free software; you can redistribute it and/or modify
  1547. * it under the terms of the GNU General Public License version 2 and
  1548. @@ -78,7 +79,7 @@
  1549. gpio@c400 {
  1550. reg = <0xc400 0x100>;
  1551. qcom,pin-num = <5>;
  1552. - status = "disabled";
  1553. + status = "okay";
  1554. };
  1555.  
  1556. gpio@c500 {
  1557. @@ -384,11 +385,9 @@
  1558. qcom,fg-memif@4400 {
  1559. status = "okay";
  1560. reg = <0x4400 0x100>;
  1561. - interrupts = <0x2 0x44 0x0 IRQ_TYPE_EDGE_BOTH>,
  1562. - <0x2 0x44 0x1 IRQ_TYPE_EDGE_BOTH>,
  1563. + interrupts = <0x2 0x44 0x1 IRQ_TYPE_EDGE_BOTH>,
  1564. <0x2 0x44 0x2 IRQ_TYPE_EDGE_BOTH>;
  1565. - interrupt-names = "ima-rdy",
  1566. - "mem-xcp",
  1567. + interrupt-names = "mem-xcp",
  1568. "dma-grant";
  1569. };
  1570. };
  1571. @@ -425,7 +424,7 @@
  1572. qcom,supported-sizes = <6>, <9>;
  1573. qcom,ramp-index = <1>;
  1574. #pwm-cells = <2>;
  1575. - status = "disabled";
  1576. + status = "okay";
  1577. };
  1578.  
  1579. pmi8998_pwm_3: pwm@b300 {
  1580. @@ -496,8 +495,6 @@
  1581. qcom,max-current = <12>;
  1582. qcom,default-state = "off";
  1583. linux,name = "red";
  1584. - linux,default-trigger =
  1585. - "battery-charging";
  1586. };
  1587.  
  1588. green_led: qcom,rgb_1 {
  1589. @@ -509,7 +506,6 @@
  1590. qcom,max-current = <12>;
  1591. qcom,default-state = "off";
  1592. linux,name = "green";
  1593. - linux,default-trigger = "battery-full";
  1594. };
  1595.  
  1596. blue_led: qcom,rgb_2 {
  1597. @@ -521,7 +517,6 @@
  1598. qcom,max-current = <12>;
  1599. qcom,default-state = "off";
  1600. linux,name = "blue";
  1601. - linux,default-trigger = "boot-indication";
  1602. };
  1603. };
  1604.  
  1605. @@ -612,7 +607,7 @@
  1606. linux,default-trigger = "bkl-trigger";
  1607. qcom,fdbk-output = "auto";
  1608. qcom,vref-uv = <127500>;
  1609. - qcom,switch-freq-khz = <800>;
  1610. + qcom,switch-freq-khz = <600>;
  1611. qcom,ovp-mv = <29600>;
  1612. qcom,ilim-ma = <970>;
  1613. qcom,boost-duty-ns = <26>;
  1614. @@ -623,7 +618,6 @@
  1615. qcom,fs-curr-ua = <25000>;
  1616. qcom,cons-sync-write-delay-us = <1000>;
  1617. qcom,led-strings-list = [00 01 02 03];
  1618. - qcom,en-ext-pfet-sc-pro;
  1619. qcom,pmic-revid = <&pmi8998_revid>;
  1620. qcom,loop-auto-gm-en;
  1621. status = "okay";
  1622. @@ -652,7 +646,6 @@
  1623. qcom,lra-high-z = "opt1";
  1624. qcom,lra-auto-res-mode = "qwd";
  1625. qcom,lra-res-cal-period = <4>;
  1626. - qcom,correct-lra-drive-freq;
  1627. };
  1628.  
  1629. flash_led: qcom,leds@d300 {
  1630. @@ -717,7 +710,7 @@
  1631. pmi8998_torch0: qcom,torch_0 {
  1632. label = "torch";
  1633. qcom,led-name = "led:torch_0";
  1634. - qcom,max-current = <500>;
  1635. + qcom,max-current = <100>;
  1636. qcom,default-led-trigger = "torch0_trigger";
  1637. qcom,id = <0>;
  1638. qcom,current-ma = <300>;
  1639. @@ -729,7 +722,7 @@
  1640. pmi8998_torch1: qcom,torch_1 {
  1641. label = "torch";
  1642. qcom,led-name = "led:torch_1";
  1643. - qcom,max-current = <500>;
  1644. + qcom,max-current = <100>;
  1645. qcom,default-led-trigger = "torch1_trigger";
  1646. qcom,id = <1>;
  1647. qcom,current-ma = <300>;
  1648. diff --git a/arch/arm/boot/dts/qcom/msm8998-audio.dtsi b/arch/arm/boot/dts/qcom/msm8998-audio.dtsi
  1649. index 86a31a4..c1121cb 100644
  1650. --- a/arch/arm/boot/dts/qcom/msm8998-audio.dtsi
  1651. +++ b/arch/arm/boot/dts/qcom/msm8998-audio.dtsi
  1652. @@ -82,7 +82,6 @@
  1653.  
  1654. qcom,msm-mbhc-hphl-swh = <0>;
  1655. qcom,msm-mbhc-gnd-swh = <0>;
  1656. - qcom,us-euro-gpios = <&wcd_us_euro_gpio>;
  1657. qcom,hph-en0-gpio = <&hph_en0_gpio>;
  1658. qcom,hph-en1-gpio = <&hph_en1_gpio>;
  1659. qcom,tasha-mclk-clk-freq = <9600000>;
  1660. @@ -216,9 +215,6 @@
  1661. qcom,hph-en1-gpio = <&tavil_hph_en1>;
  1662. qcom,tavil-mclk-clk-freq = <9600000>;
  1663.  
  1664. - qcom,usbc-analog-en1_gpio = <&wcd_usbc_analog_en1_gpio>;
  1665. - qcom,usbc-analog-en2_n_gpio = <&wcd_usbc_analog_en2n_gpio>;
  1666. -
  1667. asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
  1668. <&loopback>, <&compress>, <&hostless>,
  1669. <&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>,
  1670. @@ -305,20 +301,6 @@
  1671. pinctrl-1 = <&wcd_gnd_mic_swap_idle>;
  1672. };
  1673.  
  1674. - wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl@59 {
  1675. - compatible = "qcom,msm-cdc-pinctrl";
  1676. - pinctrl-names = "aud_active", "aud_sleep";
  1677. - pinctrl-0 = <&wcd_usbc_analog_en1_active>;
  1678. - pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
  1679. - };
  1680. -
  1681. - wcd_usbc_analog_en2n_gpio: msm_cdc_pinctrl@60 {
  1682. - compatible = "qcom,msm-cdc-pinctrl";
  1683. - pinctrl-names = "aud_active", "aud_sleep";
  1684. - pinctrl-0 = <&wcd_usbc_analog_en2n_active>;
  1685. - pinctrl-1 = <&wcd_usbc_analog_en2n_idle>;
  1686. - };
  1687. -
  1688. wcd9xxx_intc: wcd9xxx-irq {
  1689. status = "ok";
  1690. compatible = "qcom,wcd9xxx-irq";
  1691. diff --git a/arch/arm/boot/dts/qcom/msm8998-blsp.dtsi b/arch/arm/boot/dts/qcom/msm8998-blsp.dtsi
  1692. index b9e323d..c40e7a7 100644
  1693. --- a/arch/arm/boot/dts/qcom/msm8998-blsp.dtsi
  1694. +++ b/arch/arm/boot/dts/qcom/msm8998-blsp.dtsi
  1695. @@ -621,7 +621,6 @@
  1696. interrupt-names = "spi_irq", "spi_bam_irq";
  1697. interrupts = <0 106 0>, <0 239 0>;
  1698. spi-max-frequency = <50000000>;
  1699. - qcom,use-bam;
  1700. qcom,ver-reg-exists;
  1701. qcom,bam-consumer-pipe-index = <16>;
  1702. qcom,bam-producer-pipe-index = <17>;
  1703. diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi
  1704. index d5c8900..494bfd8 100644
  1705. --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi
  1706. +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-cdp.dtsi
  1707. @@ -1,5 +1,6 @@
  1708. /*
  1709. * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  1710. + * Copyright (C) 2017 XiaoMi, Inc.
  1711. *
  1712. * This program is free software; you can redistribute it and/or modify
  1713. * it under the terms of the GNU General Public License version 2 and
  1714. @@ -280,6 +281,7 @@
  1715. qcom,eeprom-src = <&eeprom1>;
  1716. qcom,actuator-src = <&actuator1>;
  1717. cam_vdig-supply = <&pm8998_lvs1>;
  1718. + qcom,led-flash-src = <&led_flash0>;
  1719. cam_vio-supply = <&pm8998_lvs1>;
  1720. cam_vana-supply = <&pmi8998_bob>;
  1721. qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
  1722. diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
  1723. index 321079a..9bfcc06 100644
  1724. --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
  1725. +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
  1726. @@ -1,5 +1,6 @@
  1727. /*
  1728. - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  1729. + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  1730. + * Copyright (C) 2017 XiaoMi, Inc.
  1731. *
  1732. * This program is free software; you can redistribute it and/or modify
  1733. * it under the terms of the GNU General Public License version 2 and
  1734. @@ -27,17 +28,7 @@
  1735. qcom,flash-source = <&pmi8998_flash2>;
  1736. qcom,torch-source = <&pmi8998_torch2>;
  1737. qcom,switch-source = <&pmi8998_switch1>;
  1738. - status = "ok";
  1739. - };
  1740. -
  1741. - actuator_regulator: gpio-regulator@0 {
  1742. - compatible = "regulator-fixed";
  1743. - regulator-name = "rear_vana_regulator";
  1744. - regulator-min-microvolt = <2800000>;
  1745. - regulator-max-microvolt = <2800000>;
  1746. - enable-active-high;
  1747. - gpio = <&tlmm 27 0>;
  1748. - vin-supply = <&pmi8998_bob>;
  1749. + status = "disable";
  1750. };
  1751. };
  1752.  
  1753. @@ -47,11 +38,14 @@
  1754. reg = <0x0>;
  1755. compatible = "qcom,actuator";
  1756. qcom,cci-master = <0>;
  1757. - cam_vaf-supply = <&actuator_regulator>;
  1758. - qcom,cam-vreg-name = "cam_vaf";
  1759. - qcom,cam-vreg-min-voltage = <2800000>;
  1760. - qcom,cam-vreg-max-voltage = <2800000>;
  1761. - qcom,cam-vreg-op-mode = <0>;
  1762. + gpios = <&tlmm 29 0>;
  1763. + qcom,gpio-vaf = <0>;
  1764. + qcom,gpio-req-tbl-num = <0>;
  1765. + qcom,gpio-req-tbl-flags = <0>;
  1766. + qcom,gpio-req-tbl-label = "CAM_VAF";
  1767. + pinctrl-names = "cam_default", "cam_suspend";
  1768. + pinctrl-0 = <&cam_actuator_vaf_active>;
  1769. + pinctrl-1 = <&cam_actuator_vaf_suspend>;
  1770. };
  1771.  
  1772. actuator1: qcom,actuator@1 {
  1773. @@ -59,31 +53,14 @@
  1774. reg = <0x1>;
  1775. compatible = "qcom,actuator";
  1776. qcom,cci-master = <1>;
  1777. - cam_vaf-supply = <&actuator_regulator>;
  1778. - qcom,cam-vreg-name = "cam_vaf";
  1779. - qcom,cam-vreg-min-voltage = <2800000>;
  1780. - qcom,cam-vreg-max-voltage = <2800000>;
  1781. - qcom,cam-vreg-op-mode = <0>;
  1782. - };
  1783. -
  1784. - tof0: qcom,tof@0 {
  1785. - cell-index = <0>;
  1786. - reg = <0x29>;
  1787. - compatible = "st,stmvl53l0";
  1788. - qcom,cci-master = <0>;
  1789. - cam_cci-supply = <&pm8998_lvs1>;
  1790. - cam_laser-supply = <&actuator_regulator>;
  1791. - qcom,cam-vreg-name = "cam_cci", "cam_laser";
  1792. - qcom,cam-vreg-min-voltage = <0 0>;
  1793. - qcom,cam-vreg-max-voltage = <0 2800000>;
  1794. - pinctrl-names = "cam_default", "cam_suspend";
  1795. - pinctrl-0 = <&cam_tof_active>;
  1796. - pinctrl-1 = <&cam_tof_suspend>;
  1797. - stm,irq-gpio = <&tlmm 26 0x2008>;
  1798. - gpios = <&tlmm 126 0>;
  1799. + gpios = <&tlmm 29 0>;
  1800. + qcom,gpio-vaf = <0>;
  1801. qcom,gpio-req-tbl-num = <0>;
  1802. qcom,gpio-req-tbl-flags = <0>;
  1803. - qcom,gpio-req-tbl-label = "CAM_CE";
  1804. + qcom,gpio-req-tbl-label = "CAM_VAF";
  1805. + pinctrl-names = "cam_default", "cam_suspend";
  1806. + pinctrl-0 = <&cam_actuator_vaf_active>;
  1807. + pinctrl-1 = <&cam_actuator_vaf_suspend>;
  1808. };
  1809.  
  1810. ois0: qcom,ois@0 {
  1811. @@ -99,6 +76,7 @@
  1812. pinctrl-names = "cam_default", "cam_suspend";
  1813. pinctrl-0 = <&cam_actuator_vaf_active>;
  1814. pinctrl-1 = <&cam_actuator_vaf_suspend>;
  1815. + status = "disabled";
  1816. };
  1817.  
  1818. eeprom0: qcom,eeprom@0 {
  1819. @@ -228,18 +206,14 @@
  1820. reg = <0x0>;
  1821. qcom,csiphy-sd-index = <0>;
  1822. qcom,csid-sd-index = <0>;
  1823. - qcom,mount-angle = <270>;
  1824. + qcom,mount-angle = <90>;
  1825. qcom,led-flash-src = <&led_flash0>;
  1826. qcom,actuator-src = <&actuator0>;
  1827. - qcom,ois-src = <&ois0>;
  1828. - qcom,eeprom-src = <&eeprom0>;
  1829. cam_vio-supply = <&pm8998_lvs1>;
  1830. - cam_vana-supply = <&pmi8998_bob>;
  1831. - cam_vdig-supply = <&pm8998_s3>;
  1832. - qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
  1833. - qcom,cam-vreg-min-voltage = <0 3312000 1352000>;
  1834. - qcom,cam-vreg-max-voltage = <0 3600000 1352000>;
  1835. - qcom,cam-vreg-op-mode = <0 80000 105000>;
  1836. + qcom,cam-vreg-name = "cam_vio";
  1837. + qcom,cam-vreg-min-voltage = <0>;
  1838. + qcom,cam-vreg-max-voltage = <0>;
  1839. + qcom,cam-vreg-op-mode = <0>;
  1840. qcom,gpio-no-mux = <0>;
  1841. pinctrl-names = "cam_default", "cam_suspend";
  1842. pinctrl-0 = <&cam_sensor_mclk0_active
  1843. @@ -249,16 +223,16 @@
  1844. gpios = <&tlmm 13 0>,
  1845. <&tlmm 30 0>,
  1846. <&pm8998_gpios 20 0>,
  1847. - <&tlmm 29 0>;
  1848. + <&tlmm 80 0>;
  1849. qcom,gpio-reset = <1>;
  1850. - qcom,gpio-vdig = <2>;
  1851. - qcom,gpio-vana = <3>;
  1852. + qcom,gpio-vana = <2>;
  1853. + qcom,gpio-vdig = <3>;
  1854. qcom,gpio-req-tbl-num = <0 1 2 3>;
  1855. qcom,gpio-req-tbl-flags = <1 0 0 0>;
  1856. qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
  1857. "CAM_RESET0",
  1858. - "CAM_VDIG",
  1859. - "CAM_VANA";
  1860. + "CAM_VANA",
  1861. + "CAM_VDIG";
  1862. qcom,sensor-position = <0>;
  1863. qcom,sensor-mode = <0>;
  1864. qcom,cci-master = <0>;
  1865. @@ -273,19 +247,18 @@
  1866. cell-index = <1>;
  1867. compatible = "qcom,camera";
  1868. reg = <0x1>;
  1869. - qcom,csiphy-sd-index = <1>;
  1870. - qcom,csid-sd-index = <1>;
  1871. + qcom,csiphy-sd-index = <2>;
  1872. + qcom,csid-sd-index = <2>;
  1873. qcom,mount-angle = <90>;
  1874. qcom,eeprom-src = <&eeprom1>;
  1875. - qcom,led-flash-src = <&led_flash0>;
  1876. qcom,actuator-src = <&actuator1>;
  1877. + qcom,led-flash-src = <&led_flash0>;
  1878. cam_vdig-supply = <&pm8998_lvs1>;
  1879. cam_vio-supply = <&pm8998_lvs1>;
  1880. - cam_vana-supply = <&pmi8998_bob>;
  1881. - qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
  1882. - qcom,cam-vreg-min-voltage = <0 0 3312000>;
  1883. - qcom,cam-vreg-max-voltage = <0 0 3600000>;
  1884. - qcom,cam-vreg-op-mode = <0 0 80000>;
  1885. + qcom,cam-vreg-name = "cam_vio";
  1886. + qcom,cam-vreg-min-voltage = <0>;
  1887. + qcom,cam-vreg-max-voltage = <0>;
  1888. + qcom,cam-vreg-op-mode = <0>;
  1889. qcom,gpio-no-mux = <0>;
  1890. pinctrl-names = "cam_default", "cam_suspend";
  1891. pinctrl-0 = <&cam_sensor_mclk2_active
  1892. @@ -294,14 +267,17 @@
  1893. &cam_sensor_rear2_suspend>;
  1894. gpios = <&tlmm 15 0>,
  1895. <&tlmm 9 0>,
  1896. - <&tlmm 8 0>;
  1897. + <&pm8998_gpios 20 0>,
  1898. + <&tlmm 80 0>;
  1899. qcom,gpio-reset = <1>;
  1900. qcom,gpio-vana = <2>;
  1901. - qcom,gpio-req-tbl-num = <0 1 2>;
  1902. - qcom,gpio-req-tbl-flags = <1 0 0>;
  1903. - qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  1904. - "CAM_RESET1",
  1905. - "CAM_VANA1";
  1906. + qcom,gpio-vdig = <3>;
  1907. + qcom,gpio-req-tbl-num = <0 1 2 3>;
  1908. + qcom,gpio-req-tbl-flags = <1 0 0 0>;
  1909. + qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
  1910. + "CAM_RESET2",
  1911. + "CAM_VDIG",
  1912. + "CAM_VANA";
  1913. qcom,sensor-position = <0>;
  1914. qcom,sensor-mode = <0>;
  1915. qcom,cci-master = <1>;
  1916. @@ -316,40 +292,36 @@
  1917. cell-index = <2>;
  1918. compatible = "qcom,camera";
  1919. reg = <0x02>;
  1920. - qcom,csiphy-sd-index = <2>;
  1921. - qcom,csid-sd-index = <2>;
  1922. - qcom,mount-angle = <90>;
  1923. - qcom,eeprom-src = <&eeprom2>;
  1924. - qcom,led-flash-src = <&led_flash1>;
  1925. - qcom,actuator-src = <&actuator1>;
  1926. + qcom,csiphy-sd-index = <1>;
  1927. + qcom,csid-sd-index = <1>;
  1928. + qcom,mount-angle = <270>;
  1929. cam_vio-supply = <&pm8998_lvs1>;
  1930. cam_vana-supply = <&pm8998_l22>;
  1931. - cam_vdig-supply = <&pm8998_s3>;
  1932. - qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
  1933. + qcom,cam-vreg-name = "cam_vio", "cam_vana";
  1934. qcom,cam-vreg-min-voltage =
  1935. - <0 2864000 1352000>;
  1936. + <0 2864000>;
  1937. qcom,cam-vreg-max-voltage =
  1938. - <0 2864000 1352000>;
  1939. - qcom,cam-vreg-op-mode = <0 80000 105000>;
  1940. + <0 2864000>;
  1941. + qcom,cam-vreg-op-mode = <0 80000>;
  1942. qcom,gpio-no-mux = <0>;
  1943. pinctrl-names = "cam_default", "cam_suspend";
  1944. pinctrl-0 = <&cam_sensor_mclk1_active
  1945. - &cam_sensor_front_active &led_enable>;
  1946. + &cam_sensor_front_active>;
  1947. pinctrl-1 = <&cam_sensor_mclk1_suspend
  1948. - &cam_sensor_front_suspend &led_disable>;
  1949. + &cam_sensor_front_suspend>;
  1950. gpios = <&tlmm 14 0>,
  1951. + <&tlmm 27 0>,
  1952. <&tlmm 28 0>,
  1953. - <&pm8998_gpios 9 0>,
  1954. - <&tlmm 21 0>;
  1955. - qcom,gpio-reset = <1>;
  1956. - qcom,gpio-vdig = <2>;
  1957. - qcom,gpio-flash-en = <3>;
  1958. + <&pm8998_gpios 9 0>;
  1959. + qcom,gpio-standby = <1>;
  1960. + qcom,gpio-reset = <2>;
  1961. + qcom,gpio-vdig = <3>;
  1962. qcom,gpio-req-tbl-num = <0 1 2 3>;
  1963. qcom,gpio-req-tbl-flags = <1 0 0 0>;
  1964. - qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
  1965. - "CAM_RESET2",
  1966. - "CAM_VDIG",
  1967. - "FLASH_EN";
  1968. + qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  1969. + "CAM_STANDBY1",
  1970. + "CAM_RESET1",
  1971. + "CAM_VDIG";
  1972. qcom,sensor-position = <1>;
  1973. qcom,sensor-mode = <0>;
  1974. qcom,cci-master = <1>;
  1975. @@ -359,46 +331,6 @@
  1976. clock-names = "cam_src_clk", "cam_clk";
  1977. qcom,clock-rates = <24000000 0>;
  1978. };
  1979. -
  1980. - qcom,camera@3 {
  1981. - cell-index = <3>;
  1982. - compatible = "qcom,camera";
  1983. - reg = <0x03>;
  1984. - qcom,csiphy-sd-index = <1>;
  1985. - qcom,csid-sd-index = <1>;
  1986. - qcom,mount-angle = <270>;
  1987. - qcom,led-flash-src = <&led_flash1>;
  1988. - cam_vio-supply = <&pm8998_lvs1>;
  1989. - cam_vana-supply = <&pm8998_l22>;
  1990. - cam_vdig-supply = <&pm8998_s3>;
  1991. - qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
  1992. - qcom,cam-vreg-min-voltage =
  1993. - <0 2864000 1352000>;
  1994. - qcom,cam-vreg-max-voltage =
  1995. - <0 2864000 1352000>;
  1996. - qcom,cam-vreg-op-mode = <0 80000 105000>;
  1997. - qcom,gpio-no-mux = <0>;
  1998. - pinctrl-names = "cam_default", "cam_suspend";
  1999. - pinctrl-0 = <&cam_sensor_mclk3_active
  2000. - &cam_sensor_front_iris_active>;
  2001. - pinctrl-1 = <&cam_sensor_mclk3_suspend
  2002. - &cam_sensor_front_iris_suspend>;
  2003. - gpios = <&tlmm 16 0>,
  2004. - <&tlmm 23 0>;
  2005. - qcom,gpio-reset = <1>;
  2006. - qcom,gpio-req-tbl-num = <0 1>;
  2007. - qcom,gpio-req-tbl-flags = <1 0>;
  2008. - qcom,gpio-req-tbl-label = "CAMIF_MCLK3",
  2009. - "CAM_RESET3";
  2010. - qcom,sensor-position = <1>;
  2011. - qcom,sensor-mode = <0>;
  2012. - qcom,cci-master = <1>;
  2013. - status = "ok";
  2014. - clocks = <&clock_mmss clk_mclk3_clk_src>,
  2015. - <&clock_mmss clk_mmss_camss_mclk3_clk>;
  2016. - clock-names = "cam_src_clk", "cam_clk";
  2017. - qcom,clock-rates = <24000000 0>;
  2018. - };
  2019. };
  2020. &pm8998_gpios {
  2021. gpio@c800 { /* GPIO 9 - CAMERA SENSOR 2 VDIG */
  2022. diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi
  2023. index 8c51aa6..093a7da 100644
  2024. --- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi
  2025. +++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-qrd.dtsi
  2026. @@ -1,6 +1,7 @@
  2027.  
  2028. /*
  2029. * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  2030. + * Copyright (C) 2017 XiaoMi, Inc.
  2031. *
  2032. * This program is free software; you can redistribute it and/or modify
  2033. * it under the terms of the GNU General Public License version 2 and
  2034. @@ -28,7 +29,7 @@
  2035. qcom,flash-source = <&pmi8998_flash2>;
  2036. qcom,torch-source = <&pmi8998_torch2>;
  2037. qcom,switch-source = <&pmi8998_switch1>;
  2038. - status = "ok";
  2039. + status = "disable";
  2040. };
  2041. };
  2042.  
  2043. @@ -38,7 +39,7 @@
  2044. reg = <0x0>;
  2045. compatible = "qcom,actuator";
  2046. qcom,cci-master = <0>;
  2047. - gpios = <&tlmm 27 0>;
  2048. + gpios = <&tlmm 29 0>;
  2049. qcom,gpio-vaf = <0>;
  2050. qcom,gpio-req-tbl-num = <0>;
  2051. qcom,gpio-req-tbl-flags = <0>;
  2052. @@ -53,7 +54,7 @@
  2053. reg = <0x1>;
  2054. compatible = "qcom,actuator";
  2055. qcom,cci-master = <1>;
  2056. - gpios = <&tlmm 27 0>;
  2057. + gpios = <&tlmm 29 0>;
  2058. qcom,gpio-vaf = <0>;
  2059. qcom,gpio-req-tbl-num = <0>;
  2060. qcom,gpio-req-tbl-flags = <0>;
  2061. @@ -209,28 +210,22 @@
  2062. qcom,mount-angle = <270>;
  2063. qcom,led-flash-src = <&led_flash0>;
  2064. qcom,actuator-src = <&actuator0>;
  2065. - qcom,ois-src = <&ois0>;
  2066. - qcom,eeprom-src = <&eeprom0>;
  2067. cam_vio-supply = <&pm8998_lvs1>;
  2068. - cam_vana-supply = <&pmi8998_bob>;
  2069. - cam_vdig-supply = <&pm8998_s3>;
  2070. - qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
  2071. - qcom,cam-vreg-min-voltage = <0 3312000 1352000>;
  2072. - qcom,cam-vreg-max-voltage = <0 3312000 1352000>;
  2073. - qcom,cam-vreg-op-mode = <0 80000 105000>;
  2074. + qcom,cam-vreg-name = "cam_vio";
  2075. + qcom,cam-vreg-min-voltage = <0>;
  2076. + qcom,cam-vreg-max-voltage = <0>;
  2077. + qcom,cam-vreg-op-mode = <0>;
  2078. qcom,gpio-no-mux = <0>;
  2079. pinctrl-names = "cam_default", "cam_suspend";
  2080. - pinctrl-0 = <&cam_sensor_mclk0_active
  2081. - &cam_sensor_rear_active>;
  2082. - pinctrl-1 = <&cam_sensor_mclk0_suspend
  2083. - &cam_sensor_rear_suspend>;
  2084. + pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_rear_active>;
  2085. + pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_rear_suspend>;
  2086. gpios = <&tlmm 13 0>,
  2087. <&tlmm 30 0>,
  2088. <&pm8998_gpios 20 0>,
  2089. - <&tlmm 29 0>;
  2090. + <&tlmm 80 0>;
  2091. qcom,gpio-reset = <1>;
  2092. - qcom,gpio-vdig = <2>;
  2093. - qcom,gpio-vana = <3>;
  2094. + qcom,gpio-vana = <2>;
  2095. + qcom,gpio-vdig = <3>;
  2096. qcom,gpio-req-tbl-num = <0 1 2 3>;
  2097. qcom,gpio-req-tbl-flags = <1 0 0 0>;
  2098. qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
  2099. @@ -251,33 +246,33 @@
  2100. cell-index = <1>;
  2101. compatible = "qcom,camera";
  2102. reg = <0x1>;
  2103. - qcom,csiphy-sd-index = <1>;
  2104. - qcom,csid-sd-index = <1>;
  2105. + qcom,csiphy-sd-index = <2>;
  2106. + qcom,csid-sd-index = <2>;
  2107. qcom,mount-angle = <90>;
  2108. - qcom,eeprom-src = <&eeprom1>;
  2109. - cam_vdig-supply = <&pm8998_lvs1>;
  2110. cam_vio-supply = <&pm8998_lvs1>;
  2111. cam_vana-supply = <&pmi8998_bob>;
  2112. - qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
  2113. - qcom,cam-vreg-min-voltage = <0 0 3312000>;
  2114. - qcom,cam-vreg-max-voltage = <0 0 3312000>;
  2115. - qcom,cam-vreg-op-mode = <0 0 80000>;
  2116. + qcom,actuator-src = <&actuator1>;
  2117. + qcom,cam-vreg-name = "cam_vio";
  2118. + qcom,cam-vreg-min-voltage = <0>;
  2119. + qcom,cam-vreg-max-voltage = <0>;
  2120. + qcom,cam-vreg-op-mode = <0>;
  2121. qcom,gpio-no-mux = <0>;
  2122. pinctrl-names = "cam_default", "cam_suspend";
  2123. - pinctrl-0 = <&cam_sensor_mclk2_active
  2124. - &cam_sensor_rear2_active>;
  2125. - pinctrl-1 = <&cam_sensor_mclk2_suspend
  2126. - &cam_sensor_rear2_suspend>;
  2127. + pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_rear_active>;
  2128. + pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_rear_suspend>;
  2129. gpios = <&tlmm 15 0>,
  2130. <&tlmm 9 0>,
  2131. - <&tlmm 8 0>;
  2132. + <&pm8998_gpios 20 0>,
  2133. + <&tlmm 80 0>;
  2134. qcom,gpio-reset = <1>;
  2135. qcom,gpio-vana = <2>;
  2136. - qcom,gpio-req-tbl-num = <0 1 2>;
  2137. - qcom,gpio-req-tbl-flags = <1 0 0>;
  2138. - qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  2139. - "CAM_RESET1",
  2140. - "CAM_VANA1";
  2141. + qcom,gpio-vdig = <3>;
  2142. + qcom,gpio-req-tbl-num = <0 1 2 3>;
  2143. + qcom,gpio-req-tbl-flags = <1 0 0 0>;
  2144. + qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
  2145. + "CAM_RESET2",
  2146. + "CAM_VDIG",
  2147. + "CAM_VANA";
  2148. qcom,sensor-position = <0>;
  2149. qcom,sensor-mode = <0>;
  2150. qcom,cci-master = <1>;
  2151. @@ -292,21 +287,17 @@
  2152. cell-index = <2>;
  2153. compatible = "qcom,camera";
  2154. reg = <0x02>;
  2155. - qcom,csiphy-sd-index = <2>;
  2156. - qcom,csid-sd-index = <2>;
  2157. - qcom,mount-angle = <90>;
  2158. - qcom,eeprom-src = <&eeprom2>;
  2159. - qcom,led-flash-src = <&led_flash1>;
  2160. - qcom,actuator-src = <&actuator1>;
  2161. + qcom,csiphy-sd-index = <1>;
  2162. + qcom,csid-sd-index = <1>;
  2163. + qcom,mount-angle = <270>;
  2164. cam_vio-supply = <&pm8998_lvs1>;
  2165. cam_vana-supply = <&pm8998_l22>;
  2166. - cam_vdig-supply = <&pm8998_s3>;
  2167. - qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
  2168. + qcom,cam-vreg-name = "cam_vio", "cam_vana";
  2169. qcom,cam-vreg-min-voltage =
  2170. - <0 2864000 1352000>;
  2171. + <0 2864000>;
  2172. qcom,cam-vreg-max-voltage =
  2173. - <0 2864000 1352000>;
  2174. - qcom,cam-vreg-op-mode = <0 80000 105000>;
  2175. + <0 2864000>;
  2176. + qcom,cam-vreg-op-mode = <0 80000>;
  2177. qcom,gpio-no-mux = <0>;
  2178. pinctrl-names = "cam_default", "cam_suspend";
  2179. pinctrl-0 = <&cam_sensor_mclk1_active
  2180. @@ -314,14 +305,17 @@
  2181. pinctrl-1 = <&cam_sensor_mclk1_suspend
  2182. &cam_sensor_front_suspend>;
  2183. gpios = <&tlmm 14 0>,
  2184. + <&tlmm 27 0>,
  2185. <&tlmm 28 0>,
  2186. <&pm8998_gpios 9 0>;
  2187. - qcom,gpio-reset = <1>;
  2188. - qcom,gpio-vdig = <2>;
  2189. - qcom,gpio-req-tbl-num = <0 1 2>;
  2190. - qcom,gpio-req-tbl-flags = <1 0 0>;
  2191. - qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
  2192. - "CAM_RESET2",
  2193. + qcom,gpio-standby = <1>;
  2194. + qcom,gpio-reset = <2>;
  2195. + qcom,gpio-vdig = <3>;
  2196. + qcom,gpio-req-tbl-num = <0 1 2 3>;
  2197. + qcom,gpio-req-tbl-flags = <1 0 0 0>;
  2198. + qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  2199. + "CAM_STANDBY1",
  2200. + "CAM_RESET1",
  2201. "CAM_VDIG";
  2202. qcom,sensor-position = <1>;
  2203. qcom,sensor-mode = <0>;
  2204. diff --git a/arch/arm/boot/dts/qcom/msm8998-camera.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera.dtsi
  2205. index f874444..1525010 100644
  2206. --- a/arch/arm/boot/dts/qcom/msm8998-camera.dtsi
  2207. +++ b/arch/arm/boot/dts/qcom/msm8998-camera.dtsi
  2208. @@ -1,5 +1,6 @@
  2209. /*
  2210. * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  2211. + * Copyright (C) 2017 XiaoMi, Inc.
  2212. *
  2213. * This program is free software; you can redistribute it and/or modify
  2214. * it under the terms of the GNU General Public License version 2 and
  2215. @@ -535,9 +536,9 @@
  2216. "NO_SET_RATE", "NO_SET_RATE",
  2217. "NO_SET_RATE", "NO_SET_RATE",
  2218. "INIT_RATE",
  2219. - "NO_SET_RATE", "NO_SET_RATE",
  2220. + "INIT_RATE", "NO_SET_RATE",
  2221. "INIT_RATE",
  2222. - "NO_SET_RATE", "NO_SET_RATE";
  2223. + "INIT_RATE", "NO_SET_RATE";
  2224. status = "ok";
  2225. };
  2226.  
  2227. @@ -856,7 +857,7 @@
  2228. qcom,hw-thd-dat = <22>;
  2229. qcom,hw-thd-sta = <162>;
  2230. qcom,hw-tbuf = <227>;
  2231. - qcom,hw-scl-stretch-en = <0>;
  2232. + qcom,hw-scl-stretch-en = <1>;
  2233. qcom,hw-trdhld = <6>;
  2234. qcom,hw-tsp = <3>;
  2235. qcom,cci-clk-src = <37500000>;
  2236. @@ -871,7 +872,7 @@
  2237. qcom,hw-thd-dat = <22>;
  2238. qcom,hw-thd-sta = <35>;
  2239. qcom,hw-tbuf = <62>;
  2240. - qcom,hw-scl-stretch-en = <0>;
  2241. + qcom,hw-scl-stretch-en = <1>;
  2242. qcom,hw-trdhld = <6>;
  2243. qcom,hw-tsp = <3>;
  2244. qcom,cci-clk-src = <37500000>;
  2245. diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi
  2246. index d00ae0f..b57800d 100644
  2247. --- a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi
  2248. +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi
  2249. @@ -1,5 +1,6 @@
  2250. /*
  2251. * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  2252. + * Copyright (C) 2017 XiaoMi, Inc.
  2253. *
  2254. * This program is free software; you can redistribute it and/or modify
  2255. * it under the terms of the GNU General Public License version 2 and
  2256. @@ -12,12 +13,6 @@
  2257. */
  2258.  
  2259. &soc {
  2260. - /delete-node/qcom,camera-flash@0;
  2261. - /delete-node/qcom,camera-flash@1;
  2262. - /delete-node/gpio-regulator@0;
  2263. -};
  2264. -
  2265. -&soc {
  2266. tlmm: pinctrl@03400000 {
  2267. cam_sensor_rear_active: cam_sensor_rear_active {
  2268. /* RESET, STANDBY */
  2269. @@ -138,17 +133,19 @@
  2270. };
  2271. };
  2272.  
  2273. +&soc {
  2274. + /delete-node/gpio-regulator@0;
  2275. +};
  2276. +
  2277. &cci {
  2278. /delete-node/qcom,camera@0;
  2279. /delete-node/qcom,camera@1;
  2280. /delete-node/qcom,camera@2;
  2281. - /delete-node/qcom,camera@3;
  2282. /delete-node/qcom,eeprom@0;
  2283. /delete-node/qcom,eeprom@1;
  2284. /delete-node/qcom,eeprom@2;
  2285. /delete-node/qcom,actuator@0;
  2286. /delete-node/qcom,actuator@1;
  2287. - /delete-node/qcom,tof@0;
  2288. /delete-node/qcom,ois@0;
  2289. };
  2290.  
  2291. diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi
  2292. index 42414db..7ffbe65 100644
  2293. --- a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi
  2294. +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi
  2295. @@ -1,5 +1,6 @@
  2296. /*
  2297. * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  2298. + * Copyright (C) 2017 XiaoMi, Inc.
  2299. *
  2300. * This program is free software; you can redistribute it and/or modify
  2301. * it under the terms of the GNU General Public License version 2 and
  2302. @@ -12,12 +13,6 @@
  2303. */
  2304.  
  2305. &soc {
  2306. - /delete-node/qcom,camera-flash@0;
  2307. - /delete-node/qcom,camera-flash@1;
  2308. - /delete-node/gpio-regulator@0;
  2309. -};
  2310. -
  2311. -&soc {
  2312. tlmm: pinctrl@03400000 {
  2313. cam_sensor_rear_active: cam_sensor_rear_active {
  2314. /* RESET, STANDBY */
  2315. @@ -176,17 +171,19 @@
  2316. };
  2317. };
  2318.  
  2319. +&soc {
  2320. + /delete-node/gpio-regulator@0;
  2321. +};
  2322. +
  2323. &cci {
  2324. /delete-node/qcom,camera@0;
  2325. /delete-node/qcom,camera@1;
  2326. /delete-node/qcom,camera@2;
  2327. - /delete-node/qcom,camera@3;
  2328. /delete-node/qcom,eeprom@0;
  2329. /delete-node/qcom,eeprom@1;
  2330. /delete-node/qcom,eeprom@2;
  2331. /delete-node/qcom,actuator@0;
  2332. /delete-node/qcom,actuator@1;
  2333. - /delete-node/qcom,tof@0;
  2334. /delete-node/qcom,ois@0;
  2335. };
  2336.  
  2337. diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
  2338. index d0d1333..14975c5 100644
  2339. --- a/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
  2340. +++ b/arch/arm/boot/dts/qcom/msm8998-mdss-panels.dtsi
  2341. @@ -1,4 +1,5 @@
  2342. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  2343. + * Copyright (C) 2017 XiaoMi, Inc.
  2344. *
  2345. * This program is free software; you can redistribute it and/or modify
  2346. * it under the terms of the GNU General Public License version 2 and
  2347. @@ -24,6 +25,9 @@
  2348. #include "dsi-panel-jdi-dualmipi-cmd.dtsi"
  2349. #include "dsi-panel-sharp-1080p-cmd.dtsi"
  2350. #include "dsi-panel-jdi-1080p-video.dtsi"
  2351. +#include "dsi-panel-jdi-fhd-r63452-cmd.dtsi"
  2352. +#include "dsi-panel-lgd-fhd-td4322-cmd.dtsi"
  2353. +#include "dsi-panel-lgd-sw43401-wqhd-cmd.dtsi"
  2354. #include "dsi-panel-sharp-dualmipi-1080p-120hz.dtsi"
  2355. #include "dsi-panel-jdi-a407-dualmipi-wqhd-cmd.dtsi"
  2356. #include "dsi-panel-sim-video.dtsi"
  2357. @@ -41,10 +45,12 @@
  2358. qcom,panel-supply-entry@0 {
  2359. reg = <0>;
  2360. qcom,supply-name = "wqhd-vddio";
  2361. - qcom,supply-min-voltage = <1880000>;
  2362. - qcom,supply-max-voltage = <1880000>;
  2363. + qcom,supply-min-voltage = <1800000>;
  2364. + qcom,supply-max-voltage = <1800000>;
  2365. qcom,supply-enable-load = <32000>;
  2366. qcom,supply-disable-load = <80>;
  2367. + qcom,supply-post-on-sleep = <1>;
  2368. + qcom,supply-pre-off-sleep = <10>;
  2369. };
  2370.  
  2371. qcom,panel-supply-entry@1 {
  2372. @@ -64,10 +70,39 @@
  2373. qcom,supply-enable-load = <100000>;
  2374. qcom,supply-disable-load = <100>;
  2375. qcom,supply-post-on-sleep = <10>;
  2376. + qcom,supply-pre-off-sleep = <5>;
  2377. + };
  2378. + };
  2379. +};
  2380. +
  2381. +&soc {
  2382. + dsi_panel_pwr_supply_amoled: dsi_panel_pwr_supply_amoled {
  2383. + #address-cells = <1>;
  2384. + #size-cells = <0>;
  2385. +
  2386. + qcom,panel-supply-entry@0 {
  2387. + reg = <0>;
  2388. + qcom,supply-name = "wqhd-vddio";
  2389. + qcom,supply-min-voltage = <1800000>;
  2390. + qcom,supply-max-voltage = <1800000>;
  2391. + qcom,supply-enable-load = <32000>;
  2392. + qcom,supply-disable-load = <80>;
  2393. + #qcom,supply-post-on-sleep = <5>;
  2394. + };
  2395. +
  2396. + qcom,panel-supply-entry@1 {
  2397. + reg = <0>;
  2398. + qcom,supply-name = "vpnl";
  2399. + qcom,supply-min-voltage = <3000000>;
  2400. + qcom,supply-max-voltage = <3000000>;
  2401. + qcom,supply-enable-load = <32000>;
  2402. + qcom,supply-disable-load = <80>;
  2403. + qcom,supply-post-on-sleep = <5>;
  2404. };
  2405. };
  2406. };
  2407.  
  2408. +
  2409. &soc {
  2410. dsi_panel_pwr_supply_no_labibb: dsi_panel_pwr_supply_no_labibb {
  2411. #address-cells = <1>;
  2412. @@ -84,6 +119,44 @@
  2413. };
  2414. };
  2415.  
  2416. +&soc {
  2417. + dsi_panel_pwr_supply_lgd_td4322: dsi_panel_pwr_supply_lgd_td4322 {
  2418. + #address-cells = <1>;
  2419. + #size-cells = <0>;
  2420. +
  2421. + qcom,panel-supply-entry@0 {
  2422. + reg = <0>;
  2423. + qcom,supply-name = "wqhd-vddio";
  2424. + qcom,supply-min-voltage = <1800000>;
  2425. + qcom,supply-max-voltage = <1800000>;
  2426. + qcom,supply-enable-load = <32000>;
  2427. + qcom,supply-disable-load = <80>;
  2428. + qcom,supply-post-on-sleep = <10>;
  2429. + qcom,supply-pre-off-sleep = <10>;
  2430. + };
  2431. +
  2432. + qcom,panel-supply-entry@1 {
  2433. + reg = <1>;
  2434. + qcom,supply-name = "lab";
  2435. + qcom,supply-min-voltage = <4600000>;
  2436. + qcom,supply-max-voltage = <6000000>;
  2437. + qcom,supply-enable-load = <100000>;
  2438. + qcom,supply-disable-load = <100>;
  2439. + };
  2440. +
  2441. + qcom,panel-supply-entry@2 {
  2442. + reg = <2>;
  2443. + qcom,supply-name = "ibb";
  2444. + qcom,supply-min-voltage = <4600000>;
  2445. + qcom,supply-max-voltage = <6000000>;
  2446. + qcom,supply-enable-load = <100000>;
  2447. + qcom,supply-disable-load = <100>;
  2448. + qcom,supply-post-on-sleep = <10>;
  2449. + qcom,supply-pre-off-sleep = <5>;
  2450. + };
  2451. + };
  2452. +};
  2453. +
  2454. &dsi_dual_nt35597_video {
  2455. qcom,mdss-dsi-panel-timings = [00 1c 08 07 23 22 07 07 05 03 04 00];
  2456. qcom,mdss-dsi-t-clk-post = <0x0d>;
  2457. @@ -180,6 +253,18 @@
  2458. qcom,mdss-dsi-t-clk-pre = <0x28>;
  2459. };
  2460.  
  2461. +&dsi_jdi_fhd_r63452_cmd {
  2462. + qcom,mdss-dsi-panel-timings = [00 1a 07 06 0a 11 07 07 05 03 04 00];
  2463. + qcom,mdss-dsi-t-clk-post = <0x07>;
  2464. + qcom,mdss-dsi-t-clk-pre = <0x28>;
  2465. +};
  2466. +
  2467. +&dsi_lgd_fhd_td4322_cmd {
  2468. + qcom,mdss-dsi-panel-timings = [00 1a 07 06 0a 11 07 07 05 03 04 00];
  2469. + qcom,mdss-dsi-t-clk-post = <0x07>;
  2470. + qcom,mdss-dsi-t-clk-pre = <0x28>;
  2471. +};
  2472. +
  2473. &dsi_dual_sharp_1080_120hz_cmd {
  2474. qcom,mdss-dsi-panel-timings = [00 19 05 06 0a 0f 05 06 05 03 04 00];
  2475. qcom,mdss-dsi-t-clk-post = <0x7>;
  2476. diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi
  2477. index 2b9e13e..ffe70b8 100644
  2478. --- a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi
  2479. +++ b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi
  2480. @@ -1,4 +1,5 @@
  2481. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  2482. + * Copyright (C) 2017 XiaoMi, Inc.
  2483. *
  2484. * This program is free software; you can redistribute it and/or modify
  2485. * it under the terms of the GNU General Public License version 2 and
  2486. @@ -379,6 +380,7 @@
  2487. reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
  2488.  
  2489. qcom,timing-db-mode;
  2490. + vpnl-supply = <&disp_vpnl_vreg>;
  2491. wqhd-vddio-supply = <&pm8998_l14>;
  2492. lab-supply = <&lab_regulator>;
  2493. ibb-supply = <&ibb_regulator>;
  2494. diff --git a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
  2495. index 7159301..7003658 100644
  2496. --- a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
  2497. +++ b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
  2498. @@ -1,4 +1,5 @@
  2499. /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  2500. + * Copyright (C) 2017 XiaoMi, Inc.
  2501. *
  2502. * This program is free software; you can redistribute it and/or modify
  2503. * it under the terms of the GNU General Public License version 2 and
  2504. @@ -942,12 +943,12 @@
  2505. cam_actuator_vaf_active: cam_actuator_vaf_active {
  2506. /* ACTUATOR POWER */
  2507. mux {
  2508. - pins = "gpio27";
  2509. + pins = "gpio29";
  2510. function = "gpio";
  2511. };
  2512.  
  2513. config {
  2514. - pins = "gpio27";
  2515. + pins = "gpio29";
  2516. bias-disable; /* No PULL */
  2517. drive-strength = <2>; /* 2 MA */
  2518. };
  2519. @@ -956,12 +957,12 @@
  2520. cam_actuator_vaf_suspend: cam_actuator_vaf_suspend {
  2521. /* ACTUATOR POWER */
  2522. mux {
  2523. - pins = "gpio27";
  2524. + pins = "gpio29";
  2525. function = "gpio";
  2526. };
  2527.  
  2528. config {
  2529. - pins = "gpio27";
  2530. + pins = "gpio29";
  2531. bias-pull-down; /* PULL DOWN */
  2532. drive-strength = <2>; /* 2 MA */
  2533. };
  2534. @@ -1004,7 +1005,7 @@
  2535. config {
  2536. pins = "gpio13";
  2537. bias-disable; /* No PULL */
  2538. - drive-strength = <2>; /* 2 MA */
  2539. + drive-strength = <4>; /* 2 MA */
  2540. };
  2541. };
  2542.  
  2543. @@ -1019,19 +1020,19 @@
  2544. config {
  2545. pins = "gpio13";
  2546. bias-pull-down; /* PULL DOWN */
  2547. - drive-strength = <2>; /* 2 MA */
  2548. + drive-strength = <4>; /* 2 MA */
  2549. };
  2550. };
  2551.  
  2552. cam_sensor_rear_active: cam_sensor_rear_active {
  2553. /* RESET, STANDBY */
  2554. mux {
  2555. - pins = "gpio30","gpio29";
  2556. + pins = "gpio30", "gpio80";
  2557. function = "gpio";
  2558. };
  2559.  
  2560. config {
  2561. - pins = "gpio30","gpio29";
  2562. + pins = "gpio30", "gpio80";
  2563. bias-disable; /* No PULL */
  2564. drive-strength = <2>; /* 2 MA */
  2565. };
  2566. @@ -1291,12 +1292,12 @@
  2567. cam_sensor_rear_suspend: cam_sensor_rear_suspend {
  2568. /* RESET, STANDBY */
  2569. mux {
  2570. - pins = "gpio30","gpio29";
  2571. + pins = "gpio30","gpio80";
  2572. function = "gpio";
  2573. };
  2574.  
  2575. config {
  2576. - pins = "gpio30","gpio29";
  2577. + pins = "gpio30","gpio80";
  2578. bias-disable; /* No PULL */
  2579. drive-strength = <2>; /* 2 MA */
  2580. };
  2581. @@ -1313,7 +1314,7 @@
  2582. config {
  2583. pins = "gpio14";
  2584. bias-disable; /* No PULL */
  2585. - drive-strength = <2>; /* 2 MA */
  2586. + drive-strength = <4>; /* 2 MA */
  2587. };
  2588. };
  2589.  
  2590. @@ -1328,7 +1329,7 @@
  2591. config {
  2592. pins = "gpio14";
  2593. bias-pull-down; /* PULL DOWN */
  2594. - drive-strength = <2>; /* 2 MA */
  2595. + drive-strength = <4>; /* 2 MA */
  2596. };
  2597. };
  2598.  
  2599. @@ -1365,12 +1366,12 @@
  2600. cam_sensor_rear2_active: cam_sensor_rear2_active {
  2601. /* RESET, STANDBY */
  2602. mux {
  2603. - pins = "gpio9","gpio8";
  2604. + pins = "gpio9";
  2605. function = "gpio";
  2606. };
  2607.  
  2608. config {
  2609. - pins = "gpio9","gpio8";
  2610. + pins = "gpio9";
  2611. bias-disable; /* No PULL */
  2612. drive-strength = <2>; /* 2 MA */
  2613. };
  2614. @@ -1485,11 +1486,11 @@
  2615. cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
  2616. /* RESET, STANDBY */
  2617. mux {
  2618. - pins = "gpio9","gpio8";
  2619. + pins = "gpio9";
  2620. function = "gpio";
  2621. };
  2622. config {
  2623. - pins = "gpio9","gpio8";
  2624. + pins = "gpio9";
  2625. bias-disable; /* No PULL */
  2626. drive-strength = <2>; /* 2 MA */
  2627. };
  2628. @@ -1506,7 +1507,7 @@
  2629. config {
  2630. pins = "gpio15";
  2631. bias-disable; /* No PULL */
  2632. - drive-strength = <2>; /* 2 MA */
  2633. + drive-strength = <4>; /* 2 MA */
  2634. };
  2635. };
  2636.  
  2637. @@ -1521,19 +1522,19 @@
  2638. config {
  2639. pins = "gpio15";
  2640. bias-pull-down; /* PULL DOWN */
  2641. - drive-strength = <2>; /* 2 MA */
  2642. + drive-strength = <4>; /* 2 MA */
  2643. };
  2644. };
  2645.  
  2646. cam_sensor_front_active: cam_sensor_front_active {
  2647. /* RESET VANA*/
  2648. mux {
  2649. - pins = "gpio28", "gpio29";
  2650. + pins = "gpio28", "gpio27","gpio9";
  2651. function = "gpio";
  2652. };
  2653.  
  2654. config {
  2655. - pins = "gpio28", "gpio29";
  2656. + pins = "gpio28", "gpio27","gpio9";
  2657. bias-disable; /* No PULL */
  2658. drive-strength = <2>; /* 2 MA */
  2659. };
  2660. @@ -1609,12 +1610,12 @@
  2661. cam_sensor_front_suspend: cam_sensor_front_suspend {
  2662. /* RESET */
  2663. mux {
  2664. - pins = "gpio28";
  2665. + pins = "gpio28", "gpio27","gpio9";
  2666. function = "gpio";
  2667. };
  2668.  
  2669. config {
  2670. - pins = "gpio28";
  2671. + pins = "gpio28", "gpio27","gpio9";
  2672. bias-disable; /* No PULL */
  2673. drive-strength = <2>; /* 2 MA */
  2674. };
  2675. @@ -1661,6 +1662,31 @@
  2676. };
  2677. };
  2678.  
  2679. + mdss_vpnl_active: mdss_vpnl_active {
  2680. + mux {
  2681. + pins = "gpio63";
  2682. + function = "gpio";
  2683. + };
  2684. + config {
  2685. + pins = "gpio63";
  2686. + drive-strength = <8>; /* 8 mA */
  2687. + bias-disable=<0>;
  2688. + output-high;
  2689. + };
  2690. + };
  2691. +
  2692. + mdss_vpnl_suspend: mdss_vpnl_suspend {
  2693. + mux {
  2694. + pins = "gpio63";
  2695. + function = "gpio";
  2696. + };
  2697. + config {
  2698. + pins = "gpio63";
  2699. + drive-strength = <2>; /* 2 mA */
  2700. + bias-pull-down; /* pull down */
  2701. + };
  2702. + };
  2703. +
  2704. pmx_mdss_te {
  2705. mdss_te_active: mdss_te_active {
  2706. mux {
  2707. @@ -1890,7 +1916,7 @@
  2708. config {
  2709. pins = "gpio89";
  2710. drive-strength = <2>;
  2711. - bias-pull-down;
  2712. + bias-disable;
  2713. };
  2714. };
  2715.  
  2716. @@ -1954,6 +1980,46 @@
  2717. };
  2718. };
  2719.  
  2720. + bk_ts_mux {
  2721. + bk_ts_active: bk_ts_active {
  2722. + mux {
  2723. + pins = "gpio58", "gpio59";
  2724. + function = "gpio";
  2725. + };
  2726. +
  2727. + config {
  2728. + pins = "gpio58", "gpio59";
  2729. + drive-strength = <16>;
  2730. + bias-pull-up;
  2731. + };
  2732. + };
  2733. +
  2734. + bk_ts_reset_suspend: bk_ts_reset_suspend {
  2735. + mux {
  2736. + pins = "gpio59";
  2737. + function = "gpio";
  2738. + };
  2739. +
  2740. + config {
  2741. + pins = "gpio59";
  2742. + drive-strength = <2>;
  2743. + bias-disable;
  2744. + };
  2745. + };
  2746. +
  2747. + bk_ts_int_suspend: bk_ts_int_suspend {
  2748. + mux {
  2749. + pins = "gpio58";
  2750. + function = "gpio";
  2751. + };
  2752. +
  2753. + config {
  2754. + pins = "gpio58";
  2755. + drive-strength = <2>;
  2756. + bias-disable;
  2757. + };
  2758. + };
  2759. + };
  2760. sdc2_clk_on: sdc2_clk_on {
  2761. config {
  2762. pins = "sdc2_clk";
  2763. @@ -3200,6 +3266,75 @@
  2764. };
  2765. };
  2766.  
  2767. + fp_mux {
  2768. + fp_active: fp_active {
  2769. + mux {
  2770. + pins = "gpio121";
  2771. + function = "gpio";
  2772. + };
  2773. + config {
  2774. + pins = "gpio121";
  2775. + drive-strength = <8>;
  2776. + bias-disable;
  2777. + };
  2778. + };
  2779. +
  2780. + fp_suspend: fp_suspend {
  2781. + mux {
  2782. + pins = "gpio121";
  2783. + function = "gpio";
  2784. + };
  2785. + config {
  2786. + pins = "gpio121";
  2787. + drive-strength = <2>;
  2788. + bias-disable;
  2789. + };
  2790. + };
  2791. + };
  2792. + /* GPIO_37 : FP_RESET_N */
  2793. + msm_gpio_37: msm_gpio_37 {
  2794. + mux {
  2795. + pins = "gpio37";
  2796. + function = "gpio";
  2797. + };
  2798. +
  2799. + config {
  2800. + pins = "gpio37";
  2801. + drive-strength = <2>;
  2802. + bias-disable;
  2803. + output-low;
  2804. + };
  2805. + };
  2806. +
  2807. + /* GPIO_37 : FP_RESET_N, state device active*/
  2808. + msm_gpio_37_output_high: msm_gpio_37_output_high {
  2809. + mux {
  2810. + pins = "gpio37";
  2811. + function = "gpio";
  2812. + };
  2813. +
  2814. + config {
  2815. + pins = "gpio37";
  2816. + drive-strength = <2>;
  2817. + bias-disable;
  2818. + output-high;
  2819. + };
  2820. + };
  2821. +
  2822. + /* GPIO_121 : FP_INT_N */
  2823. + msm_gpio_121: msm_gpio_121 {
  2824. + mux {
  2825. + pins = "gpio121";
  2826. + function = "gpio";
  2827. + };
  2828. +
  2829. + config {
  2830. + pins = "gpio121";
  2831. + drive-strength = <2>;
  2832. + bias-pull-down;
  2833. + };
  2834. + };
  2835. +
  2836. spkr_1_sd_mediabox {
  2837. spkr_1_sd_sleep_mediabox: spkr_1_sd_sleep_mediabox {
  2838. mux {
  2839. @@ -3254,6 +3389,31 @@
  2840. };
  2841. };
  2842.  
  2843. + gpio_rf {
  2844. + gpio_rf_active: gpio_rf_active {
  2845. + mux {
  2846. + pins = "gpio119";
  2847. + function = "gpio";
  2848. + };
  2849. + config {
  2850. + pins = "gpio119";
  2851. + drive-strength = <2>;
  2852. + bias-disable;
  2853. + };
  2854. + };
  2855. + gpio_rf_suspend: gpio_rf_suspend {
  2856. + mux {
  2857. + pins = "gpio119";
  2858. + function = "gpio";
  2859. + };
  2860. + config {
  2861. + pins = "gpio119";
  2862. + drive-strength = <2>;
  2863. + bias-disable;
  2864. + };
  2865. + };
  2866. + };
  2867. +
  2868. sdc2_cd_on_mediabox: sdc2_cd_on_mediabox {
  2869. mux {
  2870. pins = "gpio86";
  2871. @@ -3279,5 +3439,83 @@
  2872. drive-strength = <2>; /* 2 MA */
  2873. };
  2874. };
  2875. +
  2876. + rcv_id {
  2877. + rcv_id_no_pull: rcv_id_no_pull {
  2878. + mux {
  2879. + pins = "gpio11";
  2880. + function = "gpio";
  2881. + };
  2882. + config {
  2883. + pins = "gpio11";
  2884. + drive-strength = <8>;
  2885. + bias-disable;
  2886. + input-enable;
  2887. + };
  2888. + };
  2889. + rcv_id_pull_up: rcv_id_pull_up {
  2890. + mux {
  2891. + pins = "gpio11";
  2892. + function = "gpio";
  2893. + };
  2894. + config {
  2895. + pins = "gpio11";
  2896. + drive-strength = <8>;
  2897. + bias-pull-up;
  2898. + input-enable;
  2899. + };
  2900. + };
  2901. + rcv_id_pull_down: rcv_id_pull_down {
  2902. + mux {
  2903. + pins = "gpio11";
  2904. + function = "gpio";
  2905. + };
  2906. + config {
  2907. + pins = "gpio11";
  2908. + drive-strength = <8>;
  2909. + bias-pull-down;
  2910. + input-enable;
  2911. + };
  2912. + };
  2913. + };
  2914. +
  2915. + spk_id {
  2916. + spk_id_no_pull: spk_id_no_pull {
  2917. + mux {
  2918. + pins = "gpio100";
  2919. + function = "gpio";
  2920. + };
  2921. + config {
  2922. + pins = "gpio100";
  2923. + drive-strength = <8>;
  2924. + bias-disable;
  2925. + input-enable;
  2926. + };
  2927. + };
  2928. + spk_id_pull_up: spk_id_pull_up {
  2929. + mux {
  2930. + pins = "gpio100";
  2931. + function = "gpio";
  2932. + };
  2933. + config {
  2934. + pins = "gpio100";
  2935. + drive-strength = <8>;
  2936. + bias-pull-up;
  2937. + input-enable;
  2938. + };
  2939. + };
  2940. + spk_id_pull_down: spk_id_pull_down {
  2941. + mux {
  2942. + pins = "gpio100";
  2943. + function = "gpio";
  2944. + };
  2945. + config {
  2946. + pins = "gpio100";
  2947. + drive-strength = <8>;
  2948. + bias-pull-down;
  2949. + input-enable;
  2950. + };
  2951. + };
  2952. + };
  2953. };
  2954. };
  2955. diff --git a/arch/arm/boot/dts/qcom/msm8998-pm.dtsi b/arch/arm/boot/dts/qcom/msm8998-pm.dtsi
  2956. index 8fd75c3..4a0cda6 100644
  2957. --- a/arch/arm/boot/dts/qcom/msm8998-pm.dtsi
  2958. +++ b/arch/arm/boot/dts/qcom/msm8998-pm.dtsi
  2959. @@ -755,6 +755,7 @@
  2960. <16 42>,
  2961. <17 46>,
  2962. <18 50>,
  2963. + <0xff 52>,
  2964. <19 53>,
  2965. <20 54>,
  2966. <21 56>,
  2967. diff --git a/arch/arm/boot/dts/qcom/msm8998-regulator.dtsi b/arch/arm/boot/dts/qcom/msm8998-regulator.dtsi
  2968. index 9307a3b..9ae423f 100644
  2969. --- a/arch/arm/boot/dts/qcom/msm8998-regulator.dtsi
  2970. +++ b/arch/arm/boot/dts/qcom/msm8998-regulator.dtsi
  2971. @@ -1,4 +1,5 @@
  2972. /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  2973. + * Copyright (C) 2017 XiaoMi, Inc.
  2974. *
  2975. * This program is free software; you can redistribute it and/or modify
  2976. * it under the terms of the GNU General Public License version 2 and
  2977. @@ -222,8 +223,9 @@
  2978. rpm-regulator-ldoa6 {
  2979. status = "okay";
  2980. pm8998_l6: regulator-l6 {
  2981. - regulator-min-microvolt = <1808000>;
  2982. - regulator-max-microvolt = <1808000>;
  2983. + regulator-min-microvolt = <1800000>;
  2984. + regulator-max-microvolt = <1800000>;
  2985. + qcom,init-ldo-mode = <1>;
  2986. status = "okay";
  2987. };
  2988. };
  2989. @@ -306,8 +308,8 @@
  2990. rpm-regulator-ldoa14 {
  2991. status = "okay";
  2992. pm8998_l14: regulator-l14 {
  2993. - regulator-min-microvolt = <1880000>;
  2994. - regulator-max-microvolt = <1880000>;
  2995. + regulator-min-microvolt = <1800000>;
  2996. + regulator-max-microvolt = <1800000>;
  2997. proxy-supply = <&pm8998_l14>;
  2998. qcom,proxy-consumer-enable;
  2999. qcom,proxy-consumer-current = <32000>;
  3000. @@ -1123,6 +1125,31 @@
  3001. qcom,acc-sel-l1-bit-pos = <0>;
  3002. qcom,acc-sel-l1-bit-size = <1>;
  3003. };
  3004. +
  3005. + disp_vpnl_vreg: disp_vpnl_vreg {
  3006. + compatible = "regulator-fixed";
  3007. + regulator-name = "disp_vpnl_vreg";
  3008. + start-delay-us = <4000>;
  3009. + enable-active-high;
  3010. + gpio = <&tlmm 63 0>;
  3011. + };
  3012. +
  3013. + disp_vddts_vreg: disp_vddts_vreg {
  3014. + compatible = "regulator-fixed";
  3015. + regulator-name = "disp_vddts_vreg";
  3016. + startup-delay-us = <4000>;
  3017. + enable-active-high;
  3018. + regulator-boot-on;
  3019. + gpio = <&tlmm 50 0>;
  3020. + };
  3021. +
  3022. + fp_vdd_vreg: fp_vdd_vreg {
  3023. + compatible = "regulator-fixed";
  3024. + regulator-name = "fp_vdd_vreg";
  3025. + startup-delay-us = <4000>;
  3026. + enable-active-high;
  3027. + gpio = <&tlmm 35 0>;
  3028. + };
  3029. };
  3030.  
  3031. &pmi8998_charger {
  3032. diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
  3033. index 8e85640..deff6c3 100644
  3034. --- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
  3035. +++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
  3036. @@ -1,4 +1,5 @@
  3037. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  3038. + * Copyright (C) 2017 XiaoMi, Inc.
  3039. *
  3040. * This program is free software; you can redistribute it and/or modify
  3041. * it under the terms of the GNU General Public License version 2 and
  3042. @@ -1117,11 +1118,9 @@
  3043.  
  3044. &qusb_phy0 {
  3045. reg = <0x0c012000 0x2a8>,
  3046. - <0x01fcb24c 0x4>,
  3047. - <0x00784238 0x4>;
  3048. + <0x01fcb24c 0x4>;
  3049. reg-names = "qusb_phy_base",
  3050. - "tcsr_clamp_dig_n_1p8",
  3051. - "efuse_addr";
  3052. + "tcsr_clamp_dig_n_1p8";
  3053. qcom,efuse-bit-pos = <16>;
  3054. qcom,efuse-num-bits = <4>;
  3055. qcom,qusb-phy-init-seq =
  3056. @@ -1199,6 +1198,7 @@
  3057. /* Updated chip ID */
  3058. qcom,chipid = <0x05040001>;
  3059. qcom,initial-pwrlevel = <6>;
  3060. + qcom,restrict-pwrlevel = <1>;
  3061.  
  3062. qcom,gpu-pwrlevels {
  3063. #address-cells = <1>;
  3064. diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
  3065. index 4f27b3f..eed82c7 100644
  3066. --- a/arch/arm/boot/dts/qcom/msm8998.dtsi
  3067. +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
  3068. @@ -1,4 +1,5 @@
  3069. /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  3070. + * Copyright (C) 2017 XiaoMi, Inc.
  3071. *
  3072. * This program is free software; you can redistribute it and/or modify
  3073. * it under the terms of the GNU General Public License version 2 and
  3074. @@ -286,40 +287,40 @@
  3075. reg = <0 0x85800000 0 0x3700000>;
  3076. };
  3077.  
  3078. - pil_ipa_gpu_mem: pil_ipa_gpu_region@95200000 {
  3079. + pil_ipa_gpu_mem: pil_ipa_gpu_region@95600000 {
  3080. compatible = "removed-dma-pool";
  3081. no-map;
  3082. - reg = <0 0x95200000 0 0x100000>;
  3083. + reg = <0 0x95600000 0 0x100000>;
  3084. };
  3085.  
  3086. - pil_slpi_mem: pil_slpi_region@94300000 {
  3087. + pil_slpi_mem: pil_slpi_region@94700000 {
  3088. compatible = "removed-dma-pool";
  3089. no-map;
  3090. - reg = <0 0x94300000 0 0xf00000>;
  3091. + reg = <0 0x94700000 0 0xf00000>;
  3092. };
  3093.  
  3094. - pil_mba_mem: pil_mba_region@94100000 {
  3095. + pil_mba_mem: pil_mba_region@94500000 {
  3096. compatible = "removed-dma-pool";
  3097. no-map;
  3098. - reg = <0 0x94100000 0 0x200000>;
  3099. + reg = <0 0x94500000 0 0x200000>;
  3100. };
  3101.  
  3102. - pil_video_mem: pil_video_region@93c00000 {
  3103. + pil_video_mem: pil_video_region@94000000 {
  3104. compatible = "removed-dma-pool";
  3105. no-map;
  3106. - reg = <0 0x93c00000 0 0x500000>;
  3107. + reg = <0 0x94000000 0 0x500000>;
  3108. };
  3109.  
  3110. - modem_mem: modem_region@8cc00000 {
  3111. + modem_mem: modem_region@8d000000 {
  3112. compatible = "removed-dma-pool";
  3113. no-map;
  3114. - reg = <0 0x8cc00000 0 0x7000000>;
  3115. + reg = <0 0x8d000000 0 0x7000000>;
  3116. };
  3117.  
  3118. pil_adsp_mem: pil_adsp_region@0x8b200000 {
  3119. compatible = "removed-dma-pool";
  3120. no-map;
  3121. - reg = <0 0x8b200000 0 0x1a00000>;
  3122. + reg = <0 0x8b200000 0 0x1e00000>;
  3123. };
  3124.  
  3125. spss_mem: spss_region@8ab00000 { /* for SPSS-PIL */
  3126. @@ -1774,6 +1775,7 @@
  3127. snps,has-lpm-erratum;
  3128. snps,hird-threshold = /bits/ 8 <0x10>;
  3129. snps,num-gsi-evt-buffs = <0x3>;
  3130. + maximum-speed = "high-speed";
  3131. };
  3132.  
  3133. qcom,usbbam@a904000 {
  3134. @@ -2292,10 +2294,14 @@
  3135. qcom,sensor-name = "quiet_therm";
  3136. };
  3137. sensor_information28: qcom,sensor-information-28 {
  3138. + qcom,sensor-type = "adc";
  3139. + qcom,sensor-name = "xo_therm";
  3140. + };
  3141. + sensor_information29: qcom,sensor-information-29 {
  3142. qcom,sensor-type = "llm";
  3143. qcom,sensor-name = "limits_sensor-01";
  3144. };
  3145. - sensor_information29: qcom,sensor-information-29 {
  3146. + sensor_information30: qcom,sensor-information-30 {
  3147. qcom,sensor-type = "llm";
  3148. qcom,sensor-name = "limits_sensor-02";
  3149. };
  3150. @@ -2819,8 +2825,8 @@
  3151. reg = <0x17817000 0x1000>;
  3152. reg-names = "wdt-base";
  3153. interrupts = <0 3 0>, <0 4 0>;
  3154. - qcom,bark-time = <11000>;
  3155. - qcom,pet-time = <10000>;
  3156. + qcom,bark-time = <20000>;
  3157. + qcom,pet-time = <15000>;
  3158. qcom,ipi-ping;
  3159. qcom,wakeup-enable;
  3160. qcom,scandump-size = <0x40000>;
  3161. @@ -3252,34 +3258,53 @@
  3162. };
  3163.  
  3164. &gdsc_venus {
  3165. + clock-names = "bus_clk", "maxi_clk", "core_clk";
  3166. + clocks = <&clock_mmss clk_mmss_video_axi_clk>,
  3167. + <&clock_mmss clk_mmss_video_maxi_clk>,
  3168. + <&clock_mmss clk_mmss_video_core_clk>;
  3169. status = "ok";
  3170. };
  3171.  
  3172. &gdsc_venus_core0 {
  3173. + clock-names = "core0_clk";
  3174. + clocks = <&clock_mmss clk_mmss_video_subcore0_clk>;
  3175. status = "ok";
  3176. qcom,support-hw-trigger;
  3177. };
  3178.  
  3179. &gdsc_venus_core1 {
  3180. + clock-names = "core1_clk";
  3181. + clocks = <&clock_mmss clk_mmss_video_subcore1_clk>;
  3182. status = "ok";
  3183. qcom,support-hw-trigger;
  3184. };
  3185.  
  3186. &gdsc_camss_top {
  3187. + ock-names = "bus_clk", "vfe_axi";
  3188. + clocks = <&clock_mmss clk_mmss_camss_cpp_axi_clk>,
  3189. + <&clock_mmss clk_mmss_camss_vfe_vbif_axi_clk>;
  3190. status = "ok";
  3191. };
  3192.  
  3193. &gdsc_vfe0 {
  3194. + clock-names = "core0_clk" , "core0_stream_clk";
  3195. + clocks = <&clock_mmss clk_mmss_camss_vfe0_clk>,
  3196. + <&clock_mmss clk_mmss_camss_vfe0_stream_clk>;
  3197. parent-supply = <&gdsc_camss_top>;
  3198. status = "ok";
  3199. };
  3200.  
  3201. &gdsc_vfe1 {
  3202. + clock-names = "core1_clk" , "core1_stream_clk";
  3203. + clocks = <&clock_mmss clk_mmss_camss_vfe1_clk>,
  3204. + <&clock_mmss clk_mmss_camss_vfe1_stream_clk>;
  3205. parent-supply = <&gdsc_camss_top>;
  3206. status = "ok";
  3207. };
  3208.  
  3209. &gdsc_cpp {
  3210. + clock-names = "core_clk";
  3211. + clocks = <&clock_mmss clk_mmss_camss_cpp_clk>;
  3212. parent-supply = <&gdsc_camss_top>;
  3213. qcom,support-hw-trigger;
  3214. status = "ok";
  3215. diff --git a/arch/arm/boot/dts/qcom/sagit-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/sagit-camera-sensor-mtp.dtsi
  3216. new file mode 100644
  3217. index 0000000..dc84d6b
  3218. --- /dev/null
  3219. +++ b/arch/arm/boot/dts/qcom/sagit-camera-sensor-mtp.dtsi
  3220. @@ -0,0 +1,478 @@
  3221. +/*
  3222. + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  3223. + * Copyright (C) 2017 XiaoMi, Inc.
  3224. + *
  3225. + * This program is free software; you can redistribute it and/or modify
  3226. + * it under the terms of the GNU General Public License version 2 and
  3227. + * only version 2 as published by the Free Software Foundation.
  3228. + *
  3229. + * This program is distributed in the hope that it will be useful,
  3230. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3231. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3232. + * GNU General Public License for more details.
  3233. + */
  3234. +
  3235. +&soc {
  3236. + led_flash0: qcom,camera-flash@0 {
  3237. + cell-index = <0>;
  3238. + compatible = "qcom,camera-flash";
  3239. + qcom,flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
  3240. + qcom,torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
  3241. + qcom,switch-source = <&pmi8998_switch0>;
  3242. + status = "ok";
  3243. + };
  3244. +
  3245. + led_flash1: qcom,camera-flash@1 {
  3246. + cell-index = <1>;
  3247. + compatible = "qcom,camera-flash";
  3248. + qcom,flash-source = <&pmi8998_flash2>;
  3249. + qcom,torch-source = <&pmi8998_torch2>;
  3250. + qcom,switch-source = <&pmi8998_switch1>;
  3251. + status = "disable";
  3252. + };
  3253. +
  3254. + vaf_gpio_supply: vaf_gpio_supply {
  3255. + compatible = "regulator-fixed";
  3256. + regulator-name = "vaf_gpio_supply";
  3257. + regulator-min-microvolt = <2800000>;
  3258. + regulator-max-microvolt = <2800000>;
  3259. + startup-delay-us = <4000>;
  3260. + enable-active-high;
  3261. + gpio = <&tlmm 29 0>;
  3262. + };
  3263. +
  3264. + vana_gpio_supply: vana_gpio_supply {
  3265. + compatible = "regulator-fixed";
  3266. + regulator-name = "vana_gpio_supply";
  3267. + regulator-min-microvolt = <2800000>;
  3268. + regulator-max-microvolt = <2800000>;
  3269. + startup-delay-us = <4000>;
  3270. + enable-active-high;
  3271. + gpio = <&tlmm 80 0>;
  3272. + };
  3273. +
  3274. + vdig_gpio_supply: vdig_gpio_supply {
  3275. + compatible = "regulator-fixed";
  3276. + regulator-name = "vdig_gpio_supply";
  3277. + regulator-min-microvolt = <1100000>;
  3278. + regulator-max-microvolt = <1100000>;
  3279. + startup-delay-us = <4000>;
  3280. + enable-active-high;
  3281. + gpio = <&pm8998_gpios 20 0>;
  3282. + };
  3283. +};
  3284. +
  3285. +&cci {
  3286. + actuator0: qcom,actuator@0 {
  3287. + cell-index = <0>;
  3288. + reg = <0x0>;
  3289. + compatible = "qcom,actuator";
  3290. + qcom,cci-master = <0>;
  3291. + cam_vaf-supply = <&vaf_gpio_supply>;
  3292. + qcom,cam-vreg-name = "cam_vaf";
  3293. + qcom,cam-vreg-min-voltage = <2800000>;
  3294. + qcom,cam-vreg-max-voltage = <2800000>;
  3295. + qcom,cam-vreg-op-mode = <100000>;
  3296. + };
  3297. +
  3298. + actuator1: qcom,actuator@1 {
  3299. + cell-index = <1>;
  3300. + reg = <0x1>;
  3301. + compatible = "qcom,actuator";
  3302. + qcom,cci-master = <1>;
  3303. + cam_vaf-supply = <&vaf_gpio_supply>;
  3304. + qcom,cam-vreg-name = "cam_vaf";
  3305. + qcom,cam-vreg-min-voltage = <2800000>;
  3306. + qcom,cam-vreg-max-voltage = <2800000>;
  3307. + qcom,cam-vreg-op-mode = <100000>;
  3308. + };
  3309. +
  3310. + ois0: qcom,ois@0 {
  3311. + cell-index = <0>;
  3312. + reg = <0x0>;
  3313. + compatible = "qcom,ois";
  3314. + qcom,cci-master = <0>;
  3315. + cam_vaf-supply = <&vaf_gpio_supply>;
  3316. + qcom,cam-vreg-name = "cam_vaf";
  3317. + qcom,cam-vreg-min-voltage = <2800000>;
  3318. + qcom,cam-vreg-max-voltage = <2800000>;
  3319. + qcom,cam-vreg-op-mode = <100000>;
  3320. + };
  3321. +
  3322. + eeprom0: qcom,eeprom@0 {
  3323. + cell-index = <0>;
  3324. + reg = <0>;
  3325. + qcom,eeprom-name = "sagit_imx386_semco";
  3326. + compatible = "qcom,eeprom";
  3327. + qcom,slave-addr = <0xa0>;
  3328. + qcom,i2c-freq-mode = <1>;
  3329. + qcom,num-blocks = <1>;
  3330. + qcom,page0 = <0 0 0 0 0 0>;
  3331. + qcom,poll0 = <0 0 0 0 0 0>;
  3332. + qcom,mem0 = <7039 0x00 2 0 1 0>;
  3333. + cam_vio-supply = <&pm8998_lvs1>;
  3334. + cam_vdig-supply = <&vdig_gpio_supply>;
  3335. + cam_vana-supply = <&vana_gpio_supply>;
  3336. + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana";
  3337. + qcom,cam-vreg-min-voltage = <0 1000000 2600000>;
  3338. + qcom,cam-vreg-max-voltage = <0 1200000 2900000>;
  3339. + qcom,cam-vreg-op-mode = <0 1100000 2800000>;
  3340. + qcom,cam-power-seq-type = "sensor_vreg";
  3341. + qcom,cam-power-seq-val = "cam_vio";
  3342. + qcom,cam-power-seq-cfg-val = <1>;
  3343. + qcom,cam-power-seq-delay = <1>;
  3344. + qcom,gpio-no-mux = <0>;
  3345. + pinctrl-names = "cam_default", "cam_suspend";
  3346. + pinctrl-0 = <&cam_sensor_mclk0_active
  3347. + &cam_sensor_rear_active>;
  3348. + pinctrl-1 = <&cam_sensor_mclk0_suspend
  3349. + &cam_sensor_rear_suspend>;
  3350. + gpios = <&tlmm 13 0>,
  3351. + <&tlmm 30 0>;
  3352. + qcom,gpio-reset = <1>;
  3353. + qcom,gpio-req-tbl-num = <0 1>;
  3354. + qcom,gpio-req-tbl-flags = <1 0>;
  3355. + qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
  3356. + "CAM_RESET0";
  3357. + qcom,sensor-position = <0>;
  3358. + qcom,sensor-mode = <0>;
  3359. + qcom,cci-master = <0>;
  3360. + status = "ok";
  3361. + clocks = <&clock_mmss clk_mclk0_clk_src>,
  3362. + <&clock_mmss clk_mmss_camss_mclk0_clk>;
  3363. + clock-names = "cam_src_clk", "cam_clk";
  3364. + qcom,clock-rates = <24000000 0>;
  3365. + };
  3366. +
  3367. + eeprom1: qcom,eeprom@1 {
  3368. + cell-index = <1>;
  3369. + reg = <1>;
  3370. + qcom,eeprom-name = "sagit_s5k3m3_semco";
  3371. + compatible = "qcom,eeprom";
  3372. + qcom,slave-addr = <0xa0>;
  3373. + qcom,i2c-freq-mode = <1>;
  3374. + qcom,num-blocks = <1>;
  3375. + qcom,page0 = <0 0 0 0 0 0>;
  3376. + qcom,poll0 = <0 0 0 0 0 0>;
  3377. + qcom,mem0 = <4912 0x00 2 0 1 0>;
  3378. + cam_vio-supply = <&pm8998_lvs1>;
  3379. + cam_vdig-supply = <&vdig_gpio_supply>;
  3380. + cam_vana-supply = <&vana_gpio_supply>;
  3381. + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana";
  3382. + qcom,cam-vreg-min-voltage = <0 1000000 2800000>;
  3383. + qcom,cam-vreg-max-voltage = <0 1100000 2800000>;
  3384. + qcom,cam-vreg-op-mode = <0 1100000 2800000>;
  3385. + qcom,cam-power-seq-type = "sensor_vreg";
  3386. + qcom,cam-power-seq-val = "cam_vio";
  3387. + qcom,cam-power-seq-cfg-val = <1>;
  3388. + qcom,cam-power-seq-delay = <1>;
  3389. + qcom,gpio-no-mux = <0>;
  3390. + pinctrl-names = "cam_default", "cam_suspend";
  3391. + pinctrl-0 = <&cam_sensor_mclk0_active
  3392. + &cam_sensor_rear_active>;
  3393. + pinctrl-1 = <&cam_sensor_mclk0_suspend
  3394. + &cam_sensor_rear_suspend>;
  3395. + gpios = <&tlmm 13 0>,
  3396. + <&tlmm 30 0>;
  3397. + qcom,gpio-reset = <1>;
  3398. + qcom,gpio-req-tbl-num = <0 1>;
  3399. + qcom,gpio-req-tbl-flags = <1 0>;
  3400. + qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
  3401. + "CAM_RESET0";
  3402. + qcom,sensor-position = <0>;
  3403. + qcom,sensor-mode = <0>;
  3404. + qcom,cci-master = <0>;
  3405. + status = "ok";
  3406. + clocks = <&clock_mmss clk_mclk0_clk_src>,
  3407. + <&clock_mmss clk_mmss_camss_mclk0_clk>;
  3408. + clock-names = "cam_src_clk", "cam_clk";
  3409. + qcom,clock-rates = <24000000 0>;
  3410. + };
  3411. +
  3412. + eeprom2: qcom,eeprom@2 {
  3413. + cell-index = <2>;
  3414. + reg = <0x2>;
  3415. + qcom,eeprom-name = "sagit_imx268_primax";
  3416. + compatible = "qcom,eeprom";
  3417. + qcom,slave-addr = <0x34>;
  3418. + qcom,i2c-freq-mode = <1>;
  3419. + qcom,num-blocks = <4>;
  3420. + qcom,saddr0 = <0x34>;
  3421. + qcom,page0 = <1 0x0A02 2 0x00 1 0>;
  3422. + qcom,pageen0 = <1 0x0A00 2 0x01 1 0>;
  3423. + qcom,poll0 = <0 0x0 0 0x0 0 0>;
  3424. + qcom,mem0 = <64 0x0A04 2 0 1 0>;
  3425. +
  3426. + qcom,saddr1 = <0x34>;
  3427. + qcom,page1 = <1 0x0A02 2 0x01 1 0>;
  3428. + qcom,pageen1 = <1 0x0A00 2 0x01 1 0>;
  3429. + qcom,poll1 = <0 0x0 0 0x0 0 0>;
  3430. + qcom,mem1 = <64 0x0A04 2 0 1 0>;
  3431. +
  3432. + qcom,saddr2 = <0x34>;
  3433. + qcom,page2 = <1 0x0A02 2 0x02 1 0>;
  3434. + qcom,pageen2 = <1 0x0A00 2 0x01 1 0>;
  3435. + qcom,poll2 = <0 0x0 0 0x0 0 0>;
  3436. + qcom,mem2 = <64 0x0A04 2 0 1 0>;
  3437. +
  3438. + qcom,saddr3 = <0x34>;
  3439. + qcom,page3 = <1 0x0A02 2 0x03 1 0>;
  3440. + qcom,pageen3 = <0 0x0A00 2 0x01 1 0>;
  3441. + qcom,poll3 = <0 0x0 0 0x0 0 0>;
  3442. + qcom,mem3 = <64 0x0A04 2 0 1 0>;
  3443. +
  3444. + cam_vio-supply = <&pm8998_lvs1>;
  3445. + cam_vana-supply = <&pm8998_l22>;
  3446. + qcom,cam-vreg-name = "cam_vio", "cam_vana";
  3447. + qcom,cam-vreg-min-voltage = <0 2864000>;
  3448. + qcom,cam-vreg-max-voltage = <0 2864000>;
  3449. + qcom,cam-vreg-op-mode = <0 80000>;
  3450. + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_gpio", "sensor_vreg", "sensor_vreg", "sensor_clk", "sensor_gpio", "sensor_gpio";
  3451. + qcom,cam-power-seq-val = "sensor_gpio_reset","sensor_gpio_standby", "sensor_gpio_vdig", "cam_vio", "cam_vana", "sensor_cam_mclk", "sensor_gpio_reset","sensor_gpio_standby";
  3452. + qcom,cam-power-seq-cfg-val = <0 0 1 1 2864000 24000000 1 1>;
  3453. + qcom,cam-power-seq-delay = <1 1 1 1 1 1 1 1>;
  3454. + qcom,gpio-no-mux = <0>;
  3455. + pinctrl-names = "cam_default", "cam_suspend";
  3456. + pinctrl-0 = <&cam_sensor_mclk1_active
  3457. + &cam_sensor_front_active>;
  3458. + pinctrl-1 = <&cam_sensor_mclk1_suspend
  3459. + &cam_sensor_front_suspend>;
  3460. + gpios = <&tlmm 14 0>,
  3461. + <&tlmm 27 0>,
  3462. + <&tlmm 28 0>,
  3463. + <&pm8998_gpios 9 0>;
  3464. + qcom,gpio-standby = <1>;
  3465. + qcom,gpio-reset = <2>;
  3466. + qcom,gpio-vdig = <3>;
  3467. + qcom,gpio-req-tbl-num = <0 1 2 3>;
  3468. + qcom,gpio-req-tbl-flags = <1 0 0 0>;
  3469. + qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  3470. + "CAM_STANDBY1",
  3471. + "CAM_RESET1",
  3472. + "CAM_VDIG";
  3473. + qcom,cci-master = <1>;
  3474. + status = "ok";
  3475. +
  3476. + clocks = <&clock_mmss clk_mclk1_clk_src>,
  3477. + <&clock_mmss clk_mmss_camss_mclk1_clk>;
  3478. + clock-names = "cam_src_clk", "cam_clk";
  3479. + qcom,clock-rates = <24000000 0>;
  3480. + };
  3481. +
  3482. + eeprom3: qcom,eeprom@3 {
  3483. + cell-index = <3>;
  3484. + reg = <0x3>;
  3485. + qcom,eeprom-name = "sagit_imx268_liteon";
  3486. + compatible = "qcom,eeprom";
  3487. + qcom,slave-addr = <0x34>;
  3488. + qcom,i2c-freq-mode = <1>;
  3489. + qcom,num-blocks = <4>;
  3490. + qcom,saddr0 = <0x34>;
  3491. + qcom,page0 = <1 0x0A02 2 0x00 1 0>;
  3492. + qcom,pageen0 = <1 0x0A00 2 0x01 1 0>;
  3493. + qcom,poll0 = <0 0x0 0 0x0 0 0>;
  3494. + qcom,mem0 = <64 0x0A04 2 0 1 0>;
  3495. +
  3496. + qcom,saddr1 = <0x34>;
  3497. + qcom,page1 = <1 0x0A02 2 0x01 1 0>;
  3498. + qcom,pageen1 = <1 0x0A00 2 0x01 1 0>;
  3499. + qcom,poll1 = <0 0x0 0 0x0 0 0>;
  3500. + qcom,mem1 = <64 0x0A04 2 0 1 0>;
  3501. +
  3502. + qcom,saddr2 = <0x34>;
  3503. + qcom,page2 = <1 0x0A02 2 0x02 1 0>;
  3504. + qcom,pageen2 = <1 0x0A00 2 0x01 1 0>;
  3505. + qcom,poll2 = <0 0x0 0 0x0 0 0>;
  3506. + qcom,mem2 = <64 0x0A04 2 0 1 0>;
  3507. +
  3508. + qcom,saddr3 = <0x34>;
  3509. + qcom,page3 = <1 0x0A02 2 0x03 1 0>;
  3510. + qcom,pageen3 = <0 0x0A00 2 0x01 1 0>;
  3511. + qcom,poll3 = <0 0x0 0 0x0 0 0>;
  3512. + qcom,mem3 = <64 0x0A04 2 0 1 0>;
  3513. +
  3514. + cam_vio-supply = <&pm8998_lvs1>;
  3515. + cam_vana-supply = <&pm8998_l22>;
  3516. + qcom,cam-vreg-name = "cam_vio", "cam_vana";
  3517. + qcom,cam-vreg-min-voltage = <0 2864000>;
  3518. + qcom,cam-vreg-max-voltage = <0 2864000>;
  3519. + qcom,cam-vreg-op-mode = <0 80000>;
  3520. + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_gpio", "sensor_vreg", "sensor_vreg", "sensor_clk", "sensor_gpio", "sensor_gpio";
  3521. + qcom,cam-power-seq-val = "sensor_gpio_reset","sensor_gpio_standby", "sensor_gpio_vdig", "cam_vio", "cam_vana", "sensor_cam_mclk", "sensor_gpio_reset","sensor_gpio_standby";
  3522. + qcom,cam-power-seq-cfg-val = <0 0 1 1 2864000 24000000 1 1>;
  3523. + qcom,cam-power-seq-delay = <1 1 1 1 1 1 1 1>;
  3524. + qcom,gpio-no-mux = <0>;
  3525. + pinctrl-names = "cam_default", "cam_suspend";
  3526. + pinctrl-0 = <&cam_sensor_mclk1_active
  3527. + &cam_sensor_front_active>;
  3528. + pinctrl-1 = <&cam_sensor_mclk1_suspend
  3529. + &cam_sensor_front_suspend>;
  3530. + gpios = <&tlmm 14 0>,
  3531. + <&tlmm 27 0>,
  3532. + <&tlmm 28 0>,
  3533. + <&pm8998_gpios 9 0>;
  3534. + qcom,gpio-standby = <1>;
  3535. + qcom,gpio-reset = <2>;
  3536. + qcom,gpio-vdig = <3>;
  3537. + qcom,gpio-req-tbl-num = <0 1 2 3>;
  3538. + qcom,gpio-req-tbl-flags = <1 0 0 0>;
  3539. + qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  3540. + "CAM_STANDBY1",
  3541. + "CAM_RESET1",
  3542. + "CAM_VDIG";
  3543. + qcom,cci-master = <1>;
  3544. + status = "ok";
  3545. +
  3546. + clocks = <&clock_mmss clk_mclk1_clk_src>,
  3547. + <&clock_mmss clk_mmss_camss_mclk1_clk>;
  3548. + clock-names = "cam_src_clk", "cam_clk";
  3549. + qcom,clock-rates = <24000000 0>;
  3550. + };
  3551. +
  3552. + qcom,camera@0 {
  3553. + cell-index = <0>;
  3554. + compatible = "qcom,camera";
  3555. + reg = <0x0>;
  3556. + qcom,csiphy-sd-index = <0>;
  3557. + qcom,csid-sd-index = <0>;
  3558. + qcom,mount-angle = <90>;
  3559. + qcom,led-flash-src = <&led_flash0>;
  3560. + qcom,actuator-src = <&actuator0>;
  3561. + qcom,eeprom-src = <&eeprom0>;
  3562. + qcom,ois-src = <&ois0>;
  3563. + cam_vio-supply = <&pm8998_lvs1>;
  3564. + cam_vdig-supply = <&vdig_gpio_supply>;
  3565. + cam_vana-supply = <&vana_gpio_supply>;
  3566. + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana";
  3567. + qcom,cam-vreg-min-voltage = <0 1000000 2600000>;
  3568. + qcom,cam-vreg-max-voltage = <0 1200000 2900000>;
  3569. + qcom,cam-vreg-op-mode = <0 1100000 2800000>;
  3570. + qcom,gpio-no-mux = <0>;
  3571. + pinctrl-names = "cam_default", "cam_suspend";
  3572. + pinctrl-0 = <&cam_sensor_mclk0_active
  3573. + &cam_sensor_rear_active>;
  3574. + pinctrl-1 = <&cam_sensor_mclk0_suspend
  3575. + &cam_sensor_rear_suspend>;
  3576. + gpios = <&tlmm 13 0>,
  3577. + <&tlmm 30 0>;
  3578. + qcom,gpio-reset = <1>;
  3579. + qcom,gpio-req-tbl-num = <0 1>;
  3580. + qcom,gpio-req-tbl-flags = <1 0>;
  3581. + qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
  3582. + "CAM_RESET0";
  3583. + qcom,sensor-position = <0>;
  3584. + qcom,sensor-mode = <0>;
  3585. + qcom,cci-master = <0>;
  3586. + status = "ok";
  3587. + clocks = <&clock_mmss clk_mclk0_clk_src>,
  3588. + <&clock_mmss clk_mmss_camss_mclk0_clk>;
  3589. + clock-names = "cam_src_clk", "cam_clk";
  3590. + qcom,clock-rates = <24000000 0>;
  3591. + };
  3592. +
  3593. + qcom,camera@1 {
  3594. + cell-index = <1>;
  3595. + compatible = "qcom,camera";
  3596. + reg = <0x1>;
  3597. + qcom,csiphy-sd-index = <2>;
  3598. + qcom,csid-sd-index = <2>;
  3599. + qcom,mount-angle = <90>;
  3600. + qcom,led-flash-src = <&led_flash0>;
  3601. + qcom,actuator-src = <&actuator1>;
  3602. + qcom,eeprom-src = <&eeprom1>;
  3603. + cam_vio-supply = <&pm8998_lvs1>;
  3604. + cam_vdig-supply = <&vdig_gpio_supply>;
  3605. + cam_vana-supply = <&vana_gpio_supply>;
  3606. + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vana";
  3607. + qcom,cam-vreg-min-voltage = <0 1000000 2800000>;
  3608. + qcom,cam-vreg-max-voltage = <0 1100000 2800000>;
  3609. + qcom,cam-vreg-op-mode = <0 1100000 2800000>;
  3610. + qcom,gpio-no-mux = <0>;
  3611. + pinctrl-names = "cam_default", "cam_suspend";
  3612. + pinctrl-0 = <&cam_sensor_mclk2_active
  3613. + &cam_sensor_rear2_active>;
  3614. + pinctrl-1 = <&cam_sensor_mclk2_suspend
  3615. + &cam_sensor_rear2_suspend>;
  3616. + gpios = <&tlmm 15 0>,
  3617. + <&tlmm 9 0>;
  3618. + qcom,gpio-reset = <1>;
  3619. + qcom,gpio-req-tbl-num = <0 1>;
  3620. + qcom,gpio-req-tbl-flags = <1 0>;
  3621. + qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
  3622. + "CAM_RESET2";
  3623. + qcom,sensor-position = <0>;
  3624. + qcom,sensor-mode = <0>;
  3625. + qcom,cci-master = <1>;
  3626. + status = "ok";
  3627. + clocks = <&clock_mmss clk_mclk2_clk_src>,
  3628. + <&clock_mmss clk_mmss_camss_mclk2_clk>;
  3629. + clock-names = "cam_src_clk", "cam_clk";
  3630. + qcom,clock-rates = <24000000 0>;
  3631. + };
  3632. +
  3633. + qcom,camera@2 {
  3634. + cell-index = <2>;
  3635. + compatible = "qcom,camera";
  3636. + reg = <0x02>;
  3637. + qcom,csiphy-sd-index = <1>;
  3638. + qcom,csid-sd-index = <1>;
  3639. + qcom,mount-angle = <270>;
  3640. + qcom,eeprom-src = <&eeprom2 &eeprom3>;
  3641. + cam_vio-supply = <&pm8998_lvs1>;
  3642. + cam_vana-supply = <&pm8998_l22>;
  3643. + qcom,cam-vreg-name = "cam_vio", "cam_vana";
  3644. + qcom,cam-vreg-min-voltage =
  3645. + <0 2864000>;
  3646. + qcom,cam-vreg-max-voltage =
  3647. + <0 2864000>;
  3648. + qcom,cam-vreg-op-mode = <0 80000>;
  3649. + qcom,gpio-no-mux = <0>;
  3650. + pinctrl-names = "cam_default", "cam_suspend";
  3651. + pinctrl-0 = <&cam_sensor_mclk1_active
  3652. + &cam_sensor_front_active>;
  3653. + pinctrl-1 = <&cam_sensor_mclk1_suspend
  3654. + &cam_sensor_front_suspend>;
  3655. + gpios = <&tlmm 14 0>,
  3656. + <&tlmm 27 0>,
  3657. + <&tlmm 28 0>,
  3658. + <&pm8998_gpios 9 0>;
  3659. + qcom,gpio-standby = <1>;
  3660. + qcom,gpio-reset = <2>;
  3661. + qcom,gpio-vdig = <3>;
  3662. + qcom,gpio-req-tbl-num = <0 1 2 3>;
  3663. + qcom,gpio-req-tbl-flags = <1 0 0 0>;
  3664. + qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
  3665. + "CAM_STANDBY1",
  3666. + "CAM_RESET1",
  3667. + "CAM_VDIG";
  3668. + qcom,sensor-position = <1>;
  3669. + qcom,sensor-mode = <0>;
  3670. + qcom,cci-master = <1>;
  3671. + status = "ok";
  3672. + clocks = <&clock_mmss clk_mclk1_clk_src>,
  3673. + <&clock_mmss clk_mmss_camss_mclk1_clk>;
  3674. + clock-names = "cam_src_clk", "cam_clk";
  3675. + qcom,clock-rates = <24000000 0>;
  3676. + };
  3677. +};
  3678. +&pm8998_gpios {
  3679. + gpio@c800 { /* GPIO 9 - CAMERA SENSOR 2 VDIG */
  3680. + qcom,mode = <1>; /* Output */
  3681. + qcom,pull = <5>; /* No Pull */
  3682. + qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
  3683. + qcom,src-sel = <0>; /* GPIO */
  3684. + qcom,invert = <0>; /* Invert */
  3685. + qcom,master-en = <1>; /* Enable GPIO */
  3686. + status = "ok";
  3687. + };
  3688. +
  3689. + gpio@d300 { /* GPIO 20 - CAMERA SENSOR 0 VDIG */
  3690. + qcom,mode = <1>; /* Output */
  3691. + qcom,pull = <5>; /* No Pull */
  3692. + qcom,vin-sel = <1>; /* VIN1 GPIO_MV */
  3693. + qcom,src-sel = <0>; /* GPIO */
  3694. + qcom,invert = <0>; /* Invert */
  3695. + qcom,master-en = <1>; /* Enable GPIO */
  3696. + status = "ok";
  3697. + };
  3698. +};
  3699. diff --git a/arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dts b/arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dts
  3700. new file mode 100644
  3701. index 0000000..acf0942
  3702. --- /dev/null
  3703. +++ b/arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dts
  3704. @@ -0,0 +1,39 @@
  3705. +/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
  3706. + * Copyright (C) 2017 XiaoMi, Inc.
  3707. + *
  3708. + * This program is free software; you can redistribute it and/or modify
  3709. + * it under the terms of the GNU General Public License version 2 and
  3710. + * only version 2 as published by the Free Software Foundation.
  3711. + *
  3712. + * This program is distributed in the hope that it will be useful,
  3713. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3714. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3715. + * GNU General Public License for more details.
  3716. + */
  3717. +
  3718. +
  3719. +/dts-v1/;
  3720. +
  3721. +#include "msm8998.dtsi"
  3722. +#include "sagit-msm8998-mtp.dtsi"
  3723. +
  3724. +/ {
  3725. + model = "Qualcomm Technologies, Inc. MSM 8998 v1 MTP";
  3726. + compatible = "qcom,msm8998-mtp", "qcom,msm8998", "qcom,mtp";
  3727. + qcom,board-id = <30 0>;
  3728. +};
  3729. +
  3730. +&qusb_phy0 {
  3731. + qcom,qusb-phy-host-init-seq =
  3732. + /* value reg_offsets> */
  3733. + <0x63 0x210
  3734. + 0x13 0x04
  3735. + 0x7c 0x18c
  3736. + 0x80 0x2c
  3737. + 0x0a 0x184
  3738. + 0x8c 0x21c
  3739. + 0x05 0x23c
  3740. + 0x03 0x240
  3741. + 0xff 0x218
  3742. + 0x62 0x210>;
  3743. +};
  3744. diff --git a/arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dtsi b/arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dtsi
  3745. new file mode 100644
  3746. index 0000000..92c3252
  3747. --- /dev/null
  3748. +++ b/arch/arm/boot/dts/qcom/sagit-msm8998-mtp.dtsi
  3749. @@ -0,0 +1,944 @@
  3750. +/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
  3751. + * Copyright (C) 2017 XiaoMi, Inc.
  3752. + *
  3753. + * This program is free software; you can redistribute it and/or modify
  3754. + * it under the terms of the GNU General Public License version 2 and
  3755. + * only version 2 as published by the Free Software Foundation.
  3756. + *
  3757. + * This program is distributed in the hope that it will be useful,
  3758. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3759. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3760. + * GNU General Public License for more details.
  3761. + */
  3762. +
  3763. +#include <dt-bindings/interrupt-controller/irq.h>
  3764. +#include "msm8998-pinctrl.dtsi"
  3765. +#include "sagit-camera-sensor-mtp.dtsi"
  3766. +/ {
  3767. + bluetooth: bt_wcn3990 {
  3768. + compatible = "qca,wcn3990";
  3769. + qca,bt-vdd-io-supply = <&pm8998_s3>;
  3770. + qca,bt-vdd-xtal-supply = <&pm8998_s5>;
  3771. + qca,bt-vdd-core-supply = <&pm8998_l7>;
  3772. + qca,bt-vdd-pa-supply = <&pm8998_l17>;
  3773. + qca,bt-vdd-ldo-supply = <&pm8998_l25>;
  3774. + qca,bt-chip-pwd-supply = <&pmi8998_bob_pin1>;
  3775. + clocks = <&clock_gcc clk_rf_clk2_pin>;
  3776. + clock-names = "rf_clk2";
  3777. +
  3778. + qca,bt-vdd-io-voltage-level = <1352000 1352000>;
  3779. + qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
  3780. + qca,bt-vdd-core-voltage-level = <1800000 1800000>;
  3781. + qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
  3782. + qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
  3783. + qca,bt-chip-pwd-voltage-level = <3600000 3600000>;
  3784. +
  3785. + qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
  3786. + qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
  3787. + qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
  3788. + qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
  3789. + qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
  3790. + };
  3791. +};
  3792. +
  3793. +&blsp1_uart3_hs {
  3794. + status = "ok";
  3795. +};
  3796. +
  3797. +&ufsphy1 {
  3798. + vdda-phy-supply = <&pm8998_l1>;
  3799. + vdda-pll-supply = <&pm8998_l2>;
  3800. + vddp-ref-clk-supply = <&pm8998_l26>;
  3801. + vdda-phy-max-microamp = <51400>;
  3802. + vdda-pll-max-microamp = <14600>;
  3803. + vddp-ref-clk-max-microamp = <100>;
  3804. + vddp-ref-clk-always-on;
  3805. + status = "ok";
  3806. +};
  3807. +
  3808. +&ufs1 {
  3809. + vdd-hba-supply = <&gdsc_ufs>;
  3810. + vdd-hba-fixed-regulator;
  3811. + vcc-supply = <&pm8998_l20>;
  3812. + vccq-supply = <&pm8998_l26>;
  3813. + vccq2-supply = <&pm8998_s4>;
  3814. + vcc-max-microamp = <750000>;
  3815. + vccq-max-microamp = <560000>;
  3816. + vccq2-max-microamp = <750000>;
  3817. + status = "ok";
  3818. +};
  3819. +
  3820. +&ufs_ice {
  3821. + status = "ok";
  3822. +};
  3823. +
  3824. +&sdhc_2 {
  3825. + vdd-supply = <&pm8998_l21>;
  3826. + qcom,vdd-voltage-level = <2950000 2960000>;
  3827. + qcom,vdd-current-level = <200 800000>;
  3828. +
  3829. + vdd-io-supply = <&pm8998_l13>;
  3830. + qcom,vdd-io-voltage-level = <1808000 2960000>;
  3831. + qcom,vdd-io-current-level = <200 22000>;
  3832. +
  3833. + pinctrl-names = "active", "sleep";
  3834. + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
  3835. + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
  3836. +
  3837. + qcom,clk-rates = <400000 20000000 25000000
  3838. + 50000000 100000000 200000000>;
  3839. + qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
  3840. +
  3841. + cd-gpios = <&tlmm 95 0x1>;
  3842. +
  3843. + status = "ok";
  3844. +};
  3845. +
  3846. +&uartblsp2dm1 {
  3847. + status = "ok";
  3848. + pinctrl-names = "default";
  3849. + pinctrl-0 = <&uart_console_active>;
  3850. +};
  3851. +
  3852. +&pm8998_gpios {
  3853. + /* GPIO 6 for Vol+ Key */
  3854. + gpio@c500 {
  3855. + status = "okay";
  3856. + qcom,mode = <0>;
  3857. + qcom,pull = <0>;
  3858. + qcom,vin-sel = <0>;
  3859. + qcom,src-sel = <0>;
  3860. + qcom,out-strength = <1>;
  3861. + };
  3862. +
  3863. + /* GPIO 7 for Snapshot Key */
  3864. + gpio@c600 {
  3865. + status = "okay";
  3866. + qcom,mode = <0>;
  3867. + qcom,pull = <0>;
  3868. + qcom,vin-sel = <0>;
  3869. + qcom,src-sel = <0>;
  3870. + qcom,out-strength = <1>;
  3871. + };
  3872. +
  3873. + /* GPIO 8 for Focus Key */
  3874. + gpio@c700 {
  3875. + status = "okay";
  3876. + qcom,mode = <0>;
  3877. + qcom,pull = <0>;
  3878. + qcom,vin-sel = <0>;
  3879. + qcom,src-sel = <0>;
  3880. + qcom,out-strength = <1>;
  3881. + };
  3882. +
  3883. + gpio@cc00 { /* GPIO 13 */
  3884. + qcom,mode = <1>;
  3885. + qcom,output-type = <0>;
  3886. + qcom,pull = <5>;
  3887. + qcom,vin-sel = <0>;
  3888. + qcom,out-strength = <1>;
  3889. + qcom,src-sel = <3>;
  3890. + qcom,master-en = <1>;
  3891. + status = "okay";
  3892. + };
  3893. +
  3894. + /* GPIO 21 (NFC_CLK_REQ) */
  3895. + gpio@d400 {
  3896. + qcom,mode = <0>;
  3897. + qcom,vin-sel = <1>;
  3898. + qcom,src-sel = <0>;
  3899. + qcom,master-en = <1>;
  3900. + status = "okay";
  3901. + };
  3902. +
  3903. + /* GPIO 18 SMB138X */
  3904. + gpio@d100 {
  3905. + qcom,mode = <0>;
  3906. + qcom,pull = <0>;
  3907. + qcom,vin-sel = <0>;
  3908. + qcom,src-sel = <0>;
  3909. + qcom,master-en = <1>;
  3910. + status = "okay";
  3911. + };
  3912. +};
  3913. +
  3914. +&pmi8998_gpios {
  3915. + /* GPIO 3 for NS5S1153 AUDIO_SEL pin */
  3916. + gpio@c200 {
  3917. + status = "okay";
  3918. + qcom,mode = <1>; /* Digital out */
  3919. + qcom,pull = <5>; /* No pull */
  3920. + qcom,vin-sel = <1>; /* 1.8v */
  3921. + qcom,src-sel = <0>;
  3922. + qcom,out-strength = <1>;
  3923. + qcom,master-en = <1>;
  3924. + };
  3925. +
  3926. + /* GPIO 5 for INFARED_DRV */
  3927. + gpio@c400 {
  3928. + status = "okay";
  3929. + qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
  3930. + qcom,pull = <4>; /*PULL DOWN 10uA*/
  3931. + qcom,src-sel = <2>; /*SPECIAL FUNCTION 1*/
  3932. + qcom,master-en = <1>; /*ENABLE GPIO*/
  3933. + qcom,out-strength = <2>; /*Medium strength current*/
  3934. + };
  3935. +
  3936. + /* GPIO 6 for the internal QNOVO discharge FET control signal */
  3937. + gpio@c500 {
  3938. + status = "okay";
  3939. + qcom,mode = <1>;
  3940. + qcom,pull = <5>;
  3941. + qcom,vin-sel = <0>;
  3942. + qcom,src-sel = <2>;
  3943. + qcom,out-strength = <1>;
  3944. + qcom,master-en = <1>;
  3945. + };
  3946. +};
  3947. +
  3948. +&i2c_5 {
  3949. + status = "okay";
  3950. + synaptics_dsi_i2c@20 {
  3951. + compatible = "synaptics,dsx-i2c-force";
  3952. + reg = <0x20>;
  3953. + interrupt-parent = <&tlmm>;
  3954. + interrupts = <125 0x2008>;
  3955. + vdd-supply = <&pm8998_l6>;
  3956. + lab-supply = <&lab_regulator>;
  3957. + ibb-supply = <&ibb_regulator>;
  3958. + disp-supply = <&pm8998_l14>;
  3959. + avdd-supply = <&disp_vddts_vreg>;
  3960. + synaptics,pwr-reg-name = "vdd";
  3961. + synaptics,lab-reg-name = "lab";
  3962. + synaptics,ibb-reg-name = "ibb";
  3963. + synaptics,disp-reg-name = "disp";
  3964. + synaptics,bus-reg-name = "avdd";
  3965. + synaptics,ub-i2c-addr = <0x2c>;
  3966. + pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
  3967. + pinctrl-0 = <&ts_active>;
  3968. + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
  3969. + synaptics,mdss-dsi-reset = <&tlmm 8 0>;
  3970. + synaptics,reset-gpio = <&tlmm 89 0x00>;
  3971. + synaptics,irq-gpio = <&tlmm 125 0x2008>;
  3972. + synaptics,reset-gpio-name = "dsx_reset";
  3973. + synaptics,irq-gpio-name = "dsx_irq";
  3974. + synaptics,irq-on-state = <0>;
  3975. + synaptics,irq-flags = <0x2008>; /* IRQF_ONESHOT | IRQF_TRIGGER_LOW */
  3976. + synaptics,power-delay-ms = <5>;
  3977. + synaptics,reset-delay-ms = <200>;
  3978. + synaptics,reset-active-ms = <5>;
  3979. + synaptics,power-on-state = <1>;
  3980. + synaptics,reset-on-state = <0>;
  3981. + synaptics,mdss-reset-state = <1>;
  3982. + synaptics,panel-is-incell;
  3983. + synaptics,cap-button-codes = <158 139 102>;
  3984. + synaptics,short-jdi-25 = "000: 0xfb\n001: 0xef\n002: 0xff\n003: 0xff\n004: 0x18\n005: 0x00\n006: 0x00";
  3985. + synaptics,short-jdi-26 = "000: 0x03\n001: 0x00\n002: 0x00\n003: 0x00\n004: 0x00\n005: 0x00\n006: 0x00";
  3986. + clock-names = "iface_clk", "core_clk";
  3987. + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
  3988. + <&clock_gcc clk_gcc_blsp1_qup5_i2c_apps_clk>;
  3989. + synaptics,guest-serialization-as-lockdown;
  3990. + synaptics,tp-id-byte = /bits/ 8 <0>;
  3991. + synaptics,config-array-size = <3>;
  3992. + synaptics,cfg_1 {
  3993. + synaptics,chip-id = <0>;
  3994. + synaptics,chip-id-name = "S3330";
  3995. + synaptics,tp-id = /bits/ 8 <0x31>;
  3996. + synaptics,fw-name = "synaptics_jdi_3330_c1.fw";
  3997. + };
  3998. + synaptics,cfg_2 {
  3999. + synaptics,chip-id = <1>;
  4000. + synaptics,chip-id-name = "S3331";
  4001. + synaptics,tp-id = /bits/ 8 <0x31>;
  4002. + synaptics,fw-name = "synaptics_jdi_3331_c1.fw";
  4003. + };
  4004. + synaptics,cfg_3 {
  4005. + synaptics,chip-id = <2>;
  4006. + synaptics,chip-id-name = "TD4322";
  4007. + synaptics,chip-is-tddi;
  4008. + synaptics,disp-pre-on-sleep = <10>;
  4009. + synaptics,disp-post-on-sleep = <10>;
  4010. + synaptics,disp-pre-off-sleep = <10>;
  4011. + synaptics,disp-post-off-sleep = <0>;
  4012. + synaptics,lab-pre-on-sleep = <0>;
  4013. + synaptics,lab-post-on-sleep = <10>;
  4014. + synaptics,lab-pre-off-sleep = <10>;
  4015. + synaptics,lab-post-off-sleep = <0>;
  4016. + synaptics,ibb-pre-on-sleep = <0>;
  4017. + synaptics,ibb-post-on-sleep = <10>;
  4018. + synaptics,ibb-pre-off-sleep = <10>;
  4019. + synaptics,ibb-post-off-sleep = <0>;
  4020. + synaptics,tp-id = /bits/ 8 <0x34>;
  4021. + synaptics,fw-name = "synaptics_lgd_4322_c1.fw";
  4022. + };
  4023. + };
  4024. +};
  4025. +
  4026. +&i2c_6 { /* BLSP1 QUP6 (NFC) */
  4027. + status = "okay";
  4028. + nq@28 {
  4029. + compatible = "qcom,nq-nci";
  4030. + reg = <0x28>;
  4031. + qcom,nq-irq = <&tlmm 92 0x00>;
  4032. + qcom,nq-ven = <&tlmm 12 0x00>;
  4033. + qcom,nq-firm = <&tlmm 93 0x00>;
  4034. + qcom,nq-clkreq = <&pm8998_gpios 21 0x00>;
  4035. + qcom,nq-esepwr = <&tlmm 116 0x00>;
  4036. + interrupt-parent = <&tlmm>;
  4037. + qcom,clk-src = "BBCLK3";
  4038. + interrupts = <92 0>;
  4039. + interrupt-names = "nfc_irq";
  4040. + pinctrl-names = "nfc_active", "nfc_suspend";
  4041. + pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
  4042. + pinctrl-1 = <&nfc_int_suspend &nfc_enable_suspend>;
  4043. + clocks = <&clock_gcc clk_ln_bb_clk3_pin>;
  4044. + clock-names = "ref_clk";
  4045. + };
  4046. +};
  4047. +
  4048. +&i2c_10 { /* BLSP2 QUP4 (Speaker Smart PA)*/
  4049. + status = "okay";
  4050. + tfa98xx@34 {
  4051. + compatible = "nxp,tfa98xx";
  4052. + reg = <0x34>;
  4053. + reset-gpio = <&tlmm 41 0>;
  4054. + irq-gpio = <&tlmm 42 0>;
  4055. + spk-id = <&spk_id_pin>;
  4056. + };
  4057. +};
  4058. +
  4059. +&mdss_hdmi_tx {
  4060. + status = "disabled";
  4061. + pinctrl-names = "hdmi_hpd_active", "hdmi_ddc_active", "hdmi_cec_active",
  4062. + "hdmi_active", "hdmi_sleep";
  4063. + pinctrl-0 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
  4064. + &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>;
  4065. + pinctrl-1 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
  4066. + &mdss_hdmi_ddc_active &mdss_hdmi_cec_suspend>;
  4067. + pinctrl-2 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
  4068. + &mdss_hdmi_cec_active &mdss_hdmi_ddc_suspend>;
  4069. + pinctrl-3 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
  4070. + &mdss_hdmi_ddc_active &mdss_hdmi_cec_active>;
  4071. + pinctrl-4 = <&mdss_hdmi_5v_suspend &mdss_hdmi_hpd_suspend
  4072. + &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>;
  4073. +};
  4074. +
  4075. +&mdss_hdmi_pll {
  4076. + status = "disabled";
  4077. +};
  4078. +
  4079. +&mdss_mdp {
  4080. + qcom,mdss-pref-prim-intf = "dsi";
  4081. +};
  4082. +
  4083. +&mdss_dsi {
  4084. + hw-config = "single_dsi";
  4085. +};
  4086. +
  4087. +&mdss_dsi0 {
  4088. + qcom,dsi-pref-prim-pan = <&dsi_jdi_fhd_r63452_cmd>;
  4089. + pinctrl-names = "mdss_default", "mdss_sleep";
  4090. + pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
  4091. + pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
  4092. + qcom,platform-reset-gpio = <&tlmm 94 0>;
  4093. + qcom,platform-te-gpio = <&tlmm 10 0>;
  4094. + qcom,panel-mode-gpio = <&tlmm 91 0>;
  4095. +};
  4096. +
  4097. +&mdss_dsi1 {
  4098. + status = "disabled";
  4099. +};
  4100. +
  4101. +&mdss_dsi1_pll {
  4102. + status = "disabled";
  4103. +};
  4104. +
  4105. +&labibb {
  4106. + status = "ok";
  4107. + qcom,qpnp-labibb-mode = "lcd";
  4108. +};
  4109. +
  4110. +&dsi_dual_nt35597_video {
  4111. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4112. + qcom,mdss-dsi-bl-min-level = <1>;
  4113. + qcom,mdss-dsi-bl-max-level = <4095>;
  4114. + qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
  4115. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4116. +};
  4117. +
  4118. +&dsi_dual_nt35597_cmd {
  4119. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4120. + qcom,mdss-dsi-bl-min-level = <1>;
  4121. + qcom,mdss-dsi-bl-max-level = <4095>;
  4122. + qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
  4123. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4124. +};
  4125. +
  4126. +&dsi_dual_nt35597_truly_video {
  4127. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4128. + qcom,mdss-dsi-bl-min-level = <1>;
  4129. + qcom,mdss-dsi-bl-max-level = <4095>;
  4130. + qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
  4131. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4132. +};
  4133. +
  4134. +&dsi_dual_nt35597_truly_cmd {
  4135. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4136. + qcom,mdss-dsi-bl-min-level = <1>;
  4137. + qcom,mdss-dsi-bl-max-level = <4095>;
  4138. + qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
  4139. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4140. +};
  4141. +
  4142. +&dsi_nt35597_dsc_video {
  4143. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4144. + qcom,mdss-dsi-bl-min-level = <1>;
  4145. + qcom,mdss-dsi-bl-max-level = <4095>;
  4146. + qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
  4147. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4148. +};
  4149. +
  4150. +&dsi_nt35597_dsc_cmd {
  4151. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4152. + qcom,mdss-dsi-bl-min-level = <1>;
  4153. + qcom,mdss-dsi-bl-max-level = <4095>;
  4154. + qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
  4155. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4156. +};
  4157. +
  4158. +&dsi_sharp_4k_dsc_video {
  4159. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4160. + qcom,mdss-dsi-bl-min-level = <1>;
  4161. + qcom,mdss-dsi-bl-max-level = <4095>;
  4162. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4163. +};
  4164. +
  4165. +&dsi_sharp_4k_dsc_cmd {
  4166. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4167. + qcom,mdss-dsi-bl-min-level = <1>;
  4168. + qcom,mdss-dsi-bl-max-level = <4095>;
  4169. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4170. +};
  4171. +
  4172. +&dsi_dual_jdi_video {
  4173. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4174. + qcom,mdss-dsi-bl-min-level = <1>;
  4175. + qcom,mdss-dsi-bl-max-level = <4095>;
  4176. + qcom,5v-boost-gpio = <&tlmm 51 0>;
  4177. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4178. +};
  4179. +
  4180. +&dsi_dual_jdi_cmd {
  4181. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4182. + qcom,mdss-dsi-bl-min-level = <1>;
  4183. + qcom,mdss-dsi-bl-max-level = <4095>;
  4184. + qcom,5v-boost-gpio = <&tlmm 51 0>;
  4185. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4186. +};
  4187. +
  4188. +&dsi_jdi_fhd_r63452_cmd {
  4189. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4190. + qcom,mdss-dsi-bl-min-level = <1>;
  4191. + qcom,mdss-dsi-bl-max-level = <4095>;
  4192. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4193. +};
  4194. +
  4195. +&dsi_lgd_fhd_td4322_cmd {
  4196. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4197. + qcom,mdss-dsi-bl-min-level = <1>;
  4198. + qcom,mdss-dsi-bl-max-level = <4095>;
  4199. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply_lgd_td4322>;
  4200. +};
  4201. +
  4202. +&dsi_dual_sharp_1080_120hz_cmd {
  4203. + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
  4204. + qcom,mdss-dsi-bl-min-level = <1>;
  4205. + qcom,mdss-dsi-bl-max-level = <4095>;
  4206. + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
  4207. +};
  4208. +
  4209. +&mem_client_3_size {
  4210. + qcom,peripheral-size = <0x500000>;
  4211. +};
  4212. +
  4213. +&pmi8998_haptics {
  4214. + status = "okay";
  4215. + qcom,wave-play-rate-us = <5000>;
  4216. + qcom,vmax-mv = <3248>;
  4217. + qcom,wave-shape = "sine";
  4218. + qcom,brake-pattern = [03 02 00 00];
  4219. + qcom,brake-pattern-count = <9>;
  4220. + qcom,disable_force_back_emf_delay;
  4221. + qcom,vmax-overbrake-mv = <3596>;
  4222. + qcom,brake-pattern-arry = [03 00 00 00
  4223. + 03 02 00 00
  4224. + 03 03 01 00
  4225. + 03 03 02 01
  4226. + 03 03 03 02
  4227. + 03 03 03 02
  4228. + 03 03 03 02
  4229. + 03 03 03 02
  4230. + 03 03 03 03];
  4231. +};
  4232. +
  4233. +&pm8998_vadc {
  4234. + chan@83 {
  4235. + label = "vph_pwr";
  4236. + reg = <0x83>;
  4237. + qcom,decimation = <2>;
  4238. + qcom,pre-div-channel-scaling = <1>;
  4239. + qcom,calibration-type = "absolute";
  4240. + qcom,scale-function = <0>;
  4241. + qcom,hw-settle-time = <0>;
  4242. + qcom,fast-avg-setup = <0>;
  4243. + };
  4244. +
  4245. + chan@85 {
  4246. + label = "vcoin";
  4247. + reg = <0x85>;
  4248. + qcom,decimation = <2>;
  4249. + qcom,pre-div-channel-scaling = <1>;
  4250. + qcom,calibration-type = "absolute";
  4251. + qcom,scale-function = <0>;
  4252. + qcom,hw-settle-time = <0>;
  4253. + qcom,fast-avg-setup = <0>;
  4254. + };
  4255. +
  4256. + chan@4c {
  4257. + label = "xo_therm";
  4258. + reg = <0x4c>;
  4259. + qcom,decimation = <2>;
  4260. + qcom,pre-div-channel-scaling = <0>;
  4261. + qcom,calibration-type = "ratiometric";
  4262. + qcom,scale-function = <4>;
  4263. + qcom,hw-settle-time = <2>;
  4264. + qcom,fast-avg-setup = <0>;
  4265. + };
  4266. +
  4267. + chan@4d {
  4268. + label = "msm_therm";
  4269. + reg = <0x4d>;
  4270. + qcom,decimation = <2>;
  4271. + qcom,pre-div-channel-scaling = <0>;
  4272. + qcom,calibration-type = "ratiometric";
  4273. + qcom,scale-function = <2>;
  4274. + qcom,hw-settle-time = <2>;
  4275. + qcom,fast-avg-setup = <0>;
  4276. + };
  4277. +
  4278. + chan@4e {
  4279. + label = "emmc_therm";
  4280. + reg = <0x4e>;
  4281. + qcom,decimation = <2>;
  4282. + qcom,pre-div-channel-scaling = <0>;
  4283. + qcom,calibration-type = "ratiometric";
  4284. + qcom,scale-function = <2>;
  4285. + qcom,hw-settle-time = <2>;
  4286. + qcom,fast-avg-setup = <0>;
  4287. + };
  4288. +
  4289. + chan@4f {
  4290. + label = "pa_therm0";
  4291. + reg = <0x4f>;
  4292. + qcom,decimation = <2>;
  4293. + qcom,pre-div-channel-scaling = <0>;
  4294. + qcom,calibration-type = "ratiometric";
  4295. + qcom,scale-function = <2>;
  4296. + qcom,hw-settle-time = <2>;
  4297. + qcom,fast-avg-setup = <0>;
  4298. + };
  4299. +
  4300. + chan@50 {
  4301. + label = "pa_therm1";
  4302. + reg = <0x50>;
  4303. + qcom,decimation = <2>;
  4304. + qcom,pre-div-channel-scaling = <0>;
  4305. + qcom,calibration-type = "ratiometric";
  4306. + qcom,scale-function = <2>;
  4307. + qcom,hw-settle-time = <2>;
  4308. + qcom,fast-avg-setup = <0>;
  4309. + };
  4310. +
  4311. + chan@51 {
  4312. + label = "quiet_therm";
  4313. + reg = <0x51>;
  4314. + qcom,decimation = <2>;
  4315. + qcom,pre-div-channel-scaling = <0>;
  4316. + qcom,calibration-type = "ratiometric";
  4317. + qcom,scale-function = <2>;
  4318. + qcom,hw-settle-time = <2>;
  4319. + qcom,fast-avg-setup = <0>;
  4320. + };
  4321. +};
  4322. +
  4323. +&pm8998_adc_tm {
  4324. + chan@83 {
  4325. + label = "vph_pwr";
  4326. + reg = <0x83>;
  4327. + qcom,pre-div-channel-scaling = <1>;
  4328. + qcom,calibration-type = "absolute";
  4329. + qcom,scale-function = <0>;
  4330. + qcom,hw-settle-time = <0>;
  4331. + qcom,btm-channel-number = <0x60>;
  4332. + };
  4333. +
  4334. + chan@4d {
  4335. + label = "msm_therm";
  4336. + reg = <0x4d>;
  4337. + qcom,pre-div-channel-scaling = <0>;
  4338. + qcom,calibration-type = "ratiometric";
  4339. + qcom,scale-function = <2>;
  4340. + qcom,hw-settle-time = <2>;
  4341. + qcom,btm-channel-number = <0x68>;
  4342. + qcom,thermal-node;
  4343. + };
  4344. +
  4345. + chan@4e {
  4346. + label = "emmc_therm";
  4347. + reg = <0x4e>;
  4348. + qcom,pre-div-channel-scaling = <0>;
  4349. + qcom,calibration-type = "ratiometric";
  4350. + qcom,scale-function = <2>;
  4351. + qcom,hw-settle-time = <2>;
  4352. + qcom,btm-channel-number = <0x80>;
  4353. + qcom,thermal-node;
  4354. + };
  4355. +
  4356. + chan@4f {
  4357. + label = "pa_therm0";
  4358. + reg = <0x4f>;
  4359. + qcom,pre-div-channel-scaling = <0>;
  4360. + qcom,calibration-type = "ratiometric";
  4361. + qcom,scale-function = <2>;
  4362. + qcom,hw-settle-time = <2>;
  4363. + qcom,btm-channel-number = <0x88>;
  4364. + qcom,thermal-node;
  4365. + };
  4366. +
  4367. + chan@50 {
  4368. + label = "pa_therm1";
  4369. + reg = <0x50>;
  4370. + qcom,pre-div-channel-scaling = <0>;
  4371. + qcom,calibration-type = "ratiometric";
  4372. + qcom,scale-function = <2>;
  4373. + qcom,hw-settle-time = <2>;
  4374. + qcom,btm-channel-number = <0x90>;
  4375. + qcom,thermal-node;
  4376. + };
  4377. +
  4378. + chan@51 {
  4379. + label = "quiet_therm";
  4380. + reg = <0x51>;
  4381. + qcom,pre-div-channel-scaling = <0>;
  4382. + qcom,calibration-type = "ratiometric";
  4383. + qcom,scale-function = <2>;
  4384. + qcom,hw-settle-time = <2>;
  4385. + qcom,btm-channel-number = <0x70>;
  4386. + qcom,thermal-node;
  4387. + };
  4388. +
  4389. + chan@4c {
  4390. + label = "xo_therm";
  4391. + reg = <0x4c>;
  4392. + qcom,pre-div-channel-scaling = <0>;
  4393. + qcom,calibration-type = "ratiometric";
  4394. + qcom,scale-function = <4>;
  4395. + qcom,hw-settle-time = <2>;
  4396. + qcom,btm-channel-number = <0x78>;
  4397. + qcom,thermal-node;
  4398. + };
  4399. +};
  4400. +
  4401. +&wil6210 {
  4402. + status = "ok";
  4403. +};
  4404. +
  4405. +&slim_aud {
  4406. + tasha_codec {
  4407. + qcom,cdc-micbias1-mv = <2750>;
  4408. + qcom,cdc-micbias2-mv = <1800>;
  4409. + qcom,cdc-micbias3-mv = <1800>;
  4410. + qcom,cdc-micbias4-mv = <2750>;
  4411. + };
  4412. +};
  4413. +
  4414. +&soc {
  4415. + sound-tavil {
  4416. + status = "disabled";
  4417. + };
  4418. +
  4419. + sound-9335 {
  4420. + qcom,audio-routing =
  4421. + "AIF4 VI", "MCLK",
  4422. + "RX_BIAS", "MCLK",
  4423. + "MADINPUT", "MCLK",
  4424. + "AMIC1", "MIC BIAS2",
  4425. + "MIC BIAS2", "Handset Mic",
  4426. + "AMIC2", "MIC BIAS2",
  4427. + "MIC BIAS2", "Headset Mic",
  4428. + "AMIC3", "MIC BIAS1",
  4429. + "MIC BIAS1", "ANCRight Headset Mic",
  4430. + "AMIC4", "MIC BIAS1",
  4431. + "MIC BIAS1", "ANCLeft Headset Mic",
  4432. + "AMIC5", "MIC BIAS4",
  4433. + "MIC BIAS4", "Handset Mic",
  4434. + "AMIC6", "MIC BIAS4",
  4435. + "MIC BIAS4", "Analog Mic6";
  4436. +
  4437. + qcom,wsa-max-devs = <0>;
  4438. + qcom,msm-mbhc-hphl-swh = <1>;
  4439. + qcom,us-euro-gpios = <&wcd_us_euro_gpio>;
  4440. +
  4441. + qcom,asel-gpio = <&pmi8998_gpios 3 0x00>;
  4442. + qcom,hsdet-gpio = <&tlmm 8 0x01>;
  4443. +
  4444. + qcom,spk-id-pin = <&spk_id_pin>;
  4445. + qcom,rcv-id-pin = <&rcv_id_pin>;
  4446. + };
  4447. +
  4448. + spk_id_pin: spk-id-pin@100 {
  4449. + compatible = "audio,speaker-id";
  4450. + audio,speaker-id-gpio = <&tlmm 100 0x00>;
  4451. + pinctrl-names = "pull_down", "pull_up", "no_pull";
  4452. + pinctrl-0 = <&spk_id_pull_down>;
  4453. + pinctrl-1 = <&spk_id_pull_up>;
  4454. + pinctrl-2 = <&spk_id_no_pull>;
  4455. + };
  4456. +
  4457. + rcv_id_pin: rcv-id-pin@11 {
  4458. + compatible = "audio,speaker-id";
  4459. + audio,speaker-id-gpio = <&tlmm 11 0x00>;
  4460. + pinctrl-names = "pull_down", "pull_up", "no_pull";
  4461. + pinctrl-0 = <&rcv_id_pull_down>;
  4462. + pinctrl-1 = <&rcv_id_pull_up>;
  4463. + pinctrl-2 = <&rcv_id_no_pull>;
  4464. + };
  4465. +
  4466. + qcom,msm-dai-mi2s {
  4467. + dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
  4468. + qcom,msm-mi2s-rx-lines = <1>;
  4469. + qcom,msm-mi2s-tx-lines = <2>;
  4470. + pinctrl-names = "default", "sleep";
  4471. + pinctrl-0 = <&quat_mi2s_active
  4472. + &quat_mi2s_sd0_active
  4473. + &quat_mi2s_sd1_active>;
  4474. + pinctrl-1 = <&quat_mi2s_sleep
  4475. + &quat_mi2s_sd0_sleep
  4476. + &quat_mi2s_sd1_sleep>;
  4477. + };
  4478. + };
  4479. +
  4480. + sn_fuse: snfuse@0x786134 {
  4481. + compatible = "qcom,sn-fuse";
  4482. + reg = <0x786134 0x4>;
  4483. + reg-names = "sn-base";
  4484. + };
  4485. +
  4486. + gpio_keys {
  4487. + compatible = "gpio-keys";
  4488. + input-name = "gpio-keys";
  4489. + status = "okay";
  4490. +
  4491. + vol_up {
  4492. + label = "volume_up";
  4493. + gpios = <&pm8998_gpios 6 0x1>;
  4494. + linux,input-type = <1>;
  4495. + linux,code = <115>;
  4496. + gpio-key,wakeup;
  4497. + debounce-interval = <15>;
  4498. + };
  4499. +
  4500. + hall_key0 {
  4501. + label = "hall_key0";
  4502. + gpios = <&tlmm 124 0x01>;
  4503. + linux,input-type = <5>;
  4504. + linux,code = <0>;
  4505. + gpio-key,wakeup;
  4506. + debounce-interval = <15>;
  4507. + };
  4508. + };
  4509. +
  4510. + gpio_rf {
  4511. + pinctrl-names = "tlmm_gpio_rf_active","tlmm_gpio_rf_suspend";
  4512. + pinctrl-0 = <&gpio_rf_active>;
  4513. + pinctrl-1 = <&gpio_rf_suspend>;
  4514. + compatible = "gpio_rf";
  4515. + gpios = <&tlmm 119 0x01>;
  4516. + debounce-interval = <15>;
  4517. + };
  4518. +
  4519. + qcom,msm-dai-mi2s {
  4520. + dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
  4521. + qcom,msm-mi2s-rx-lines = <1>;
  4522. + qcom,msm-mi2s-tx-lines = <2>;
  4523. + pinctrl-names = "default", "sleep";
  4524. + pinctrl-0 = <&quat_mi2s_active
  4525. + &quat_mi2s_sd0_active
  4526. + &quat_mi2s_sd1_active>;
  4527. + pinctrl-1 = <&quat_mi2s_sleep
  4528. + &quat_mi2s_sd0_sleep
  4529. + &quat_mi2s_sd1_sleep>;
  4530. + };
  4531. + };
  4532. + pwm_ir {
  4533. + compatible = "pwm-ir";
  4534. + pwms = <&pmi8998_pwm_2 0 0>;
  4535. + };
  4536. +
  4537. + fingerprint_fpc {
  4538. + status = "ok";
  4539. + compatible = "fpc,fpc1020";
  4540. + interrupt-parent = <&tlmm>;
  4541. + interrupts = <121 0x0>;
  4542. + fpc,gpio_rst = <&tlmm 37 0x0>;
  4543. + fpc,gpio_irq = <&tlmm 121 0x0>;
  4544. + vdd_ana-supply = <&fp_vdd_vreg>;
  4545. + /* fpc,enable-on-boot; */
  4546. + /* fpc,enable-wakeup; */
  4547. +
  4548. + pinctrl-names = "fpc1020_reset_reset",
  4549. + "fpc1020_reset_active",
  4550. + "fpc1020_irq_active";
  4551. +
  4552. + pinctrl-0 = <&msm_gpio_37>;
  4553. + pinctrl-1 = <&msm_gpio_37_output_high>;
  4554. + pinctrl-2 = <&msm_gpio_121>;
  4555. + };
  4556. +
  4557. + fingerprint_goodix {
  4558. + compatible = "goodix,fingerprint";
  4559. + fp-gpio-reset = <&tlmm 37 0>;
  4560. + fp-gpio-irq = <&tlmm 121 0>;
  4561. + pinctrl-names = "pmx_fp_active", "pmx_fp_suspend";
  4562. + pinctrl-0 = <&fp_active>;
  4563. + pinctrl-1 = <&fp_suspend>;
  4564. + clock-names = "iface_clk", "core_clk";
  4565. + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
  4566. + <&clock_gcc clk_gcc_blsp2_qup6_spi_apps_clk>;
  4567. + status = "ok";
  4568. + };
  4569. +};
  4570. +
  4571. +&spi_2 {
  4572. + compatible = "qcom,spi-qup-v2";
  4573. + #address-cells = <1>;
  4574. + #size-cells = <0>;
  4575. + reg-names = "spi_physical", "spi_bam_physical";
  4576. + reg = <0xC176000 0x600>,
  4577. + <0xC144000 0x25000>;
  4578. + interrupt-names = "spi_irq", "spi_bam_irq";
  4579. + interrupts = <0 96 0>, <0 238 0>;
  4580. + spi-max-frequency = <19200000>;
  4581. + qcom,use-bam;
  4582. + qcom,ver-reg-exists;
  4583. + qcom,bam-consumer-pipe-index = <8>;
  4584. + qcom,bam-producer-pipe-index = <9>;
  4585. + qcom,master-id = <86>;
  4586. + qcom,use-pinctrl;
  4587. + pinctrl-names = "spi_default", "spi_sleep";
  4588. + pinctrl-0 = <&spi_2_active>;
  4589. + pinctrl-1 = <&spi_2_sleep>;
  4590. + clock-names = "iface_clk", "core_clk";
  4591. + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
  4592. + <&clock_gcc clk_gcc_blsp1_qup2_spi_apps_clk>;
  4593. + status = "ok";
  4594. + peel_ir@0 {
  4595. + compatible = "peel_ir";
  4596. + reg = <0>;
  4597. + spi-max-frequency = <19200000>;
  4598. + peel_ir,lr-gpio = <73>;
  4599. + peel_ir,lr-gpio-valid = <1>;
  4600. + peel_ir,spi-bpw = <32>;
  4601. + peel_ir,spi-clk-speed= <960000>;
  4602. + peel_ir,spi-mode = <0>;
  4603. + peel_ir,peel-field = <2345>;
  4604. + status = "ok";
  4605. + };
  4606. +};
  4607. +
  4608. +&pcie0 {
  4609. + status = "disabled";
  4610. +};
  4611. +
  4612. +&fp_vdd_vreg {
  4613. + regulator-always-on;
  4614. +};
  4615. +
  4616. +&pmi8998_wled {
  4617. + qcom,led-strings-list = [00 01];
  4618. + qcom,fs-curr-ua = <20000>;
  4619. + qcom,en-cabc;
  4620. +};
  4621. +
  4622. +/* Red led was used for powersupply of White led */
  4623. +&red_led {
  4624. + qcom,start-idx = <1>;
  4625. + qcom,idx-len = <10>;
  4626. + qcom,duty-pcts = [00 19 32 4B 64
  4627. + 64 4B 32 19 00];
  4628. + qcom,lut-flags = <3>;
  4629. + qcom,pause-lo = <0>;
  4630. + qcom,pause-hi = <0>;
  4631. + qcom,ramp-step-ms = <255>;
  4632. + qcom,use-blink;
  4633. + linux,name = "white";
  4634. +};
  4635. +
  4636. +/* Blue led was used for powersupply of left button key backlight */
  4637. +&blue_led {
  4638. + linux,name = "button-backlight";
  4639. +};
  4640. +
  4641. +/* Green led was used for powersupply of right button key backlight */
  4642. +&green_led {
  4643. + linux,name = "button-backlight1";
  4644. +};
  4645. +&pmi8998_charger {
  4646. + qcom,usb-icl-ua = <3000000>;
  4647. + qcom,fcc-max-ua = <3200000>;
  4648. + qcom,auto-recharge-soc;
  4649. +
  4650. + qcom,thermal-mitigation
  4651. + = <1800000 1600000 1400000 1200000 1000000 1000000 1000000>;
  4652. + qcom,thermal-mitigation-dcp
  4653. + = <1800000 1600000 1400000 1200000 1000000 1000000 1000000>;
  4654. + qcom,thermal-mitigation-qc3
  4655. + = <3000000 2425000 2125000 1825000 1525000 1225000 925000>;
  4656. + qcom,thermal-mitigation-qc2
  4657. + = <1600000 1400000 1200000 1000000 900000 900000 900000>;
  4658. +};
  4659. +&pmi8998_fg {
  4660. + qcom,fg-force-load-profile;
  4661. + qcom,fg-sys-term-current = <(-300)>;
  4662. + qcom,fg-chg-term-current = <120>;
  4663. + qcom,fg-auto-recharge-soc;
  4664. + qcom,fg-recharge-soc-thr = <99>;
  4665. + qcom,fg-cutoff-voltage = <3400>;
  4666. + qcom,fg-empty-voltage = <3100>;
  4667. + qcom,fg-jeita-hyst-temp = <0>;
  4668. + qcom,fg-jeita-thresholds = <0 15 45 60>;
  4669. + qcom,fg-esr-clamp-mohms = <60>;
  4670. + qcom,fg-batt-temp-delta = <6>;
  4671. + qcom,hold-soc-while-full;
  4672. +};
  4673. +/{
  4674. + mtp_batterydata: qcom,battery-data {
  4675. + qcom,batt-id-range-pct = <15>;
  4676. + #include "batterydata-c1-atl-3350mAh.dtsi"
  4677. + #include "batterydata-c1-sdi-3440mAh.dtsi"
  4678. + #include "batterydata-itech-3020mAh.dtsi"
  4679. + };
  4680. +};
  4681. +
  4682. +
  4683. +&qusb_phy0 {
  4684. + qcom,qusb-phy-init-seq =
  4685. + /* <value reg_offset> */
  4686. + <0x80 0x0
  4687. + 0x13 0x04
  4688. + 0x7c 0x18c
  4689. + 0x80 0x2c
  4690. + 0x0a 0x184
  4691. + 0xf0 0x23c
  4692. + 0x0d 0x240>;
  4693. +};
  4694. diff --git a/arch/arm/boot/dts/qcom/sagit-msm8998-v2-mtp.dts b/arch/arm/boot/dts/qcom/sagit-msm8998-v2-mtp.dts
  4695. new file mode 100644
  4696. index 0000000..a53954e
  4697. --- /dev/null
  4698. +++ b/arch/arm/boot/dts/qcom/sagit-msm8998-v2-mtp.dts
  4699. @@ -0,0 +1,24 @@
  4700. +/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
  4701. + * Copyright (C) 2017 XiaoMi, Inc.
  4702. + *
  4703. + * This program is free software; you can redistribute it and/or modify
  4704. + * it under the terms of the GNU General Public License version 2 and
  4705. + * only version 2 as published by the Free Software Foundation.
  4706. + *
  4707. + * This program is distributed in the hope that it will be useful,
  4708. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  4709. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  4710. + * GNU General Public License for more details.
  4711. + */
  4712. +
  4713. +
  4714. +/dts-v1/;
  4715. +
  4716. +#include "msm8998-v2.dtsi"
  4717. +#include "sagit-msm8998-mtp.dtsi"
  4718. +
  4719. +/ {
  4720. + model = "Qualcomm Technologies, Inc. MSM 8998 v2 MTP";
  4721. + compatible = "qcom,msm8998-mtp", "qcom,msm8998", "qcom,mtp";
  4722. + qcom,board-id = <30 0>;
  4723. +};
  4724. diff --git a/arch/arm/boot/dts/qcom/sagit-msm8998-v2.1-mtp.dts b/arch/arm/boot/dts/qcom/sagit-msm8998-v2.1-mtp.dts
  4725. new file mode 100644
  4726. index 0000000..aae3991
  4727. --- /dev/null
  4728. +++ b/arch/arm/boot/dts/qcom/sagit-msm8998-v2.1-mtp.dts
  4729. @@ -0,0 +1,24 @@
  4730. +/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
  4731. + * Copyright (C) 2017 XiaoMi, Inc.
  4732. + *
  4733. + * This program is free software; you can redistribute it and/or modify
  4734. + * it under the terms of the GNU General Public License version 2 and
  4735. + * only version 2 as published by the Free Software Foundation.
  4736. + *
  4737. + * This program is distributed in the hope that it will be useful,
  4738. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  4739. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  4740. + * GNU General Public License for more details.
  4741. + */
  4742. +
  4743. +
  4744. +/dts-v1/;
  4745. +
  4746. +#include "msm8998-v2.1.dtsi"
  4747. +#include "sagit-msm8998-mtp.dtsi"
  4748. +
  4749. +/ {
  4750. + model = "Qualcomm Technologies, Inc. MSM 8998 v2.1 MTP";
  4751. + compatible = "qcom,msm8998-mtp", "qcom,msm8998", "qcom,mtp";
  4752. + qcom,board-id = <30 0>;
  4753. +};
  4754. diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
  4755. index 3b01369..420346b 100644
  4756. --- a/arch/arm64/Kconfig
  4757. +++ b/arch/arm64/Kconfig
  4758. @@ -1088,3 +1088,18 @@ source "arch/arm64/crypto/Kconfig"
  4759. endif
  4760.  
  4761. source "lib/Kconfig"
  4762. +
  4763. +config BOOT_INFO
  4764. + bool "Boot information from bootloader"
  4765. + default y
  4766. + help
  4767. + On embedded linux device, we try to collect more information from
  4768. + bootloader to kernel. eg. powerup reason.
  4769. +
  4770. +config HWCONF_MANAGER
  4771. + bool "Hardware configuration and monitor information"
  4772. + default y
  4773. + depends on CJSON
  4774. + help
  4775. + It provides all kinds of components configuration information and
  4776. + monitor values.
  4777. diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
  4778. index 6f55e27..9129ca1 100644
  4779. --- a/arch/arm64/configs/msmcortex_defconfig
  4780. +++ b/arch/arm64/configs/msmcortex_defconfig
  4781. @@ -290,8 +290,8 @@ CONFIG_KEYBOARD_GPIO=y
  4782. CONFIG_INPUT_JOYSTICK=y
  4783. CONFIG_INPUT_TOUCHSCREEN=y
  4784. CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
  4785. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v21=y
  4786. CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
  4787. -CONFIG_SECURE_TOUCH=y
  4788. CONFIG_TOUCHSCREEN_ST=y
  4789. CONFIG_TOUCHSCREEN_ST_I2C=y
  4790. CONFIG_INPUT_MISC=y
  4791. diff --git a/arch/arm64/configs/sagit_user_defconfig b/arch/arm64/configs/sagit_user_defconfig
  4792. new file mode 100644
  4793. index 0000000..f374b39
  4794. --- /dev/null
  4795. +++ b/arch/arm64/configs/sagit_user_defconfig
  4796. @@ -0,0 +1,723 @@
  4797. +CONFIG_LOCALVERSION="-perf"
  4798. +CONFIG_AUDIT=y
  4799. +# CONFIG_AUDITSYSCALL is not set
  4800. +CONFIG_NO_HZ=y
  4801. +CONFIG_HIGH_RES_TIMERS=y
  4802. +CONFIG_IRQ_TIME_ACCOUNTING=y
  4803. +CONFIG_RCU_EXPERT=y
  4804. +CONFIG_RCU_FAST_NO_HZ=y
  4805. +CONFIG_RCU_NOCB_CPU=y
  4806. +CONFIG_RCU_NOCB_CPU_ALL=y
  4807. +# CONFIG_IKCONFIG is not set
  4808. +# CONFIG_IKCONFIG_PROC is not set
  4809. +CONFIG_LOG_BUF_SHIFT=21
  4810. +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
  4811. +CONFIG_CGROUP_FREEZER=y
  4812. +CONFIG_CPUSETS=y
  4813. +CONFIG_CGROUP_CPUACCT=y
  4814. +CONFIG_CGROUP_SCHEDTUNE=y
  4815. +CONFIG_RT_GROUP_SCHED=y
  4816. +CONFIG_SCHED_HMP=y
  4817. +CONFIG_SCHED_HMP_CSTATE_AWARE=y
  4818. +CONFIG_SCHED_CORE_CTL=y
  4819. +CONFIG_NAMESPACES=y
  4820. +# CONFIG_UTS_NS is not set
  4821. +# CONFIG_PID_NS is not set
  4822. +CONFIG_SCHED_AUTOGROUP=y
  4823. +CONFIG_SCHED_TUNE=y
  4824. +CONFIG_BLK_DEV_INITRD=y
  4825. +# CONFIG_RD_XZ is not set
  4826. +# CONFIG_RD_LZO is not set
  4827. +# CONFIG_RD_LZ4 is not set
  4828. +CONFIG_CC_OPTIMIZE_FOR_SIZE=y
  4829. +CONFIG_KALLSYMS_ALL=y
  4830. +# CONFIG_AIO is not set
  4831. +# CONFIG_MEMBARRIER is not set
  4832. +CONFIG_EMBEDDED=y
  4833. +# CONFIG_SLUB_DEBUG is not set
  4834. +# CONFIG_COMPAT_BRK is not set
  4835. +CONFIG_PROFILING=y
  4836. +CONFIG_CC_STACKPROTECTOR_REGULAR=y
  4837. +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
  4838. +CONFIG_MODULES=y
  4839. +CONFIG_MODULE_UNLOAD=y
  4840. +CONFIG_MODULE_FORCE_UNLOAD=y
  4841. +CONFIG_MODVERSIONS=y
  4842. +CONFIG_MODULE_SIG=y
  4843. +CONFIG_MODULE_SIG_FORCE=y
  4844. +CONFIG_MODULE_SIG_SHA512=y
  4845. +CONFIG_PARTITION_ADVANCED=y
  4846. +CONFIG_ARCH_QCOM=y
  4847. +CONFIG_ARCH_MSM8998=y
  4848. +CONFIG_ARCH_MSMHAMSTER=y
  4849. +CONFIG_PCI=y
  4850. +CONFIG_PCI_MSM=y
  4851. +CONFIG_SCHED_MC=y
  4852. +CONFIG_NR_CPUS=8
  4853. +CONFIG_QCOM_TLB_EL2_HANDLER=y
  4854. +CONFIG_PREEMPT=y
  4855. +CONFIG_HZ_100=y
  4856. +CONFIG_ARM64_REG_REBALANCE_ON_CTX_SW=y
  4857. +CONFIG_CMA=y
  4858. +CONFIG_CMA_DEBUGFS=y
  4859. +CONFIG_ZSMALLOC=y
  4860. +CONFIG_BALANCE_ANON_FILE_RECLAIM=y
  4861. +CONFIG_SECCOMP=y
  4862. +CONFIG_ARMV8_DEPRECATED=y
  4863. +CONFIG_SWP_EMULATION=y
  4864. +CONFIG_CP15_BARRIER_EMULATION=y
  4865. +CONFIG_SETEND_EMULATION=y
  4866. +# CONFIG_EFI is not set
  4867. +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
  4868. +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
  4869. +CONFIG_COMPAT=y
  4870. +CONFIG_PM_AUTOSLEEP=y
  4871. +CONFIG_PM_WAKELOCKS=y
  4872. +CONFIG_PM_WAKELOCKS_LIMIT=0
  4873. +# CONFIG_PM_WAKELOCKS_GC is not set
  4874. +CONFIG_CPU_FREQ=y
  4875. +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
  4876. +CONFIG_CPU_FREQ_GOV_USERSPACE=y
  4877. +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
  4878. +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
  4879. +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
  4880. +CONFIG_CPU_BOOST=y
  4881. +CONFIG_NET=y
  4882. +CONFIG_PACKET=y
  4883. +CONFIG_UNIX=y
  4884. +CONFIG_XFRM_USER=y
  4885. +CONFIG_XFRM_STATISTICS=y
  4886. +CONFIG_NET_KEY=y
  4887. +CONFIG_INET=y
  4888. +CONFIG_IP_MULTICAST=y
  4889. +CONFIG_IP_ADVANCED_ROUTER=y
  4890. +CONFIG_IP_MULTIPLE_TABLES=y
  4891. +CONFIG_IP_ROUTE_VERBOSE=y
  4892. +CONFIG_IP_PNP=y
  4893. +CONFIG_IP_PNP_DHCP=y
  4894. +CONFIG_INET_AH=y
  4895. +CONFIG_INET_ESP=y
  4896. +CONFIG_INET_IPCOMP=y
  4897. +CONFIG_INET_DIAG_DESTROY=y
  4898. +CONFIG_IPV6_ROUTER_PREF=y
  4899. +CONFIG_IPV6_ROUTE_INFO=y
  4900. +CONFIG_IPV6_OPTIMISTIC_DAD=y
  4901. +CONFIG_INET6_AH=y
  4902. +CONFIG_INET6_ESP=y
  4903. +CONFIG_INET6_IPCOMP=y
  4904. +CONFIG_IPV6_MIP6=y
  4905. +CONFIG_IPV6_MULTIPLE_TABLES=y
  4906. +CONFIG_IPV6_SUBTREES=y
  4907. +CONFIG_NETFILTER=y
  4908. +CONFIG_NF_CONNTRACK=y
  4909. +CONFIG_NF_CONNTRACK_SECMARK=y
  4910. +CONFIG_NF_CONNTRACK_EVENTS=y
  4911. +CONFIG_NF_CT_PROTO_DCCP=y
  4912. +CONFIG_NF_CT_PROTO_SCTP=y
  4913. +CONFIG_NF_CT_PROTO_UDPLITE=y
  4914. +CONFIG_NF_CONNTRACK_AMANDA=y
  4915. +CONFIG_NF_CONNTRACK_FTP=y
  4916. +CONFIG_NF_CONNTRACK_H323=y
  4917. +CONFIG_NF_CONNTRACK_IRC=y
  4918. +CONFIG_NF_CONNTRACK_NETBIOS_NS=y
  4919. +CONFIG_NF_CONNTRACK_PPTP=y
  4920. +CONFIG_NF_CONNTRACK_SANE=y
  4921. +CONFIG_NF_CONNTRACK_TFTP=y
  4922. +CONFIG_NF_CT_NETLINK=y
  4923. +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
  4924. +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
  4925. +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
  4926. +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
  4927. +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
  4928. +CONFIG_NETFILTER_XT_TARGET_LOG=y
  4929. +CONFIG_NETFILTER_XT_TARGET_MARK=y
  4930. +CONFIG_NETFILTER_XT_TARGET_NFLOG=y
  4931. +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
  4932. +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
  4933. +CONFIG_NETFILTER_XT_TARGET_TEE=y
  4934. +CONFIG_NETFILTER_XT_TARGET_TPROXY=y
  4935. +CONFIG_NETFILTER_XT_TARGET_TRACE=y
  4936. +CONFIG_NETFILTER_XT_TARGET_SECMARK=y
  4937. +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
  4938. +CONFIG_NETFILTER_XT_MATCH_COMMENT=y
  4939. +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
  4940. +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
  4941. +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
  4942. +CONFIG_NETFILTER_XT_MATCH_DSCP=y
  4943. +CONFIG_NETFILTER_XT_MATCH_ESP=y
  4944. +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
  4945. +CONFIG_NETFILTER_XT_MATCH_HELPER=y
  4946. +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
  4947. +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
  4948. +CONFIG_NETFILTER_XT_MATCH_LENGTH=y
  4949. +CONFIG_NETFILTER_XT_MATCH_LIMIT=y
  4950. +CONFIG_NETFILTER_XT_MATCH_MAC=y
  4951. +CONFIG_NETFILTER_XT_MATCH_MARK=y
  4952. +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
  4953. +CONFIG_NETFILTER_XT_MATCH_POLICY=y
  4954. +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
  4955. +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
  4956. +CONFIG_NETFILTER_XT_MATCH_QUOTA=y
  4957. +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
  4958. +CONFIG_NETFILTER_XT_MATCH_SOCKET=y
  4959. +CONFIG_NETFILTER_XT_MATCH_STATE=y
  4960. +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
  4961. +CONFIG_NETFILTER_XT_MATCH_STRING=y
  4962. +CONFIG_NETFILTER_XT_MATCH_TIME=y
  4963. +CONFIG_NETFILTER_XT_MATCH_U32=y
  4964. +CONFIG_NF_CONNTRACK_IPV4=y
  4965. +CONFIG_IP_NF_IPTABLES=y
  4966. +CONFIG_IP_NF_MATCH_AH=y
  4967. +CONFIG_IP_NF_MATCH_ECN=y
  4968. +CONFIG_IP_NF_MATCH_RPFILTER=y
  4969. +CONFIG_IP_NF_MATCH_TTL=y
  4970. +CONFIG_IP_NF_FILTER=y
  4971. +CONFIG_IP_NF_TARGET_REJECT=y
  4972. +CONFIG_IP_NF_NAT=y
  4973. +CONFIG_IP_NF_TARGET_MASQUERADE=y
  4974. +CONFIG_IP_NF_TARGET_NETMAP=y
  4975. +CONFIG_IP_NF_TARGET_REDIRECT=y
  4976. +CONFIG_IP_NF_MANGLE=y
  4977. +CONFIG_IP_NF_RAW=y
  4978. +CONFIG_IP_NF_SECURITY=y
  4979. +CONFIG_IP_NF_ARPTABLES=y
  4980. +CONFIG_IP_NF_ARPFILTER=y
  4981. +CONFIG_IP_NF_ARP_MANGLE=y
  4982. +CONFIG_NF_CONNTRACK_IPV6=y
  4983. +CONFIG_IP6_NF_IPTABLES=y
  4984. +CONFIG_IP6_NF_MATCH_RPFILTER=y
  4985. +CONFIG_IP6_NF_FILTER=y
  4986. +CONFIG_IP6_NF_TARGET_REJECT=y
  4987. +CONFIG_IP6_NF_MANGLE=y
  4988. +CONFIG_IP6_NF_RAW=y
  4989. +CONFIG_BRIDGE_NF_EBTABLES=y
  4990. +CONFIG_BRIDGE_EBT_BROUTE=y
  4991. +CONFIG_L2TP=y
  4992. +CONFIG_L2TP_V3=y
  4993. +CONFIG_L2TP_IP=y
  4994. +CONFIG_L2TP_ETH=y
  4995. +CONFIG_BRIDGE=y
  4996. +CONFIG_NET_SCHED=y
  4997. +CONFIG_NET_SCH_HTB=y
  4998. +CONFIG_NET_SCH_PRIO=y
  4999. +CONFIG_NET_SCH_MULTIQ=y
  5000. +CONFIG_NET_SCH_INGRESS=y
  5001. +CONFIG_NET_CLS_FW=y
  5002. +CONFIG_NET_CLS_U32=y
  5003. +CONFIG_CLS_U32_MARK=y
  5004. +CONFIG_NET_CLS_FLOW=y
  5005. +CONFIG_NET_EMATCH=y
  5006. +CONFIG_NET_EMATCH_CMP=y
  5007. +CONFIG_NET_EMATCH_NBYTE=y
  5008. +CONFIG_NET_EMATCH_U32=y
  5009. +CONFIG_NET_EMATCH_META=y
  5010. +CONFIG_NET_EMATCH_TEXT=y
  5011. +CONFIG_NET_CLS_ACT=y
  5012. +CONFIG_NET_ACT_GACT=y
  5013. +CONFIG_NET_ACT_MIRRED=y
  5014. +CONFIG_NET_ACT_SKBEDIT=y
  5015. +CONFIG_RMNET_DATA=y
  5016. +CONFIG_RMNET_DATA_FC=y
  5017. +CONFIG_RMNET_DATA_DEBUG_PKT=y
  5018. +CONFIG_SOCKEV_NLMCAST=y
  5019. +CONFIG_BT=y
  5020. +CONFIG_MSM_BT_POWER=y
  5021. +CONFIG_BTFM_SLIM=y
  5022. +CONFIG_BTFM_SLIM_WCN3990=y
  5023. +CONFIG_CFG80211=y
  5024. +CONFIG_CFG80211_INTERNAL_REGDB=y
  5025. +CONFIG_RFKILL=y
  5026. +CONFIG_NFC_NQ=y
  5027. +CONFIG_IPC_ROUTER=y
  5028. +CONFIG_IPC_ROUTER_SECURITY=y
  5029. +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
  5030. +CONFIG_DMA_CMA=y
  5031. +# CONFIG_PNP_DEBUG_MESSAGES is not set
  5032. +CONFIG_ZRAM=y
  5033. +CONFIG_ZRAM_DEBUG=y
  5034. +CONFIG_SWAP=y
  5035. +CONFIG_MEMCG=y
  5036. +CONFIG_MEMCG_SWAP=y
  5037. +CONFIG_ANDROID_WHETSTONE=y
  5038. +CONFIG_CGROUP_MEM_RES_CTLR=y
  5039. +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
  5040. +CONFIG_BLK_DEV_LOOP=y
  5041. +CONFIG_BLK_DEV_RAM=y
  5042. +CONFIG_BLK_DEV_RAM_SIZE=8192
  5043. +CONFIG_QSEECOM=y
  5044. +CONFIG_HDCP_QSEECOM=y
  5045. +CONFIG_UID_CPUTIME=y
  5046. +CONFIG_QPNP_MISC=y
  5047. +CONFIG_SCSI=y
  5048. +CONFIG_BLK_DEV_SD=y
  5049. +CONFIG_CHR_DEV_SG=y
  5050. +CONFIG_CHR_DEV_SCH=y
  5051. +CONFIG_SCSI_CONSTANTS=y
  5052. +CONFIG_SCSI_LOGGING=y
  5053. +CONFIG_SCSI_SCAN_ASYNC=y
  5054. +CONFIG_SCSI_UFSHCD=y
  5055. +CONFIG_SCSI_UFSHCD_PLATFORM=y
  5056. +CONFIG_SCSI_UFS_QCOM=y
  5057. +CONFIG_SCSI_UFS_QCOM_ICE=y
  5058. +CONFIG_MD=y
  5059. +CONFIG_BLK_DEV_MD=y
  5060. +CONFIG_MD_LINEAR=y
  5061. +CONFIG_BLK_DEV_DM=y
  5062. +CONFIG_DM_CRYPT=y
  5063. +CONFIG_DM_REQ_CRYPT=y
  5064. +CONFIG_DM_UEVENT=y
  5065. +CONFIG_DM_VERITY=y
  5066. +CONFIG_DM_VERITY_FEC=y
  5067. +CONFIG_DM_ANDROID_VERITY=y
  5068. +CONFIG_NETDEVICES=y
  5069. +CONFIG_BONDING=y
  5070. +CONFIG_DUMMY=y
  5071. +CONFIG_TUN=y
  5072. +CONFIG_SKY2=y
  5073. +CONFIG_RNDIS_IPA=y
  5074. +CONFIG_SMSC911X=y
  5075. +CONFIG_PPP=y
  5076. +CONFIG_PPP_BSDCOMP=y
  5077. +CONFIG_PPP_DEFLATE=y
  5078. +CONFIG_PPP_MPPE=y
  5079. +CONFIG_PPPOLAC=y
  5080. +CONFIG_PPPOPNS=y
  5081. +CONFIG_USB_USBNET=y
  5082. +CONFIG_USB_USBNET=y
  5083. +CONFIG_WCNSS_MEM_PRE_ALLOC=y
  5084. +CONFIG_ATH_CARDS=y
  5085. +CONFIG_WIL6210=m
  5086. +CONFIG_CLD_LL_CORE=y
  5087. +CONFIG_INPUT_EVDEV=y
  5088. +CONFIG_INPUT_KEYRESET=y
  5089. +CONFIG_KEYBOARD_GPIO=y
  5090. +# CONFIG_INPUT_MOUSE is not set
  5091. +CONFIG_INPUT_TOUCHSCREEN=y
  5092. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FORCE=y
  5093. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE=y
  5094. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE=y
  5095. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_FORCE=y
  5096. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_FORCE=y
  5097. +CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_FORCE=y
  5098. +CONFIG_SECURE_TOUCH=y
  5099. +CONFIG_INPUT_MISC=y
  5100. +CONFIG_INPUT_HBTP_INPUT=y
  5101. +CONFIG_INPUT_QPNP_POWER_ON=y
  5102. +CONFIG_INPUT_UINPUT=y
  5103. +CONFIG_INPUT_STMVL53L0=y
  5104. +CONFIG_INPUT_FINGERPRINT=y
  5105. +CONFIG_INPUT_GPIO=y
  5106. +CONFIG_FINGERPRINT_GOODIX_TA=y
  5107. +CONFIG_FINGERPRINT_FPC1268_TEE=y
  5108. +# CONFIG_SERIO_SERPORT is not set
  5109. +# CONFIG_VT is not set
  5110. +# CONFIG_LEGACY_PTYS is not set
  5111. +# CONFIG_DEVMEM is not set
  5112. +# CONFIG_DEVKMEM is not set
  5113. +# CONFIG_SERIAL_MSM is not set
  5114. +# CONFIG_SERIAL_MSM_CONSOLE is not set
  5115. +CONFIG_SERIAL_MSM_HS=y
  5116. +CONFIG_SERIAL_MSM_SMD=y
  5117. +CONFIG_DIAG_CHAR=y
  5118. +CONFIG_HW_RANDOM=y
  5119. +CONFIG_HW_RANDOM_MSM_LEGACY=y
  5120. +CONFIG_MSM_ADSPRPC=y
  5121. +CONFIG_MSM_RDBG=m
  5122. +CONFIG_I2C_CHARDEV=y
  5123. +CONFIG_I2C_MSM_V2=y
  5124. +CONFIG_SLIMBUS_MSM_NGD=y
  5125. +CONFIG_SOUNDWIRE=y
  5126. +CONFIG_SPI=y
  5127. +CONFIG_SPI_QUP=y
  5128. +CONFIG_SPI_SPIDEV=y
  5129. +CONFIG_SPMI=y
  5130. +CONFIG_PINCTRL_MSM8998=y
  5131. +CONFIG_PINCTRL_SDM660=y
  5132. +CONFIG_GPIOLIB=y
  5133. +CONFIG_GPIO_SYSFS=y
  5134. +CONFIG_GPIO_QPNP_PIN=y
  5135. +CONFIG_POWER_RESET_QCOM=y
  5136. +CONFIG_QCOM_DLOAD_MODE=y
  5137. +CONFIG_POWER_RESET_XGENE=y
  5138. +CONFIG_POWER_RESET_SYSCON=y
  5139. +CONFIG_QPNP_FG_GEN3=y
  5140. +CONFIG_MSM_BCL_CTL=y
  5141. +CONFIG_MSM_BCL_PERIPHERAL_CTL=y
  5142. +CONFIG_BATTERY_BCL=y
  5143. +CONFIG_QPNP_SMB2=y
  5144. +CONFIG_SMB138X_CHARGER=y
  5145. +CONFIG_QPNP_QNOVO=y
  5146. +CONFIG_MSM_PM=y
  5147. +CONFIG_APSS_CORE_EA=y
  5148. +CONFIG_MSM_APM=y
  5149. +CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
  5150. +CONFIG_CPU_THERMAL=y
  5151. +CONFIG_LIMITS_MONITOR=y
  5152. +CONFIG_LIMITS_LITE_HW=y
  5153. +CONFIG_THERMAL_MONITOR=y
  5154. +CONFIG_THERMAL_TSENS8974=y
  5155. +CONFIG_THERMAL_QPNP=y
  5156. +CONFIG_THERMAL_QPNP_ADC_TM=y
  5157. +CONFIG_QCOM_THERMAL_LIMITS_DCVS=y
  5158. +CONFIG_MFD_SPMI_PMIC=y
  5159. +CONFIG_MFD_I2C_PMIC=y
  5160. +CONFIG_WCD9335_CODEC=y
  5161. +CONFIG_WCD934X_CODEC=y
  5162. +CONFIG_REGULATOR=y
  5163. +CONFIG_REGULATOR_FIXED_VOLTAGE=y
  5164. +CONFIG_REGULATOR_RPM_SMD=y
  5165. +CONFIG_REGULATOR_QPNP=y
  5166. +CONFIG_REGULATOR_QPNP_LABIBB=y
  5167. +CONFIG_REGULATOR_QPNP_LCDB=y
  5168. +CONFIG_REGULATOR_SPM=y
  5169. +CONFIG_REGULATOR_CPR3_HMSS=y
  5170. +CONFIG_REGULATOR_CPR3_MMSS=y
  5171. +CONFIG_REGULATOR_CPRH_KBSS=y
  5172. +CONFIG_REGULATOR_MEM_ACC=y
  5173. +CONFIG_REGULATOR_PROXY_CONSUMER=y
  5174. +CONFIG_REGULATOR_STUB=y
  5175. +CONFIG_MEDIA_SUPPORT=y
  5176. +CONFIG_MEDIA_CAMERA_SUPPORT=y
  5177. +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
  5178. +CONFIG_MEDIA_CONTROLLER=y
  5179. +CONFIG_VIDEO_V4L2_SUBDEV_API=y
  5180. +CONFIG_VIDEO_ADV_DEBUG=y
  5181. +CONFIG_VIDEO_FIXED_MINOR_RANGES=y
  5182. +CONFIG_V4L_PLATFORM_DRIVERS=y
  5183. +CONFIG_MSM_CAMERA=y
  5184. +CONFIG_MSM_CAMERA_DEBUG=y
  5185. +CONFIG_MSMB_CAMERA=y
  5186. +CONFIG_MSMB_CAMERA_DEBUG=y
  5187. +CONFIG_MSM_CAMERA_SENSOR=y
  5188. +CONFIG_MSM_CPP=y
  5189. +CONFIG_MSM_CCI=y
  5190. +CONFIG_MSM_CSI20_HEADER=y
  5191. +CONFIG_MSM_CSI22_HEADER=y
  5192. +CONFIG_MSM_CSI30_HEADER=y
  5193. +CONFIG_MSM_CSI31_HEADER=y
  5194. +CONFIG_MSM_CSIPHY=y
  5195. +CONFIG_MSM_CSID=y
  5196. +CONFIG_MSM_EEPROM=y
  5197. +CONFIG_MSM_ISPIF=y
  5198. +CONFIG_IMX134=y
  5199. +CONFIG_IMX132=y
  5200. +CONFIG_OV9724=y
  5201. +CONFIG_OV5648=y
  5202. +CONFIG_GC0339=y
  5203. +CONFIG_OV8825=y
  5204. +CONFIG_OV8865=y
  5205. +CONFIG_s5k4e1=y
  5206. +CONFIG_OV12830=y
  5207. +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
  5208. +CONFIG_MSMB_JPEG=y
  5209. +CONFIG_MSM_FD=y
  5210. +CONFIG_MSM_JPEGDMA=y
  5211. +CONFIG_MSM_VIDC_V4L2=y
  5212. +CONFIG_MSM_VIDC_VMEM=y
  5213. +CONFIG_MSM_VIDC_GOVERNORS=y
  5214. +CONFIG_MSM_SDE_ROTATOR=y
  5215. +CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
  5216. +CONFIG_DVB_MPQ=m
  5217. +CONFIG_DVB_MPQ_DEMUX=m
  5218. +CONFIG_TSPP=m
  5219. +CONFIG_QCOM_KGSL=y
  5220. +CONFIG_FB=y
  5221. +CONFIG_FB_ARMCLCD=y
  5222. +CONFIG_FB_MSM=y
  5223. +CONFIG_FB_MSM_MDSS=y
  5224. +CONFIG_FB_MSM_MDSS_WRITEBACK=y
  5225. +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
  5226. +CONFIG_FB_MSM_MDSS_DP_PANEL=y
  5227. +# CONFIG_FB_MSM_MDSS_XLOG_DEBUG is not set
  5228. +CONFIG_LOGO=y
  5229. +# CONFIG_LOGO_LINUX_MONO is not set
  5230. +# CONFIG_LOGO_LINUX_VGA16 is not set
  5231. +CONFIG_SOUND=y
  5232. +CONFIG_SND=y
  5233. +CONFIG_SND_USB_AUDIO=y
  5234. +CONFIG_SND_USB_AUDIO_QMI=y
  5235. +CONFIG_SND_SOC=y
  5236. +CONFIG_SND_SOC_MSM8998=y
  5237. +CONFIG_UHID=y
  5238. +CONFIG_HID_APPLE=y
  5239. +CONFIG_HID_ELECOM=y
  5240. +CONFIG_HID_MAGICMOUSE=y
  5241. +CONFIG_HID_MICROSOFT=y
  5242. +CONFIG_HID_MULTITOUCH=y
  5243. +CONFIG_HID_PLANTRONICS=y
  5244. +CONFIG_USB=y
  5245. +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
  5246. +CONFIG_USB_XHCI_HCD=y
  5247. +CONFIG_USB_EHCI_HCD=y
  5248. +CONFIG_USB_EHCI_HCD_PLATFORM=y
  5249. +CONFIG_USB_OHCI_HCD=y
  5250. +CONFIG_USB_OHCI_HCD_PLATFORM=y
  5251. +CONFIG_USB_STORAGE=y
  5252. +CONFIG_USB_DWC3=y
  5253. +CONFIG_USB_ISP1760=y
  5254. +CONFIG_USB_ISP1760_HOST_ROLE=y
  5255. +CONFIG_USB_PD_POLICY=y
  5256. +CONFIG_QPNP_USB_PDPHY=y
  5257. +CONFIG_USB_EHSET_TEST_FIXTURE=y
  5258. +CONFIG_USB_OTG_WAKELOCK=y
  5259. +CONFIG_NOP_USB_XCEIV=y
  5260. +CONFIG_USB_MSM_SSPHY_QMP=y
  5261. +CONFIG_MSM_QUSB_PHY=y
  5262. +CONFIG_DUAL_ROLE_USB_INTF=y
  5263. +CONFIG_USB_GADGET=y
  5264. +CONFIG_USB_GADGET_VBUS_DRAW=500
  5265. +CONFIG_USB_CONFIGFS=y
  5266. +CONFIG_USB_CONFIGFS_NCM=y
  5267. +CONFIG_USB_CONFIGFS_MASS_STORAGE=y
  5268. +CONFIG_USB_CONFIGFS_F_FS=y
  5269. +CONFIG_USB_CONFIGFS_F_MTP=y
  5270. +CONFIG_USB_CONFIGFS_F_PTP=y
  5271. +CONFIG_USB_CONFIGFS_F_ACC=y
  5272. +CONFIG_USB_CONFIGFS_UEVENT=y
  5273. +CONFIG_USB_CONFIGFS_F_MIDI=y
  5274. +CONFIG_USB_CONFIGFS_F_HID=y
  5275. +CONFIG_USB_CONFIGFS_F_DIAG=y
  5276. +CONFIG_USB_CONFIGFS_F_GSI=y
  5277. +CONFIG_USB_CONFIGFS_F_CDEV=y
  5278. +CONFIG_USB_CONFIGFS_F_QDSS=y
  5279. +CONFIG_USB_CONFIGFS_F_CCID=y
  5280. +CONFIG_MMC=y
  5281. +CONFIG_MMC_PERF_PROFILING=y
  5282. +CONFIG_MMC_CLKGATE=y
  5283. +CONFIG_MMC_BLOCK_MINORS=32
  5284. +CONFIG_MMC_TEST=y
  5285. +CONFIG_MMC_SDHCI=y
  5286. +CONFIG_MMC_SDHCI_PLTFM=y
  5287. +CONFIG_MMC_SDHCI_MSM=y
  5288. +CONFIG_LEDS_QPNP=y
  5289. +CONFIG_LEDS_QPNP_FLASH_V2=y
  5290. +CONFIG_LEDS_QPNP_WLED=y
  5291. +CONFIG_LEDS_SYSCON=y
  5292. +CONFIG_LEDS_TRIGGERS=y
  5293. +CONFIG_SWITCH=y
  5294. +CONFIG_RTC_CLASS=y
  5295. +CONFIG_RTC_DRV_QPNP=y
  5296. +CONFIG_DMADEVICES=y
  5297. +CONFIG_QCOM_SPS_DMA=y
  5298. +CONFIG_UIO=y
  5299. +CONFIG_UIO_MSM_SHAREDMEM=y
  5300. +CONFIG_STAGING=y
  5301. +CONFIG_ASHMEM=y
  5302. +CONFIG_ANDROID_TIMED_GPIO=y
  5303. +CONFIG_ANDROID_LOW_MEMORY_KILLER=y
  5304. +CONFIG_MULTIPLE_LMK=y
  5305. +CONFIG_ION=y
  5306. +CONFIG_ION_MSM=y
  5307. +CONFIG_QPNP_REVID=y
  5308. +CONFIG_QPNP_COINCELL=y
  5309. +CONFIG_SPS=y
  5310. +CONFIG_SPS_SUPPORT_NDP_BAM=y
  5311. +CONFIG_IPA=y
  5312. +CONFIG_RMNET_IPA=y
  5313. +CONFIG_GSI=y
  5314. +CONFIG_IPA3=y
  5315. +CONFIG_RMNET_IPA3=y
  5316. +CONFIG_GPIO_USB_DETECT=y
  5317. +CONFIG_SEEMP_CORE=y
  5318. +CONFIG_USB_BAM=y
  5319. +CONFIG_MSM_MDSS_PLL=y
  5320. +CONFIG_REMOTE_SPINLOCK_MSM=y
  5321. +CONFIG_MSM_TIMER_LEAP=y
  5322. +CONFIG_IOMMU_IO_PGTABLE_FAST=y
  5323. +CONFIG_ARM_SMMU=y
  5324. +CONFIG_IOMMU_DEBUG=y
  5325. +CONFIG_IOMMU_DEBUG_TRACKING=y
  5326. +CONFIG_IOMMU_TESTS=y
  5327. +# CONFIG_QCOM_COMMON_LOG is not set
  5328. +# CONFIG_SERIAL_EARLYCON is not set
  5329. +# CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC is not set
  5330. +CONFIG_MSM_SMEM=y
  5331. +CONFIG_QPNP_HAPTIC=y
  5332. +CONFIG_MSM_SMD=y
  5333. +CONFIG_MSM_GLINK=y
  5334. +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
  5335. +CONFIG_MSM_GLINK_SMD_XPRT=y
  5336. +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
  5337. +CONFIG_MSM_GLINK_SPI_XPRT=y
  5338. +CONFIG_MSM_SPCOM=y
  5339. +CONFIG_MSM_SPSS_UTILS=y
  5340. +CONFIG_MSM_SMEM_LOGGING=y
  5341. +CONFIG_MSM_SMP2P=y
  5342. +CONFIG_MSM_SMP2P_TEST=y
  5343. +CONFIG_MSM_QMI_INTERFACE=y
  5344. +CONFIG_MSM_RPM_SMD=y
  5345. +CONFIG_QCOM_BUS_SCALING=y
  5346. +CONFIG_MSM_SERVICE_LOCATOR=y
  5347. +CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
  5348. +CONFIG_MSM_SYSMON_GLINK_COMM=y
  5349. +CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
  5350. +CONFIG_MSM_GLINK_PKT=y
  5351. +CONFIG_MSM_SPM=y
  5352. +CONFIG_QCOM_SCM=y
  5353. +CONFIG_QCOM_WATCHDOG_V2=y
  5354. +CONFIG_DUMP_ALL_STACKS=y
  5355. +# CONFIG_FIRE_WATCHDOG is not set
  5356. +CONFIG_QCOM_IRQ_HELPER=y
  5357. +CONFIG_QCOM_MEMORY_DUMP_V2=y
  5358. +CONFIG_ICNSS=y
  5359. +CONFIG_MSM_RUN_QUEUE_STATS=y
  5360. +CONFIG_MSM_BOOT_STATS=y
  5361. +CONFIG_MSM_ADSP_LOADER=y
  5362. +CONFIG_MSM_PERFORMANCE=y
  5363. +CONFIG_MSM_SUBSYSTEM_RESTART=y
  5364. +CONFIG_MSM_PIL=y
  5365. +CONFIG_MSM_PIL_SSR_GENERIC=y
  5366. +CONFIG_MSM_PIL_MSS_QDSP6V5=y
  5367. +CONFIG_TRACER_PKT=y
  5368. +# CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC is not set
  5369. +CONFIG_MSM_MPM_OF=y
  5370. +CONFIG_MSM_EVENT_TIMER=y
  5371. +CONFIG_MSM_AVTIMER=y
  5372. +CONFIG_QCOM_REMOTEQDSS=y
  5373. +CONFIG_MSM_SERVICE_NOTIFIER=y
  5374. +CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
  5375. +CONFIG_MSM_RPM_LOG=y
  5376. +CONFIG_MSM_RPM_STATS_LOG=y
  5377. +CONFIG_QSEE_IPC_IRQ_BRIDGE=y
  5378. +CONFIG_QCOM_SMCINVOKE=y
  5379. +CONFIG_QCOM_EARLY_RANDOM=y
  5380. +CONFIG_MEM_SHARE_QMI_SERVICE=y
  5381. +CONFIG_QCOM_BIMC_BWMON=y
  5382. +CONFIG_ARM_MEMLAT_MON=y
  5383. +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
  5384. +CONFIG_DEVFREQ_GOV_MEMLAT=y
  5385. +CONFIG_QCOM_DEVFREQ_DEVBW=y
  5386. +CONFIG_SPDM_SCM=y
  5387. +CONFIG_DEVFREQ_SPDM=y
  5388. +CONFIG_EXTCON=y
  5389. +CONFIG_IIO=y
  5390. +CONFIG_QCOM_RRADC=y
  5391. +CONFIG_QCOM_TADC=y
  5392. +CONFIG_PWM=y
  5393. +CONFIG_PWM_QPNP=y
  5394. +CONFIG_ARM_GIC_V3_ACL=y
  5395. +CONFIG_ANDROID=y
  5396. +CONFIG_ANDROID_BINDER_IPC=y
  5397. +CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder"
  5398. +CONFIG_MSM_TZ_LOG=y
  5399. +CONFIG_SENSORS_SSC=y
  5400. +CONFIG_EXT2_FS=y
  5401. +CONFIG_EXT2_FS_XATTR=y
  5402. +CONFIG_EXT3_FS=y
  5403. +CONFIG_EXT4_FS_SECURITY=y
  5404. +CONFIG_EXT4_ENCRYPTION=y
  5405. +CONFIG_EXT4_FS_ENCRYPTION=y
  5406. +CONFIG_EXT4_FS_ICE_ENCRYPTION=y
  5407. +CONFIG_FUSE_FS=y
  5408. +CONFIG_MSDOS_FS=y
  5409. +CONFIG_VFAT_FS=y
  5410. +CONFIG_TMPFS=y
  5411. +CONFIG_TMPFS_POSIX_ACL=y
  5412. +CONFIG_ECRYPT_FS=y
  5413. +CONFIG_ECRYPT_FS_MESSAGING=y
  5414. +CONFIG_NLS_CODEPAGE_437=y
  5415. +CONFIG_NLS_ISO8859_1=y
  5416. +CONFIG_PRINTK_TIME=y
  5417. +CONFIG_DEBUG_INFO=y
  5418. +CONFIG_DYNAMIC_DEBUG=y
  5419. +CONFIG_MAGIC_SYSRQ=y
  5420. +CONFIG_PANIC_TIMEOUT=1
  5421. +CONFIG_SCHEDSTATS=y
  5422. +CONFIG_TIMER_STATS=y
  5423. +# CONFIG_DEBUG_PREEMPT is not set
  5424. +CONFIG_IPC_LOGGING=y
  5425. +CONFIG_QCOM_RTB=y
  5426. +CONFIG_QCOM_RTB_SEPARATE_CPUS=y
  5427. +CONFIG_CPU_FREQ_SWITCH_PROFILER=y
  5428. +CONFIG_DEBUG_SET_MODULE_RONX=y
  5429. +CONFIG_DEBUG_RODATA=y
  5430. +CONFIG_DEBUG_ALIGN_RODATA=y
  5431. +CONFIG_CORESIGHT=y
  5432. +CONFIG_CORESIGHT_EVENT=y
  5433. +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
  5434. +CONFIG_CORESIGHT_QCOM_REPLICATOR=y
  5435. +CONFIG_CORESIGHT_STM=y
  5436. +CONFIG_CORESIGHT_HWEVENT=y
  5437. +CONFIG_CORESIGHT_CTI=y
  5438. +CONFIG_CORESIGHT_TPDA=y
  5439. +CONFIG_CORESIGHT_TPDM=y
  5440. +CONFIG_CORESIGHT_QPDI=y
  5441. +CONFIG_CORESIGHT_SOURCE_DUMMY=y
  5442. +CONFIG_PFK=y
  5443. +CONFIG_SECURITY=y
  5444. +CONFIG_SECURITY_SELINUX=y
  5445. +CONFIG_SECURITY_SMACK=y
  5446. +CONFIG_CRYPTO_ECHAINIV=y
  5447. +CONFIG_CRYPTO_XCBC=y
  5448. +CONFIG_CRYPTO_MD4=y
  5449. +CONFIG_CRYPTO_TWOFISH=y
  5450. +CONFIG_CRYPTO_ANSI_CPRNG=y
  5451. +CONFIG_CRYPTO_DEV_QCRYPTO=y
  5452. +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
  5453. +CONFIG_CRYPTO_DEV_QCEDEV=y
  5454. +CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
  5455. +CONFIG_CRYPTO_DEV_QCOM_ICE=y
  5456. +CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem"
  5457. +CONFIG_ARM64_CRYPTO=y
  5458. +CONFIG_CRYPTO_SHA1_ARM64_CE=y
  5459. +CONFIG_CRYPTO_SHA2_ARM64_CE=y
  5460. +CONFIG_CRYPTO_GHASH_ARM64_CE=y
  5461. +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
  5462. +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
  5463. +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
  5464. +CONFIG_CRYPTO_CRC32_ARM64=y
  5465. +CONFIG_QMI_ENCDEC=y
  5466. +
  5467. +CONFIG_PSTORE=y
  5468. +CONFIG_PSTORE_CONSOLE=y
  5469. +CONFIG_PSTORE_RAM=y
  5470. +CONFIG_PSTORE_PMSG=y
  5471. +CONFIG_CMDLINE="ramoops_memreserve=4M"
  5472. +CONFIG_CMDLINE_EXTEND=y
  5473. +CONFIG_BOOT_INFO=y
  5474. +CONFIG_CJSON=y
  5475. +CONFIG_HWCONF_MANAGER=y
  5476. +CONFIG_OF_FLATTREE=y
  5477. +CONFIG_SERIAL_NUM=y
  5478. +CONFIG_LAST_TOUCH_EVENTS=y
  5479. +CONFIG_SPI_PEELIR=y
  5480. +
  5481. +## MIUI ADD:START
  5482. +## Multi userspace config support
  5483. +CONFIG_KEYS=y
  5484. +CONFIG_ENCRYPTED_KEYS=y
  5485. +CONFIG_CRYPTO=y
  5486. +CONFIG_CRYPTO_AES=y
  5487. +CONFIG_CRYPTO_SHA1=y
  5488. +CONFIG_CRYPTO_SHA256=y
  5489. +CONFIG_CRYPTO_MD5=y
  5490. +CONFIG_CRYPTO_GF128MUL=y
  5491. +CONFIG_CRYPTO_SEQIV=y
  5492. +CONFIG_CRYPTO_CTR=y
  5493. +CONFIG_CRYPTO_XTS=y
  5494. +CONFIG_NET_NS=y
  5495. +CONFIG_VETH=y
  5496. +CONFIG_GPIO_RF=y
  5497. +## END
  5498. +
  5499. +
  5500. +#MIUI ADD
  5501. +#Add CIFS Config
  5502. +CONFIG_NETWORK_FILESYSTEMS=y
  5503. +CONFIG_CIFS=y
  5504. +CONFIG_NLS=y
  5505. +CONFIG_NLS_DEFAULT="iso8859-1"
  5506. +CONFIG_NLS_CODEPAGE_936=y
  5507. +CONFIG_NLS_CODEPAGE_950=y
  5508. +CONFIG_NLS_UTF8=y
  5509. +#MIUI END
  5510. +CONFIG_F2FS_FS=y
  5511. +CONFIG_F2FS_STAT_FS=y
  5512. +CONFIG_F2FS_FS_XATTR=y
  5513. +CONFIG_F2FS_FS_POSIX_ACL=y
  5514. +CONFIG_F2FS_FS_SECURITY=y
  5515. +CONFIG_F2FS_FS_ENCRYPTION=y
  5516. +CONFIG_F2FS_FS_ICE_ENCRYPTION=y
  5517. +
  5518. +# cpuset totally exlusive support for vr
  5519. +CONFIG_CPUSET_EXCLUSIVE_IND=y
  5520. diff --git a/arch/arm64/include/asm/bootinfo.h b/arch/arm64/include/asm/bootinfo.h
  5521. new file mode 100644
  5522. index 0000000..697813e
  5523. --- /dev/null
  5524. +++ b/arch/arm64/include/asm/bootinfo.h
  5525. @@ -0,0 +1,55 @@
  5526. +/*
  5527. + * bootinfo.h
  5528. + *
  5529. + * This program is free software; you can redistribute it and/or modify
  5530. + * it under the terms of the GNU General Public License version 2 as
  5531. + * published by the Free Software Foundation.
  5532. + */
  5533. +
  5534. +#ifndef __ASMARM_BOOTINFO_H
  5535. +#define __ASMARM_BOOTINFO_H
  5536. +
  5537. +#define HW_DEVID_VERSION_SHIFT 8
  5538. +#define HW_DEVID_VERSION_MASK 0xF00UL
  5539. +#define HW_MAJOR_VERSION_SHIFT 4
  5540. +#define HW_MAJOR_VERSION_MASK 0xF0
  5541. +#define HW_MINOR_VERSION_SHIFT 0
  5542. +#define HW_MINOR_VERSION_MASK 0x0F
  5543. +
  5544. +typedef enum {
  5545. + PU_REASON_EVENT_HWRST,
  5546. + PU_REASON_EVENT_SMPL,
  5547. + PU_REASON_EVENT_RTC,
  5548. + PU_REASON_EVENT_DC_CHG,
  5549. + PU_REASON_EVENT_USB_CHG,
  5550. + PU_REASON_EVENT_PON1,
  5551. + PU_REASON_EVENT_CABLE,
  5552. + PU_REASON_EVENT_KPD,
  5553. + PU_REASON_EVENT_WARMRST,
  5554. + PU_REASON_EVENT_LPK,
  5555. + PU_REASON_EVENT_LCK,
  5556. + PU_REASON_MAX
  5557. +} powerup_reason_t;
  5558. +
  5559. +enum {
  5560. + RS_REASON_EVENT_WDOG,
  5561. + RS_REASON_EVENT_KPANIC,
  5562. + RS_REASON_EVENT_NORMAL,
  5563. + RS_REASON_EVENT_OTHER,
  5564. + RS_REASON_MAX
  5565. +};
  5566. +
  5567. +#define RESTART_EVENT_WDOG 0x10000
  5568. +#define RESTART_EVENT_KPANIC 0x20000
  5569. +#define RESTART_EVENT_NORMAL 0x40000
  5570. +#define RESTART_EVENT_OTHER 0x80000
  5571. +
  5572. +unsigned int get_powerup_reason(void);
  5573. +int is_abnormal_powerup(void);
  5574. +void set_powerup_reason(unsigned int powerup_reason);
  5575. +unsigned int get_hw_version(void);
  5576. +void set_hw_version(unsigned int hw_version);
  5577. +unsigned int get_hw_version_devid(void);
  5578. +unsigned int get_hw_version_major(void);
  5579. +unsigned int get_hw_version_minor(void);
  5580. +#endif
  5581. diff --git a/arch/arm64/include/asm/hwconf_manager.h b/arch/arm64/include/asm/hwconf_manager.h
  5582. new file mode 100644
  5583. index 0000000..50e162c
  5584. --- /dev/null
  5585. +++ b/arch/arm64/include/asm/hwconf_manager.h
  5586. @@ -0,0 +1,21 @@
  5587. +/*
  5588. + * hwconf_manager.h
  5589. + *
  5590. + * This program is free software; you can redistribute it and/or modify
  5591. + * it under the terms of the GNU General Public License version 2 as
  5592. + * published by the Free Software Foundation.
  5593. + */
  5594. +
  5595. +#ifndef _LINUX_HWCONF_MANAGER_H
  5596. +#define _LINUX_HWCONF_MANAGER_H
  5597. +
  5598. +int register_hw_component_info(char *component_name);
  5599. +int add_hw_component_info(char *component_name, char *key, char *value);
  5600. +int unregister_hw_component_info(char *component_name);
  5601. +
  5602. +int register_hw_monitor_info(char *component_name);
  5603. +int add_hw_monitor_info(char *component_name, char *mon_key, char *mon_value);
  5604. +int update_hw_monitor_info(char *component_name, char *mon_key, char *mon_value);
  5605. +int unregister_hw_monitor_info(char *component_name);
  5606. +
  5607. +#endif
  5608. diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
  5609. index f6e0269..3bd7ff7 100644
  5610. --- a/arch/arm64/kernel/Makefile
  5611. +++ b/arch/arm64/kernel/Makefile
  5612. @@ -40,6 +40,8 @@ arm64-obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
  5613. arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
  5614. arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
  5615. arm64-obj-$(CONFIG_KGDB) += kgdb.o
  5616. +arm64-obj-$(CONFIG_BOOT_INFO) += bootinfo.o
  5617. +arm64-obj-$(CONFIG_HWCONF_MANAGER) += hwconf_manager.o
  5618. arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o
  5619. arm64-obj-$(CONFIG_PCI) += pci.o
  5620. arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
  5621. diff --git a/arch/arm64/kernel/bootinfo.c b/arch/arm64/kernel/bootinfo.c
  5622. new file mode 100644
  5623. index 0000000..a248c92
  5624. --- /dev/null
  5625. +++ b/arch/arm64/kernel/bootinfo.c
  5626. @@ -0,0 +1,214 @@
  5627. +/*
  5628. + * bootinfo.c
  5629. + *
  5630. + * Copyright (C) 2017 XiaoMi, Inc.
  5631. + *
  5632. + * This program is free software; you can redistribute it and/or modify
  5633. + * it under the terms of the GNU General Public License version 2 as
  5634. + * published by the Free Software Foundation.
  5635. + */
  5636. +
  5637. +#include <linux/module.h>
  5638. +#include <linux/kernel.h>
  5639. +#include <linux/init.h>
  5640. +#include <linux/fs.h>
  5641. +#include <linux/string.h>
  5642. +#include <asm/setup.h>
  5643. +#include <asm/bootinfo.h>
  5644. +#include <linux/bitops.h>
  5645. +#include <linux/input/qpnp-power-on.h>
  5646. +
  5647. +static const char * const powerup_reasons[PU_REASON_MAX] = {
  5648. + [PU_REASON_EVENT_KPD] = "keypad",
  5649. + [PU_REASON_EVENT_RTC] = "rtc",
  5650. + [PU_REASON_EVENT_CABLE] = "cable",
  5651. + [PU_REASON_EVENT_SMPL] = "smpl",
  5652. + [PU_REASON_EVENT_PON1] = "pon1",
  5653. + [PU_REASON_EVENT_USB_CHG] = "usb_chg",
  5654. + [PU_REASON_EVENT_DC_CHG] = "dc_chg",
  5655. + [PU_REASON_EVENT_HWRST] = "hw_reset",
  5656. + [PU_REASON_EVENT_LPK] = "long_power_key",
  5657. + [PU_REASON_EVENT_LCK] = "long_combo_key",
  5658. +};
  5659. +
  5660. +static const char * const reset_reasons[RS_REASON_MAX] = {
  5661. + [RS_REASON_EVENT_WDOG] = "wdog",
  5662. + [RS_REASON_EVENT_KPANIC] = "kpanic",
  5663. + [RS_REASON_EVENT_NORMAL] = "reboot",
  5664. + [RS_REASON_EVENT_OTHER] = "other",
  5665. +};
  5666. +
  5667. +static struct kobject *bootinfo_kobj;
  5668. +static powerup_reason_t powerup_reason;
  5669. +static unsigned int hw_version;
  5670. +
  5671. +#define bootinfo_attr(_name) \
  5672. +static struct kobj_attribute _name##_attr = { \
  5673. + .attr = { \
  5674. + .name = __stringify(_name), \
  5675. + .mode = 0644, \
  5676. + }, \
  5677. + .show = _name##_show, \
  5678. + .store = NULL, \
  5679. +}
  5680. +
  5681. +#define bootinfo_func_init(type, name, initval) \
  5682. +static type name = (initval); \
  5683. +type get_##name(void) \
  5684. +{ \
  5685. + return name; \
  5686. +} \
  5687. +void set_##name(type __##name) \
  5688. +{ \
  5689. + name = __##name; \
  5690. +}
  5691. +
  5692. +int is_abnormal_powerup(void)
  5693. +{
  5694. + u32 pu_reason = get_powerup_reason();
  5695. + return (pu_reason & (RESTART_EVENT_KPANIC | RESTART_EVENT_WDOG)) |
  5696. + (pu_reason & BIT(PU_REASON_EVENT_HWRST) & RESTART_EVENT_OTHER);
  5697. +}
  5698. +
  5699. +static ssize_t powerup_reason_show(struct kobject *kobj,
  5700. + struct kobj_attribute *attr, char *buf)
  5701. +{
  5702. + char *s = buf;
  5703. + u32 pu_reason;
  5704. + int pu_reason_index = PU_REASON_MAX;
  5705. + u32 reset_reason;
  5706. + int reset_reason_index = RS_REASON_MAX;
  5707. +
  5708. + pu_reason = get_powerup_reason();
  5709. + if (pu_reason & BIT(PU_REASON_EVENT_WARMRST)
  5710. + && qpnp_pon_is_lck()) {
  5711. + pu_reason_index = PU_REASON_EVENT_LCK;
  5712. + s += snprintf(s, strlen(powerup_reasons[pu_reason_index]) + 1,
  5713. + powerup_reasons[pu_reason_index]);
  5714. + pr_debug("%s: pu_reason [0x%x] index %d\n",
  5715. + __func__, pu_reason, pu_reason_index);
  5716. + goto out;
  5717. + }
  5718. +
  5719. + if (((pu_reason & BIT(PU_REASON_EVENT_HWRST))
  5720. + && qpnp_pon_is_ps_hold_reset()) ||
  5721. + (pu_reason & BIT(PU_REASON_EVENT_WARMRST))) {
  5722. + reset_reason = pu_reason >> 16;
  5723. + reset_reason_index = find_first_bit((unsigned long *)&reset_reason,
  5724. + sizeof(reset_reason)*BITS_PER_BYTE);
  5725. + if (reset_reason_index < RS_REASON_MAX && reset_reason_index >= 0) {
  5726. + s += snprintf(s, strlen(reset_reasons[reset_reason_index]) + 1,
  5727. + reset_reasons[reset_reason_index]);
  5728. + pr_debug("%s: rs_reason [0x%x], first non-zero bit %d\n",
  5729. + __func__, reset_reason, reset_reason_index);
  5730. + goto out;
  5731. + };
  5732. + }
  5733. + if (qpnp_pon_is_lpk() &&
  5734. + (pu_reason & BIT(PU_REASON_EVENT_HWRST)))
  5735. + pu_reason_index = PU_REASON_EVENT_LPK;
  5736. + else if (pu_reason & BIT(PU_REASON_EVENT_HWRST))
  5737. + pu_reason_index = PU_REASON_EVENT_HWRST;
  5738. + else if (pu_reason & BIT(PU_REASON_EVENT_SMPL))
  5739. + pu_reason_index = PU_REASON_EVENT_SMPL;
  5740. + else if (pu_reason & BIT(PU_REASON_EVENT_RTC))
  5741. + pu_reason_index = PU_REASON_EVENT_RTC;
  5742. + else if (pu_reason & BIT(PU_REASON_EVENT_USB_CHG))
  5743. + pu_reason_index = PU_REASON_EVENT_USB_CHG;
  5744. + else if (pu_reason & BIT(PU_REASON_EVENT_DC_CHG))
  5745. + pu_reason_index = PU_REASON_EVENT_DC_CHG;
  5746. + else if (pu_reason & BIT(PU_REASON_EVENT_KPD))
  5747. + pu_reason_index = PU_REASON_EVENT_KPD;
  5748. + else if (pu_reason & BIT(PU_REASON_EVENT_PON1))
  5749. + pu_reason_index = PU_REASON_EVENT_PON1;
  5750. + if (pu_reason_index < PU_REASON_MAX && pu_reason_index >= 0) {
  5751. + s += snprintf(s, strlen(powerup_reasons[pu_reason_index]) + 1,
  5752. + powerup_reasons[pu_reason_index]);
  5753. + pr_debug("%s: pu_reason [0x%x] index %d\n",
  5754. + __func__, pu_reason, pu_reason_index);
  5755. + goto out;
  5756. + }
  5757. + s += snprintf(s, 15, "unknown reboot");
  5758. +out:
  5759. + return (s - buf);
  5760. +}
  5761. +
  5762. +static ssize_t powerup_reason_details_show(struct kobject *kobj,
  5763. + struct kobj_attribute *attr, char *buf)
  5764. +{
  5765. + u32 pu_reason;
  5766. +
  5767. + pu_reason = get_powerup_reason();
  5768. +
  5769. + return snprintf(buf, 11, "0x%x\n", pu_reason);
  5770. +}
  5771. +
  5772. +static ssize_t hw_version_show(struct kobject *kobj,
  5773. + struct kobj_attribute *attr, char *buf)
  5774. +{
  5775. + u32 hw_version;
  5776. +
  5777. + hw_version = get_hw_version();
  5778. +
  5779. + return snprintf(buf, 11, "0x%x\n", hw_version);
  5780. +}
  5781. +
  5782. +bootinfo_attr(powerup_reason);
  5783. +bootinfo_attr(powerup_reason_details);
  5784. +bootinfo_attr(hw_version);
  5785. +bootinfo_func_init(u32, powerup_reason, 0);
  5786. +bootinfo_func_init(u32, hw_version, 0);
  5787. +
  5788. +unsigned int get_hw_version_devid(void)
  5789. +{
  5790. + return ((get_hw_version() & HW_DEVID_VERSION_MASK)
  5791. + >> HW_DEVID_VERSION_SHIFT);
  5792. +}
  5793. +EXPORT_SYMBOL(get_hw_version_devid);
  5794. +
  5795. +static struct attribute *g[] = {
  5796. + &powerup_reason_attr.attr,
  5797. + &powerup_reason_details_attr.attr,
  5798. + &hw_version_attr.attr,
  5799. + NULL,
  5800. +};
  5801. +
  5802. +static struct attribute_group attr_group = {
  5803. + .attrs = g,
  5804. +};
  5805. +
  5806. +static int __init bootinfo_init(void)
  5807. +{
  5808. + int ret = -ENOMEM;
  5809. +
  5810. + bootinfo_kobj = kobject_create_and_add("bootinfo", NULL);
  5811. + if (bootinfo_kobj == NULL) {
  5812. + pr_err("bootinfo_init: subsystem_register failed\n");
  5813. + goto fail;
  5814. + }
  5815. +
  5816. + ret = sysfs_create_group(bootinfo_kobj, &attr_group);
  5817. + if (ret) {
  5818. + pr_err("bootinfo_init: subsystem_register failed\n");
  5819. + goto sys_fail;
  5820. + }
  5821. +
  5822. + return ret;
  5823. +
  5824. +sys_fail:
  5825. + kobject_del(bootinfo_kobj);
  5826. +fail:
  5827. + return ret;
  5828. +
  5829. +}
  5830. +
  5831. +static void __exit bootinfo_exit(void)
  5832. +{
  5833. + if (bootinfo_kobj) {
  5834. + sysfs_remove_group(bootinfo_kobj, &attr_group);
  5835. + kobject_del(bootinfo_kobj);
  5836. + }
  5837. +}
  5838. +
  5839. +core_initcall(bootinfo_init);
  5840. +module_exit(bootinfo_exit);
  5841. diff --git a/arch/arm64/kernel/hwconf_manager.c b/arch/arm64/kernel/hwconf_manager.c
  5842. new file mode 100644
  5843. index 0000000..8d1a507
  5844. --- /dev/null
  5845. +++ b/arch/arm64/kernel/hwconf_manager.c
  5846. @@ -0,0 +1,459 @@
  5847. +/*
  5848. + * hwconf_manager.c
  5849. + *
  5850. + * Copyright (C) 2017 XiaoMi, Inc.
  5851. + *
  5852. + * This program is free software; you can redistribute it and/or modify
  5853. + * it under the terms of the GNU General Public License version 2 as
  5854. + * published by the Free Software Foundation.
  5855. + */
  5856. +
  5857. +#include <linux/module.h>
  5858. +#include <linux/kernel.h>
  5859. +#include <linux/init.h>
  5860. +#include <linux/fs.h>
  5861. +#include <linux/string.h>
  5862. +#include <linux/slab.h>
  5863. +#include <linux/ctype.h>
  5864. +#include <linux/debugfs.h>
  5865. +#include <linux/crypto.h>
  5866. +#include <linux/cJSON.h>
  5867. +#include <asm/setup.h>
  5868. +#include <asm/hwconf_manager.h>
  5869. +
  5870. +struct hw_info_manager {
  5871. + cJSON *hw_config;
  5872. + cJSON *hw_monitor;
  5873. + struct crypto_cipher *tfm;
  5874. + struct kobject *hwconf_kobj;
  5875. + struct dentry *hwconf_check;
  5876. +};
  5877. +
  5878. +struct hw_info_manager *info_manager;
  5879. +
  5880. +#define INIT_KEY "0123456789"
  5881. +char crypto_key[32] = INIT_KEY;
  5882. +
  5883. +#define __HWINFO_DECRYPT_DEBUG__ 0
  5884. +
  5885. +#define hwconf_attr(_name) \
  5886. +static struct kobj_attribute _name##_attr = { \
  5887. + .attr = { \
  5888. + .name = __stringify(_name), \
  5889. + .mode = 0644, \
  5890. + }, \
  5891. + .show = _name##_show, \
  5892. + .store = _name##_store, \
  5893. +}
  5894. +
  5895. +int add_hw_component_info(char *component_name, char *key, char *value)
  5896. +{
  5897. + cJSON *component;
  5898. +
  5899. + if (!info_manager->hw_config) {
  5900. + pr_err("hwconfig_manager is still not ready.\n");
  5901. + return -EINVAL;
  5902. + }
  5903. +
  5904. + component = cJSON_GetObjectItem(info_manager->hw_config,
  5905. + component_name);
  5906. + if (!component)
  5907. + return -EINVAL;
  5908. +
  5909. + if (cJSON_HasObjectItem(component, key)) {
  5910. + pr_err("%s is added in %s already\n", key, component_name);
  5911. + return -EINVAL;
  5912. + }
  5913. +
  5914. + cJSON_AddStringToObject(component, key, value);
  5915. + pr_debug("%s: %s\n", __func__, cJSON_Print(component));
  5916. +
  5917. + return 0;
  5918. +}
  5919. +EXPORT_SYMBOL(add_hw_component_info);
  5920. +
  5921. +int register_hw_component_info(char *component_name)
  5922. +{
  5923. + cJSON *component;
  5924. +
  5925. + if (!info_manager->hw_config) {
  5926. + pr_err("hwconfig_manager is still not ready.\n");
  5927. + return -EINVAL;
  5928. + }
  5929. +
  5930. + component = cJSON_GetObjectItem(info_manager->hw_config,
  5931. + component_name);
  5932. + if (component) {
  5933. + pr_err("%s is registered already\n", component_name);
  5934. + return -EINVAL;
  5935. + }
  5936. +
  5937. + component = cJSON_CreateObject();
  5938. + cJSON_AddItemToObject(info_manager->hw_config,
  5939. + component_name, component);
  5940. + pr_debug("%s: %s\n", __func__, cJSON_Print(component));
  5941. +
  5942. + return 0;
  5943. +}
  5944. +EXPORT_SYMBOL(register_hw_component_info);
  5945. +
  5946. +int unregister_hw_component_info(char *component_name)
  5947. +{
  5948. + cJSON *component;
  5949. +
  5950. + if (!info_manager->hw_config) {
  5951. + pr_err("hwconfig_manager is still not ready.\n");
  5952. + return -EINVAL;
  5953. + }
  5954. +
  5955. + component = cJSON_GetObjectItem(info_manager->hw_config,
  5956. + component_name);
  5957. + if (!component)
  5958. + return -EINVAL;
  5959. +
  5960. + cJSON_DetachItemFromObject(info_manager->hw_config,
  5961. + component_name);
  5962. +
  5963. + return 0;
  5964. +}
  5965. +EXPORT_SYMBOL(unregister_hw_component_info);
  5966. +
  5967. +int update_hw_monitor_info(char *component_name, char *mon_key, char *mon_value)
  5968. +{
  5969. + cJSON *component;
  5970. +
  5971. + if (!info_manager->hw_monitor) {
  5972. + pr_err("hwconfig_manager is still not ready.\n");
  5973. + return -EINVAL;
  5974. + }
  5975. +
  5976. + component = cJSON_GetObjectItem(info_manager->hw_monitor,
  5977. + component_name);
  5978. + if (!component) {
  5979. + pr_err("No component %s\n", component_name);
  5980. + return -EINVAL;
  5981. + }
  5982. +
  5983. + if (!cJSON_HasObjectItem(component, mon_key)) {
  5984. + pr_err("No key %s\n", mon_key);
  5985. + return -EINVAL;
  5986. + }
  5987. +
  5988. + cJSON_DeleteItemFromObject(component, mon_key);
  5989. + cJSON_AddStringToObject(component, mon_key, mon_value);
  5990. +
  5991. + pr_debug("%s: %s\n", __func__, cJSON_Print(info_manager->hw_monitor));
  5992. +
  5993. + return 0;
  5994. +}
  5995. +EXPORT_SYMBOL(update_hw_monitor_info);
  5996. +
  5997. +int add_hw_monitor_info(char *component_name, char *mon_key, char *mon_value)
  5998. +{
  5999. + cJSON *component;
  6000. +
  6001. + if (!info_manager->hw_monitor) {
  6002. + pr_err("hwconfig_manager is still not ready.\n");
  6003. + return -EINVAL;
  6004. + }
  6005. +
  6006. + component = cJSON_GetObjectItem(info_manager->hw_monitor,
  6007. + component_name);
  6008. + if (!component)
  6009. + return -EINVAL;
  6010. +
  6011. + if (cJSON_HasObjectItem(component, mon_key)) {
  6012. + pr_err("%s is added in %s already\n", mon_key, component_name);
  6013. + return -EINVAL;
  6014. + }
  6015. +
  6016. + cJSON_AddStringToObject(component, mon_key, mon_value);
  6017. + pr_debug("%s: %s\n", __func__, cJSON_Print(component));
  6018. +
  6019. + return 0;
  6020. +}
  6021. +EXPORT_SYMBOL(add_hw_monitor_info);
  6022. +
  6023. +int register_hw_monitor_info(char *component_name)
  6024. +{
  6025. + cJSON *component;
  6026. +
  6027. + if (!info_manager->hw_monitor) {
  6028. + pr_err("hwconfig_manager is still not ready.\n");
  6029. + return -EINVAL;
  6030. + }
  6031. +
  6032. + component = cJSON_GetObjectItem(info_manager->hw_monitor,
  6033. + component_name);
  6034. + if (component) {
  6035. + pr_err("%s is registered already\n", component_name);
  6036. + return -EINVAL;
  6037. + }
  6038. +
  6039. + component = cJSON_CreateObject();
  6040. + cJSON_AddItemToObject(info_manager->hw_monitor,
  6041. + component_name, component);
  6042. + pr_debug("%s: %s\n", __func__, cJSON_Print(component));
  6043. +
  6044. + return 0;
  6045. +}
  6046. +EXPORT_SYMBOL(register_hw_monitor_info);
  6047. +
  6048. +int unregister_hw_monitor_info(char *component_name)
  6049. +{
  6050. + cJSON *component;
  6051. +
  6052. + if (!info_manager->hw_monitor) {
  6053. + pr_err("hwconfig_manager is still not ready.\n");
  6054. + return -EINVAL;
  6055. + }
  6056. +
  6057. + component = cJSON_GetObjectItem(info_manager->hw_monitor,
  6058. + component_name);
  6059. + if (!component)
  6060. + return -EINVAL;
  6061. +
  6062. + cJSON_DetachItemFromObject(info_manager->hw_monitor,
  6063. + component_name);
  6064. +
  6065. + return 0;
  6066. +}
  6067. +EXPORT_SYMBOL(unregister_hw_monitor_info);
  6068. +
  6069. +static ssize_t hw_info_store(struct kobject *kobj,
  6070. + struct kobj_attribute *attr, const char *buf,
  6071. + size_t count)
  6072. +{
  6073. + memcpy(crypto_key, buf, sizeof(crypto_key));
  6074. +
  6075. + pr_debug("%s crypto_key=%s\n", __func__, crypto_key);
  6076. +
  6077. + return count;
  6078. +}
  6079. +
  6080. +#if __HWINFO_DECRYPT_DEBUG__
  6081. +static int hw_info_decrypt_test(char *buf, size_t len)
  6082. +{
  6083. + char *dest;
  6084. + unsigned int blocksize;
  6085. + int i;
  6086. + int ret;
  6087. +
  6088. + info_manager->tfm = crypto_alloc_cipher("aes",
  6089. + CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_ASYNC);
  6090. + if (IS_ERR(info_manager->tfm)) {
  6091. + pr_err("Failed to load transform for aes mode!\n");
  6092. + ret = -EINVAL;
  6093. + goto out;
  6094. + }
  6095. +
  6096. + ret = crypto_cipher_setkey(info_manager->tfm, crypto_key,
  6097. + sizeof(crypto_key));
  6098. + if (ret) {
  6099. + pr_err("Failed to setkey\n");
  6100. + ret = -EINVAL;
  6101. + goto free_cipher;
  6102. + }
  6103. +
  6104. + blocksize = crypto_cipher_blocksize(info_manager->tfm);
  6105. + if (!blocksize) {
  6106. + ret = -EINVAL;
  6107. + goto free_cipher;
  6108. + }
  6109. +
  6110. + dest = kzalloc(len, GFP_KERNEL);
  6111. + if (!dest) {
  6112. + ret = -ENOMEM;
  6113. + goto free_cipher;
  6114. + }
  6115. +
  6116. + for (i = 0; i < len; i += blocksize)
  6117. + crypto_cipher_decrypt_one(info_manager->tfm,
  6118. + &dest[i], &buf[i]);
  6119. +
  6120. + pr_debug("%s: %s\n", __func__, dest);
  6121. +
  6122. + kfree(dest);
  6123. +free_cipher:
  6124. + crypto_free_cipher(info_manager->tfm);
  6125. +out:
  6126. + return ret;
  6127. +}
  6128. +#endif
  6129. +
  6130. +static ssize_t hw_info_show(struct kobject *kobj,
  6131. + struct kobj_attribute *attr, char *buf)
  6132. +{
  6133. + int ret;
  6134. + char *src = cJSON_Print(info_manager->hw_config);
  6135. + int i;
  6136. + unsigned int blocksize;
  6137. + char *padding;
  6138. + int blocks = 0;
  6139. +
  6140. + if (!strncmp(crypto_key, INIT_KEY, sizeof(crypto_key))) {
  6141. + pr_err("crypto_key == INIT_KEY\n");
  6142. + return 0;
  6143. + }
  6144. +
  6145. + /* Allocate transform for AES CRYPTO_ALG_TYPE_BLKCIPHER */
  6146. + info_manager->tfm = crypto_alloc_cipher("aes",
  6147. + CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_ASYNC);
  6148. + if (IS_ERR(info_manager->tfm)) {
  6149. + pr_err("Failed to load transform for aes mode!\n");
  6150. + return 0;
  6151. + }
  6152. +
  6153. + pr_debug("%s crypto_key=%s\n", __func__, crypto_key);
  6154. + ret = crypto_cipher_setkey(info_manager->tfm, crypto_key,
  6155. + sizeof(crypto_key));
  6156. + if (ret) {
  6157. + pr_err("Failed to setkey\n");
  6158. + crypto_free_cipher(info_manager->tfm);
  6159. + return 0;
  6160. + }
  6161. +
  6162. + blocksize = crypto_cipher_blocksize(info_manager->tfm);
  6163. + if (!blocksize)
  6164. + return 0;
  6165. +
  6166. + padding = kmalloc(blocksize + 1, GFP_KERNEL);
  6167. + if (!padding)
  6168. + return -ENOMEM;
  6169. +
  6170. + /* start encrypt */
  6171. + for (i = 0; i < strlen(src); i += blocksize) {
  6172. + memset(padding, 0, blocksize + 1);
  6173. + strlcpy(padding, &src[i], blocksize + 1);
  6174. + crypto_cipher_encrypt_one(info_manager->tfm,
  6175. + &buf[i], padding);
  6176. + blocks++;
  6177. + }
  6178. +
  6179. + kfree(padding);
  6180. + crypto_free_cipher(info_manager->tfm);
  6181. +
  6182. +#if __HWINFO_DECRYPT_DEBUG__
  6183. + hw_info_decrypt_test(buf, blocks * blocksize);
  6184. +#endif
  6185. +
  6186. + return blocks * blocksize;
  6187. +}
  6188. +
  6189. +static ssize_t hw_mon_store(struct kobject *kobj,
  6190. + struct kobj_attribute *attr, const char *buf,
  6191. + size_t count)
  6192. +{
  6193. + int on = 99;
  6194. + char component_name[32] = { 0 };
  6195. + int len;
  6196. +
  6197. + len = sscanf(buf, "%s %d", component_name, &on);
  6198. +
  6199. + pr_debug("%s component_name=%s, on=%d\n", __func__, component_name, on);
  6200. +
  6201. + if (on == 0)
  6202. + unregister_hw_monitor_info(component_name);
  6203. +
  6204. + return count;
  6205. +}
  6206. +
  6207. +static ssize_t hw_mon_show(struct kobject *kobj,
  6208. + struct kobj_attribute *attr, char *buf)
  6209. +{
  6210. + return snprintf(buf, PAGE_SIZE, "%s\n",
  6211. + cJSON_Print(info_manager->hw_monitor));
  6212. +}
  6213. +
  6214. +hwconf_attr(hw_info);
  6215. +hwconf_attr(hw_mon);
  6216. +
  6217. +static struct attribute *g[] = {
  6218. + &hw_info_attr.attr,
  6219. + &hw_mon_attr.attr,
  6220. + NULL,
  6221. +};
  6222. +
  6223. +static struct attribute_group attr_group = {
  6224. + .attrs = g,
  6225. +};
  6226. +
  6227. +static int hwconf_debugfs_get(void *data, u64 *val)
  6228. +{
  6229. + pr_debug("hw_config:\n%s\n", cJSON_Print(info_manager->hw_config));
  6230. + pr_debug("hw_monitor:\n%s\n", cJSON_Print(info_manager->hw_monitor));
  6231. + *val = 0;
  6232. + return 0;
  6233. +}
  6234. +
  6235. +static int hwconf_debugfs_set(void *data, u64 val)
  6236. +{
  6237. + if (val == 1) {
  6238. + register_hw_component_info("debugfs_hwconf");
  6239. + add_hw_component_info("debugfs_hwconf", "key1", "value1");
  6240. +
  6241. + register_hw_monitor_info("debugfs_hwmon");
  6242. + add_hw_monitor_info("debugfs_hwmon", "key2", "value2");
  6243. + } else if (val == 2) {
  6244. + update_hw_monitor_info("debugfs_hwmon", "key2", "value3");
  6245. + } else if (val == 3) {
  6246. + unregister_hw_component_info("debugfs_hwconf");
  6247. + unregister_hw_monitor_info("debugfs_hwmon");
  6248. + }
  6249. + return 0;
  6250. +}
  6251. +DEFINE_SIMPLE_ATTRIBUTE(hwconf_check_fops, hwconf_debugfs_get,
  6252. + hwconf_debugfs_set, "%llu\n");
  6253. +
  6254. +static int __init hwconf_init(void)
  6255. +{
  6256. + int ret = -ENOMEM;
  6257. +
  6258. + info_manager = kmalloc(sizeof(*info_manager), GFP_KERNEL);
  6259. + if (!info_manager)
  6260. + return ret;
  6261. +
  6262. + info_manager->hw_config = cJSON_CreateObject();
  6263. + info_manager->hw_monitor = cJSON_CreateObject();
  6264. +
  6265. + info_manager->hwconf_kobj = kobject_create_and_add("hwconf", NULL);
  6266. + if (!info_manager->hwconf_kobj) {
  6267. + pr_err("hwconf_init: subsystem_register failed\n");
  6268. + goto fail;
  6269. + }
  6270. +
  6271. + ret = sysfs_create_group(info_manager->hwconf_kobj, &attr_group);
  6272. + if (ret) {
  6273. + pr_err("hwconf_init: subsystem_register failed\n");
  6274. + goto sys_fail;
  6275. + }
  6276. +
  6277. + info_manager->hwconf_check = debugfs_create_file("hwconf_check",
  6278. + 0644, NULL, NULL, &hwconf_check_fops);
  6279. +
  6280. + return ret;
  6281. +
  6282. +sys_fail:
  6283. + kobject_del(info_manager->hwconf_kobj);
  6284. +fail:
  6285. + cJSON_Delete(info_manager->hw_config);
  6286. + cJSON_Delete(info_manager->hw_monitor);
  6287. + kfree(info_manager);
  6288. +
  6289. + return ret;
  6290. +}
  6291. +
  6292. +static void __exit hwconf_exit(void)
  6293. +{
  6294. + cJSON_Delete(info_manager->hw_config);
  6295. + cJSON_Delete(info_manager->hw_monitor);
  6296. +
  6297. + if (info_manager->hwconf_kobj) {
  6298. + sysfs_remove_group(info_manager->hwconf_kobj, &attr_group);
  6299. + kobject_del(info_manager->hwconf_kobj);
  6300. + }
  6301. + debugfs_remove(info_manager->hwconf_check);
  6302. +}
  6303. +
  6304. +core_initcall(hwconf_init);
  6305. +module_exit(hwconf_exit);
  6306. diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
  6307. index 5a09efa..1a189b5 100644
  6308. --- a/arch/arm64/kernel/process.c
  6309. +++ b/arch/arm64/kernel/process.c
  6310. @@ -260,7 +260,7 @@ void __show_regs(struct pt_regs *regs)
  6311. printk("\n");
  6312. }
  6313. if (!user_mode(regs))
  6314. - show_extra_register_data(regs, 64);
  6315. + show_extra_register_data(regs, 256);
  6316. printk("\n");
  6317. }
  6318.  
  6319. diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
  6320. index 326c53b..76c4a02 100644
  6321. --- a/arch/arm64/kernel/setup.c
  6322. +++ b/arch/arm64/kernel/setup.c
  6323. @@ -3,6 +3,7 @@
  6324. *
  6325. * Copyright (C) 1995-2001 Russell King
  6326. * Copyright (C) 2012 ARM Ltd.
  6327. + * Copyright (C) 2017 XiaoMi, Inc.
  6328. *
  6329. * This program is free software; you can redistribute it and/or modify
  6330. * it under the terms of the GNU General Public License version 2 as
  6331. @@ -65,6 +66,17 @@
  6332. #include <asm/xen/hypervisor.h>
  6333. #include <asm/mmu_context.h>
  6334.  
  6335. +#include <asm/bootinfo.h>
  6336. +
  6337. +#ifdef CONFIG_OF_FLATTREE
  6338. +void __init early_init_dt_setup_pureason_arch(unsigned long pu_reason)
  6339. +{
  6340. + set_powerup_reason(pu_reason);
  6341. + pr_info("Powerup reason=0x%x\n", get_powerup_reason());
  6342. +}
  6343. +#endif
  6344. +
  6345. +
  6346. unsigned int boot_reason;
  6347. EXPORT_SYMBOL(boot_reason);
  6348.  
  6349. diff --git a/drivers/Makefile b/drivers/Makefile
  6350. index eb67aad..7ee655c 100644
  6351. --- a/drivers/Makefile
  6352. +++ b/drivers/Makefile
  6353. @@ -50,7 +50,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/
  6354. obj-y += tty/
  6355. obj-y += char/
  6356.  
  6357. -
  6358. +obj-y += elliptic/
  6359. # gpu/ comes after char for AGP vs DRM startup and after iommu
  6360. obj-y += gpu/
  6361.  
  6362. diff --git a/drivers/android/binder.c b/drivers/android/binder.c
  6363. index 5ce31c8..285ffcc 100644
  6364. --- a/drivers/android/binder.c
  6365. +++ b/drivers/android/binder.c
  6366. @@ -3,6 +3,7 @@
  6367. * Android IPC Subsystem
  6368. *
  6369. * Copyright (C) 2007-2008 Google, Inc.
  6370. + * Copyright (C) 2017 XiaoMi, Inc.
  6371. *
  6372. * This software is licensed under the terms of the GNU General Public
  6373. * License version 2, as published by the Free Software Foundation, and
  6374. @@ -2500,7 +2501,7 @@ static int binder_thread_write(struct binder_proc *proc,
  6375. if (list_empty(&buffer->target_node->async_todo))
  6376. buffer->target_node->has_async_transaction = 0;
  6377. else
  6378. - list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
  6379. + list_move_tail(buffer->target_node->async_todo.next, &proc->todo);
  6380. }
  6381. trace_binder_transaction_buffer_release(buffer);
  6382. binder_transaction_buffer_release(proc, buffer, NULL);
  6383. diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
  6384. index 09c07f5..292d888 100644
  6385. --- a/drivers/base/power/wakeup.c
  6386. +++ b/drivers/base/power/wakeup.c
  6387. @@ -2,6 +2,7 @@
  6388. * drivers/base/power/wakeup.c - System wakeup events framework
  6389. *
  6390. * Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
  6391. + * Copyright (C) 2017 XiaoMi, Inc.
  6392. *
  6393. * This file is released under the GPLv2.
  6394. */
  6395. @@ -870,6 +871,7 @@ EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
  6396. * since the old value was stored. Also return true if the current number of
  6397. * wakeup events being processed is different from zero.
  6398. */
  6399. +bool wakeup_irq_abort_suspend;
  6400. bool pm_wakeup_pending(void)
  6401. {
  6402. unsigned long flags;
  6403. @@ -896,6 +898,7 @@ bool pm_wakeup_pending(void)
  6404. void pm_system_wakeup(void)
  6405. {
  6406. pm_abort_suspend = true;
  6407. + wakeup_irq_abort_suspend = true;
  6408. freeze_wake();
  6409. }
  6410. EXPORT_SYMBOL_GPL(pm_system_wakeup);
  6411. @@ -903,6 +906,7 @@ EXPORT_SYMBOL_GPL(pm_system_wakeup);
  6412. void pm_wakeup_clear(void)
  6413. {
  6414. pm_abort_suspend = false;
  6415. + wakeup_irq_abort_suspend = false;
  6416. pm_wakeup_irq = 0;
  6417. }
  6418.  
  6419. diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c
  6420. index 96c34a9..43fc837 100644
  6421. --- a/drivers/base/syscore.c
  6422. +++ b/drivers/base/syscore.c
  6423. @@ -2,6 +2,7 @@
  6424. * syscore.c - Execution of system core operations.
  6425. *
  6426. * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
  6427. + * Copyright (C) 2017 XiaoMi, Inc.
  6428. *
  6429. * This file is released under the GPLv2.
  6430. */
  6431. @@ -46,17 +47,25 @@ EXPORT_SYMBOL_GPL(unregister_syscore_ops);
  6432. *
  6433. * This function is executed with one CPU on-line and disabled interrupts.
  6434. */
  6435. +extern bool wakeup_irq_abort_suspend;
  6436. int syscore_suspend(void)
  6437. {
  6438. struct syscore_ops *ops;
  6439. int ret = 0;
  6440. + char suspend_abort[MAX_SUSPEND_ABORT_LEN];
  6441.  
  6442. trace_suspend_resume(TPS("syscore_suspend"), 0, true);
  6443. pr_debug("Checking wakeup interrupts\n");
  6444.  
  6445. /* Return error code if there are any wakeup interrupts pending. */
  6446. - if (pm_wakeup_pending())
  6447. + if (pm_wakeup_pending()) {
  6448. + if (wakeup_irq_abort_suspend == false) {
  6449. + pm_get_active_wakeup_sources(suspend_abort, MAX_SUSPEND_ABORT_LEN);
  6450. + log_suspend_abort_reason(suspend_abort);
  6451. + }
  6452. + pr_err("PM: Abort system core suspend, wakeup interrupt or wakeup source detected");
  6453. return -EBUSY;
  6454. + }
  6455.  
  6456. WARN_ONCE(!irqs_disabled(),
  6457. "Interrupts enabled before system core suspend.\n");
  6458. diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
  6459. index 3c59417..fc7bfcb 100644
  6460. --- a/drivers/block/zram/zram_drv.c
  6461. +++ b/drivers/block/zram/zram_drv.c
  6462. @@ -3,6 +3,7 @@
  6463. *
  6464. * Copyright (C) 2008, 2009, 2010 Nitin Gupta
  6465. * 2012, 2013 Minchan Kim
  6466. + * Copyright (C) 2017 XiaoMi, Inc.
  6467. *
  6468. * This code is released using a dual license strategy: BSD/GPL
  6469. * You can choose the licence that better fits your requirements.
  6470. @@ -49,6 +50,7 @@ static const char *default_compressor = "lzo";
  6471.  
  6472. /* Module params (documentation at end) */
  6473. static unsigned int num_devices = 1;
  6474. +static struct zram **zram_devices;
  6475.  
  6476. static inline void deprecated_attr_warn(const char *name)
  6477. {
  6478. @@ -411,6 +413,31 @@ static ssize_t compact_store(struct device *dev,
  6479. return len;
  6480. }
  6481.  
  6482. +int zs_get_page_usage(unsigned long *total_pool_pages,
  6483. + unsigned long *total_ori_pages)
  6484. +{
  6485. + int i;
  6486. + *total_pool_pages = *total_ori_pages = 0;
  6487. + if (!zram_devices)
  6488. + return 0;
  6489. + for (i = 0; i < num_devices; i++) {
  6490. + struct zram *zram = zram_devices[i];
  6491. + struct zram_meta *meta;
  6492. + if (!zram)
  6493. + return 0;
  6494. + meta = zram->meta;
  6495. + if (!down_read_trylock(&zram->init_lock))
  6496. + continue;
  6497. + if (init_done(zram)) {
  6498. + *total_pool_pages += zs_get_total_pages(meta->mem_pool);
  6499. + *total_ori_pages += atomic64_read(
  6500. + &zram->stats.pages_stored);
  6501. + }
  6502. + up_read(&zram->init_lock);
  6503. + }
  6504. + return 0;
  6505. +}
  6506. +
  6507. static ssize_t io_stat_show(struct device *dev,
  6508. struct device_attribute *attr, char *buf)
  6509. {
  6510. @@ -1204,7 +1231,7 @@ static int zram_add(void)
  6511. {
  6512. struct zram *zram;
  6513. struct request_queue *queue;
  6514. - int ret, device_id;
  6515. + int i, ret, device_id;
  6516.  
  6517. zram = kzalloc(sizeof(struct zram), GFP_KERNEL);
  6518. if (!zram)
  6519. @@ -1288,6 +1315,13 @@ static int zram_add(void)
  6520. zram->meta = NULL;
  6521. zram->max_comp_streams = 1;
  6522.  
  6523. + for (i = 0; i < num_devices; i++) {
  6524. + if (!zram_devices[i]) {
  6525. + zram_devices[i] = zram;
  6526. + break;
  6527. + }
  6528. + }
  6529. +
  6530. pr_info("Added device: %s\n", zram->disk->disk_name);
  6531. return device_id;
  6532.  
  6533. @@ -1410,6 +1444,7 @@ static int zram_remove_cb(int id, void *ptr, void *data)
  6534.  
  6535. static void destroy_devices(void)
  6536. {
  6537. + kfree(zram_devices);
  6538. class_unregister(&zram_control_class);
  6539. idr_for_each(&zram_index_idr, &zram_remove_cb, NULL);
  6540. idr_destroy(&zram_index_idr);
  6541. @@ -1420,6 +1455,10 @@ static int __init zram_init(void)
  6542. {
  6543. int ret;
  6544.  
  6545. + zram_devices = kzalloc(num_devices * sizeof(struct zram *), GFP_KERNEL);
  6546. + if (!zram_devices)
  6547. + return -ENOMEM;
  6548. +
  6549. ret = class_register(&zram_control_class);
  6550. if (ret) {
  6551. pr_err("Unable to register zram-control class\n");
  6552. diff --git a/drivers/bluetooth/btfm_slim.h b/drivers/bluetooth/btfm_slim.h
  6553. index e67c696..bff12f0 100644
  6554. --- a/drivers/bluetooth/btfm_slim.h
  6555. +++ b/drivers/bluetooth/btfm_slim.h
  6556. @@ -1,4 +1,5 @@
  6557. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  6558. + * Copyright (C) 2017 XiaoMi, Inc.
  6559. *
  6560. * This program is free software; you can redistribute it and/or modify
  6561. * it under the terms of the GNU General Public License version 2 and
  6562. @@ -68,6 +69,7 @@ struct btfmslim {
  6563.  
  6564. uint32_t num_rx_port;
  6565. uint32_t num_tx_port;
  6566. + uint32_t sample_rate;
  6567.  
  6568. struct btfmslim_ch *rx_chs;
  6569. struct btfmslim_ch *tx_chs;
  6570. diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
  6571. index 1ed366f..db72144 100644
  6572. --- a/drivers/bluetooth/btfm_slim_codec.c
  6573. +++ b/drivers/bluetooth/btfm_slim_codec.c
  6574. @@ -1,4 +1,5 @@
  6575. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  6576. + * Copyright (C) 2017 XiaoMi, Inc.
  6577. *
  6578. * This program is free software; you can redistribute it and/or modify
  6579. * it under the terms of the GNU General Public License version 2 and
  6580. @@ -134,6 +135,9 @@ int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
  6581. BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
  6582. dai->id, dai->rate);
  6583.  
  6584. + /* save sample rate */
  6585. + btfmslim->sample_rate = dai->rate;
  6586. +
  6587. switch (dai->id) {
  6588. case BTFM_FM_SLIM_TX:
  6589. grp = true; nchan = 2;
  6590. diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
  6591. index a451ff3..f081fa0 100644
  6592. --- a/drivers/bluetooth/btfm_slim_wcn3990.c
  6593. +++ b/drivers/bluetooth/btfm_slim_wcn3990.c
  6594. @@ -1,4 +1,5 @@
  6595. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  6596. + * Copyright (C) 2017 XiaoMi, Inc.
  6597. *
  6598. * This program is free software; you can redistribute it and/or modify
  6599. * it under the terms of the GNU General Public License version 2 and
  6600. @@ -120,18 +121,6 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
  6601. BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
  6602. goto error;
  6603. }
  6604. - } else if (port_num == CHRK_SB_PGD_PORT_TX_SCO) {
  6605. - /* SCO Tx */
  6606. - reg_val = 0x1 << CHRK_SB_PGD_PORT_TX_SCO;
  6607. - reg = CHRK_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
  6608. - BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
  6609. - reg_val, reg);
  6610. - ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
  6611. - if (ret) {
  6612. - BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
  6613. - ret, reg);
  6614. - goto error;
  6615. - }
  6616. }
  6617.  
  6618. /* Enable Tx port hw auto recovery for underrun or overrun error */
  6619. diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
  6620. index 3c10462..d5bdd80 100644
  6621. --- a/drivers/char/diag/diag_masks.c
  6622. +++ b/drivers/char/diag/diag_masks.c
  6623. @@ -1,4 +1,5 @@
  6624. /* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
  6625. + * Copyright (C) 2017 XiaoMi, Inc.
  6626. *
  6627. * This program is free software; you can redistribute it and/or modify
  6628. * it under the terms of the GNU General Public License version 2 and
  6629. @@ -707,6 +708,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
  6630. pr_err_ratelimited("diag: In %s, unable to allocate memory for msg mask ptr, mask_size: %d\n",
  6631. __func__, mask_size);
  6632. mutex_unlock(&mask->lock);
  6633. + mutex_unlock(&mask_info->lock);
  6634. return -ENOMEM;
  6635. }
  6636. mask->ptr = temp;
  6637. diff --git a/drivers/clk/msm/clock-debug.c b/drivers/clk/msm/clock-debug.c
  6638. index 0fe93ed..4bb2980 100644
  6639. --- a/drivers/clk/msm/clock-debug.c
  6640. +++ b/drivers/clk/msm/clock-debug.c
  6641. @@ -35,7 +35,7 @@ static LIST_HEAD(clk_list);
  6642. static DEFINE_MUTEX(clk_list_lock);
  6643.  
  6644. static struct dentry *debugfs_base;
  6645. -static u32 debug_suspend;
  6646. +static u32 debug_suspend = 1;
  6647.  
  6648. static int clock_debug_rate_set(void *data, u64 val)
  6649. {
  6650. diff --git a/drivers/clk/msm/clock-mmss-8998.c b/drivers/clk/msm/clock-mmss-8998.c
  6651. index fdaaa72..63d0e18 100644
  6652. --- a/drivers/clk/msm/clock-mmss-8998.c
  6653. +++ b/drivers/clk/msm/clock-mmss-8998.c
  6654. @@ -1,4 +1,5 @@
  6655. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  6656. + * Copyright (C) 2017 XiaoMi, Inc.
  6657. *
  6658. * This program is free software; you can redistribute it and/or modify
  6659. * it under the terms of the GNU General Public License version 2 and
  6660. @@ -359,6 +360,7 @@ static struct rcg_clk mdp_clk_src = {
  6661. .set_rate = set_rate_hid,
  6662. .freq_tbl = ftbl_mdp_clk_src,
  6663. .current_freq = &rcg_dummy_freq,
  6664. + .non_local_control_timeout = 1000,
  6665. .non_local_children = true,
  6666. .base = &virt_base,
  6667. .c = {
  6668. diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c b/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c
  6669. index ad6d80d..36e4c05 100644
  6670. --- a/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c
  6671. +++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8998.c
  6672. @@ -156,7 +156,7 @@ static void dsi_pll_config_slave(struct mdss_pll_resources *rsc)
  6673. rsc->slave = NULL;
  6674.  
  6675. if (!orsc) {
  6676. - pr_warn("slave PLL unavilable, assuming standalone config\n");
  6677. + pr_debug("slave PLL unavilable, assuming standalone config\n");
  6678. return;
  6679. }
  6680.  
  6681. diff --git a/drivers/elliptic/Makefile b/drivers/elliptic/Makefile
  6682. new file mode 100644
  6683. index 0000000..b4161b6
  6684. --- /dev/null
  6685. +++ b/drivers/elliptic/Makefile
  6686. @@ -0,0 +1,17 @@
  6687. +ccflags-y := -I$(src) -Wall -Werror
  6688. +IO_MODULE := msm
  6689. +MIXER_MODULE := test
  6690. +
  6691. +EXTRA_CFLAGS += -DDEBUG
  6692. +
  6693. +obj-y += elliptic.o io_modules/$(IO_MODULE)/elliptic_data_io.o elliptic_sysfs.o
  6694. +# elliptic_driver-y := elliptic.o
  6695. +# elliptic_driver-y += io_modules/$(IO_MODULE)/elliptic_data_io.o
  6696. +# elliptic_driver-y += mixer_controls/$(MIXER_MODULE)/elliptic_mixer_controls.o
  6697. +# elliptic_driver-y += elliptic_sysfs.o
  6698. +
  6699. +# .PHONY: clean
  6700. +# all:
  6701. +# make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
  6702. +# clean:
  6703. +# rm *.o *.ko
  6704. diff --git a/drivers/elliptic/elliptic.c b/drivers/elliptic/elliptic.c
  6705. new file mode 100644
  6706. index 0000000..a399f14
  6707. --- /dev/null
  6708. +++ b/drivers/elliptic/elliptic.c
  6709. @@ -0,0 +1,716 @@
  6710. +/**
  6711. +* Copyright Elliptic Labs
  6712. +* Copyright (C) 2017 XiaoMi, Inc.
  6713. +*
  6714. +*/
  6715. +/* #define DEBUG*/
  6716. +#include <linux/module.h>
  6717. +#include <linux/kernel.h>
  6718. +#include <linux/version.h>
  6719. +/* includes the file structure, that is, file open read close */
  6720. +#include <linux/fs.h>
  6721. +
  6722. +#include <sound/apr_elliptic.h>
  6723. +
  6724. +/* include the character device, makes cdev avilable */
  6725. +#include <linux/cdev.h>
  6726. +#include <linux/semaphore.h>
  6727. +
  6728. +/* includes copy_user vice versa */
  6729. +#include <linux/uaccess.h>
  6730. +#include <linux/spinlock.h>
  6731. +#include <linux/slab.h>
  6732. +#include <linux/stat.h>
  6733. +#include <linux/init.h>
  6734. +#include <linux/platform_device.h>
  6735. +#include <linux/types.h>
  6736. +#include <linux/kdev_t.h>
  6737. +#include <linux/device.h>
  6738. +
  6739. +#include <linux/pm_wakeup.h>
  6740. +#include <linux/kfifo.h>
  6741. +#include <linux/poll.h>
  6742. +#include <linux/kobject.h>
  6743. +
  6744. +#include "elliptic_sysfs.h"
  6745. +#include "elliptic_device.h"
  6746. +#include "elliptic_data_io.h"
  6747. +
  6748. +static struct elliptic_device *elliptic_devices;
  6749. +
  6750. +/* Global variable for the device class*/
  6751. +struct class *elliptic_class;
  6752. +
  6753. +typedef uint32_t el_fifo_size_t;
  6754. +
  6755. +/* Major number provided by the kernel*/
  6756. +static dev_t elliptic_major;
  6757. +
  6758. +static struct wakeup_source *wake_source;
  6759. +
  6760. +
  6761. +void elliptic_data_reset_debug_counters(struct elliptic_data
  6762. + *elliptic_data) {
  6763. +
  6764. + elliptic_data->isr_fifo_flush_count = 0;
  6765. + elliptic_data->userspace_fifo_flush_count = 0;
  6766. +}
  6767. +
  6768. +void elliptic_data_print_debug_counters(struct elliptic_data
  6769. + *elliptic_data) {
  6770. +
  6771. + if (elliptic_data->isr_fifo_flush_count > 0) {
  6772. + EL_PRINT_E("isr fifo flushed %u times",
  6773. + elliptic_data->isr_fifo_flush_count);
  6774. + }
  6775. +
  6776. + if (elliptic_data->userspace_fifo_flush_count > 0) {
  6777. + EL_PRINT_E("userspace fifo flushed %u times",
  6778. + elliptic_data->userspace_fifo_flush_count);
  6779. + }
  6780. +
  6781. + if (elliptic_data->userspace_read_total !=
  6782. + elliptic_data->isr_write_total) {
  6783. + EL_PRINT_I("user space reads / isr writes : %u / %u",
  6784. + elliptic_data->userspace_read_total,
  6785. + elliptic_data->isr_write_total);
  6786. + }
  6787. +
  6788. + EL_PRINT_I(
  6789. + "total isr fifo flushed count : %u",
  6790. + elliptic_data->isr_fifo_flush_count_total);
  6791. +
  6792. + EL_PRINT_I("total userspace fifo flushed count : %u",
  6793. + elliptic_data->userspace_fifo_flush_count_total);
  6794. +
  6795. +
  6796. +}
  6797. +
  6798. +void elliptic_data_update_debug_counters(struct elliptic_data
  6799. + *elliptic_data)
  6800. +{
  6801. + elliptic_data->isr_fifo_flush_count_total +=
  6802. + elliptic_data->isr_fifo_flush_count;
  6803. + elliptic_data->userspace_fifo_flush_count_total +=
  6804. + elliptic_data->userspace_fifo_flush_count;
  6805. +}
  6806. +
  6807. +
  6808. +/* spin lock for isr must be held prior to calling */
  6809. +static void elliptic_data_flush_isr_fifo(struct elliptic_data
  6810. + *elliptic_data)
  6811. +{
  6812. + kfifo_reset(&elliptic_data->fifo_isr);
  6813. +}
  6814. +
  6815. +/* mutex lock for user space copy must be held prior to calling */
  6816. +static void elliptic_data_flush_userspace_fifo(struct elliptic_data
  6817. + *elliptic_data)
  6818. +{
  6819. + kfifo_reset(&elliptic_data->fifo_userspace);
  6820. +}
  6821. +
  6822. +/* inode refers to the actual file on disk */
  6823. +static int device_open(struct inode *inode, struct file *filp)
  6824. +{
  6825. + unsigned int major;
  6826. + unsigned int minor;
  6827. + struct elliptic_device *dev;
  6828. + struct elliptic_data *elliptic_data;
  6829. +
  6830. + major = imajor(inode);
  6831. + minor = iminor(inode);
  6832. +
  6833. + if (major != elliptic_major || minor < 0
  6834. + || minor >= ELLIPTIC_NUM_DEVICES) {
  6835. + EL_PRINT_W("no device found with minor=%d and major=%d",
  6836. + major, minor);
  6837. + return -ENODEV; /* No such device */
  6838. + }
  6839. +
  6840. + dev = NULL;
  6841. + dev = &elliptic_devices[minor];
  6842. + filp->private_data = dev;
  6843. +
  6844. + if (inode->i_cdev != &dev->cdev) {
  6845. + EL_PRINT_W("dev pointer mismatch");
  6846. + return -ENODEV; /* No such device */
  6847. + }
  6848. +
  6849. + if (down_interruptible(&dev->sem) != 0) {
  6850. + EL_PRINT_E("the device has been opened, unable to open lock");
  6851. + return -EINVAL;
  6852. + }
  6853. +
  6854. + elliptic_data = &dev->el_data;
  6855. + spin_lock(&elliptic_data->fifo_isr_spinlock);
  6856. + elliptic_data_flush_isr_fifo(elliptic_data);
  6857. + spin_unlock(&elliptic_data->fifo_isr_spinlock);
  6858. +
  6859. + mutex_lock(&elliptic_data->fifo_usp_lock);
  6860. + elliptic_data_flush_userspace_fifo(elliptic_data);
  6861. + mutex_unlock(&elliptic_data->fifo_usp_lock);
  6862. +
  6863. + elliptic_data_reset_debug_counters(elliptic_data);
  6864. +
  6865. + EL_PRINT_I("Opened device elliptic%u", minor);
  6866. + dev->opened = 1;
  6867. + return 0;
  6868. +}
  6869. +
  6870. +static void elliptic_data_work_handler(struct work_struct *ws)
  6871. +{
  6872. + struct elliptic_data *elliptic_data;
  6873. + unsigned long flags;
  6874. +
  6875. + unsigned int fifo_result = 0;
  6876. + size_t available_space = 0;
  6877. +
  6878. + elliptic_data = container_of(ws, struct elliptic_data, work);
  6879. +
  6880. + if (kfifo_is_empty(&elliptic_data->fifo_isr)) {
  6881. + EL_PRINT_W("work handler called when isr fifo is empty");
  6882. + return;
  6883. + }
  6884. +
  6885. + mutex_lock(&elliptic_data->fifo_usp_lock);
  6886. +
  6887. + spin_lock_irqsave(&elliptic_data->fifo_isr_spinlock, flags);
  6888. +
  6889. + fifo_result = kfifo_out(&elliptic_data->fifo_isr,
  6890. + elliptic_data->isr_swap_buffer, ELLIPTIC_MSG_BUF_SIZE);
  6891. + if (fifo_result == 0) {
  6892. + EL_PRINT_E("failed to copy from fifo isr to swap buffer %u",
  6893. + fifo_result);
  6894. + goto fail;
  6895. + }
  6896. +
  6897. + available_space = kfifo_avail(&elliptic_data->fifo_userspace);
  6898. +
  6899. + if (available_space < ELLIPTIC_MSG_BUF_SIZE) {
  6900. + EL_PRINT_E("available_space %lu, entry_size %lu. Flushing fifo",
  6901. + available_space, (size_t)ELLIPTIC_MSG_BUF_SIZE);
  6902. +
  6903. + ++elliptic_data->userspace_fifo_flush_count;
  6904. + elliptic_data_flush_userspace_fifo(elliptic_data);
  6905. + goto fail;
  6906. + }
  6907. +
  6908. + fifo_result = kfifo_in(&elliptic_data->fifo_userspace,
  6909. + elliptic_data->isr_swap_buffer, ELLIPTIC_MSG_BUF_SIZE);
  6910. + if (fifo_result == 0) {
  6911. + EL_PRINT_E("failed to copy from swap to fifo user space: %u",
  6912. + fifo_result);
  6913. + goto fail;
  6914. + }
  6915. +
  6916. + spin_unlock_irqrestore(&elliptic_data->fifo_isr_spinlock, flags);
  6917. + mutex_unlock(&elliptic_data->fifo_usp_lock);
  6918. + wake_up_interruptible(&elliptic_data->fifo_usp_not_empty);
  6919. + __pm_wakeup_event(wake_source, elliptic_data->wakeup_timeout);
  6920. + return;
  6921. +
  6922. +fail:
  6923. + spin_unlock_irqrestore(&elliptic_data->fifo_isr_spinlock, flags);
  6924. + mutex_unlock(&elliptic_data->fifo_usp_lock);
  6925. +
  6926. +}
  6927. +
  6928. +#define WORK_QUEUE_HANDLER_NAME_LENGTH 64
  6929. +int elliptic_data_initialize(struct elliptic_data
  6930. + *elliptic_data, size_t queue_size,
  6931. + unsigned int wakeup_timeout, int id)
  6932. +{
  6933. + int is_power_of_two;
  6934. +
  6935. + char name[WORK_QUEUE_HANDLER_NAME_LENGTH] = {0};
  6936. +
  6937. + is_power_of_two = (queue_size != 0) && !(queue_size & (queue_size - 1));
  6938. +
  6939. + if (is_power_of_two != 1) {
  6940. + EL_PRINT_E("non power of 2 fifo size");
  6941. + return -EINVAL;
  6942. + }
  6943. +
  6944. + if (kfifo_alloc(&elliptic_data->fifo_isr,
  6945. + queue_size, GFP_KERNEL) != 0) {
  6946. + EL_PRINT_E("failed to allocate fifo isr");
  6947. + return -EINVAL;
  6948. + }
  6949. +
  6950. + if (kfifo_alloc(&elliptic_data->fifo_userspace,
  6951. + queue_size, GFP_KERNEL) != 0) {
  6952. +
  6953. + EL_PRINT_E("failed to allocate fifo user space");
  6954. + return -EINVAL;
  6955. + }
  6956. +
  6957. +
  6958. + atomic_set(&elliptic_data->abort_io, 0);
  6959. + spin_lock_init(&elliptic_data->fifo_isr_spinlock);
  6960. +
  6961. + INIT_WORK(&elliptic_data->work, elliptic_data_work_handler);
  6962. + mutex_init(&elliptic_data->fifo_usp_lock);
  6963. + init_waitqueue_head(&elliptic_data->fifo_usp_not_empty);
  6964. +
  6965. + snprintf(name, WORK_QUEUE_HANDLER_NAME_LENGTH,
  6966. + "%s_%d", "ELLIPTIC_DATA_WORK_HANDLER", id);
  6967. + elliptic_data->wq = create_singlethread_workqueue(name);
  6968. +
  6969. + return 0;
  6970. +}
  6971. +
  6972. +int elliptic_data_cleanup(struct elliptic_data *elliptic_data)
  6973. +{
  6974. + spin_unlock(&elliptic_data->fifo_isr_spinlock);
  6975. + kfifo_free(&elliptic_data->fifo_isr);
  6976. + return 0;
  6977. +}
  6978. +
  6979. +size_t elliptic_data_pop(struct elliptic_data
  6980. + *elliptic_data, char __user *buffer, size_t buffer_size)
  6981. +{
  6982. + int result;
  6983. + unsigned int num_copied;
  6984. +
  6985. + if (buffer_size < ELLIPTIC_MSG_BUF_SIZE) {
  6986. + EL_PRINT_E("buffer_size : %lu smaller than %lu",
  6987. + buffer_size, (size_t)ELLIPTIC_MSG_BUF_SIZE);
  6988. + return 0;
  6989. + }
  6990. +
  6991. + result = wait_event_interruptible(elliptic_data->fifo_usp_not_empty,
  6992. + (kfifo_is_empty(&elliptic_data->fifo_userspace) == 0)
  6993. + || (atomic_read(&elliptic_data->abort_io) == 1));
  6994. +
  6995. + if (atomic_read(&elliptic_data->abort_io) == 1) {
  6996. + atomic_set(&elliptic_data->abort_io, 0);
  6997. + EL_PRINT_D("pop cancelled");
  6998. + return 0;
  6999. + }
  7000. +
  7001. +
  7002. + if (result == 0) {
  7003. + mutex_lock(&elliptic_data->fifo_usp_lock);
  7004. +
  7005. + num_copied = 0;
  7006. + result = kfifo_to_user(&elliptic_data->fifo_userspace, buffer,
  7007. + ELLIPTIC_MSG_BUF_SIZE, &num_copied);
  7008. +
  7009. + if (result == -EFAULT) {
  7010. + EL_PRINT_E("failed kfifo_to_user");
  7011. + mutex_unlock(&elliptic_data->fifo_usp_lock);
  7012. + return 0;
  7013. + }
  7014. +
  7015. + mutex_unlock(&elliptic_data->fifo_usp_lock);
  7016. + ++elliptic_data->userspace_read_total;
  7017. +
  7018. + if ((size_t)num_copied != ELLIPTIC_MSG_BUF_SIZE) {
  7019. + EL_PRINT_E("copied less than entry size : %u"
  7020. + , num_copied);
  7021. + return (size_t)num_copied;
  7022. + }
  7023. + } else {
  7024. + if (-ERESTARTSYS == result)
  7025. + EL_PRINT_D("wait interrupted");
  7026. + else
  7027. + EL_PRINT_E("wait error = %d", result);
  7028. + }
  7029. +
  7030. + return (size_t)ELLIPTIC_MSG_BUF_SIZE;
  7031. +}
  7032. +
  7033. +int elliptic_data_push(const char *buffer, size_t buffer_size)
  7034. +{
  7035. + size_t available_space;
  7036. + size_t space_required;
  7037. + size_t zeros_to_pad;
  7038. + int err;
  7039. + int i;
  7040. + unsigned long flags;
  7041. + struct elliptic_device *device;
  7042. + struct elliptic_data *elliptic_data;
  7043. + unsigned int fifo_result;
  7044. + static uint8_t zero_pad_buffer[ELLIPTIC_MSG_BUF_SIZE];
  7045. +
  7046. + err = 0;
  7047. + fifo_result = 0;
  7048. +
  7049. + if (buffer_size > ELLIPTIC_MSG_BUF_SIZE) {
  7050. + EL_PRINT_E("buffer size %lu is larger than max buffer size %lu",
  7051. + buffer_size, (size_t)ELLIPTIC_MSG_BUF_SIZE);
  7052. + return -EINVAL;
  7053. + }
  7054. +
  7055. +
  7056. + zeros_to_pad = ELLIPTIC_MSG_BUF_SIZE - buffer_size;
  7057. +
  7058. + for (i = 0; i < ELLIPTIC_NUM_DEVICES; ++i) {
  7059. + device = &elliptic_devices[i];
  7060. + elliptic_data = &device->el_data;
  7061. +
  7062. + if ((!device->opened))
  7063. + continue;
  7064. +
  7065. + available_space = kfifo_avail(&elliptic_data->fifo_isr);
  7066. + space_required = ELLIPTIC_MSG_BUF_SIZE;
  7067. +
  7068. + spin_lock_irqsave(&elliptic_data->fifo_isr_spinlock, flags);
  7069. +
  7070. + if (available_space < space_required) {
  7071. + EL_PRINT_W("fifo space too small: %lu, flushing fifo",
  7072. + available_space);
  7073. +
  7074. + ++elliptic_data->isr_fifo_flush_count;
  7075. + elliptic_data_flush_isr_fifo(elliptic_data);
  7076. + }
  7077. +
  7078. + fifo_result = kfifo_in(&elliptic_data->fifo_isr,
  7079. + buffer, buffer_size);
  7080. + if (fifo_result == 0) {
  7081. + EL_PRINT_W("failed to push buffer to fifo");
  7082. + spin_unlock_irqrestore(
  7083. + &elliptic_data->fifo_isr_spinlock, flags);
  7084. + continue;
  7085. + }
  7086. +
  7087. + if (zeros_to_pad > 0) {
  7088. + fifo_result = kfifo_in(
  7089. + &elliptic_data->fifo_isr, zero_pad_buffer,
  7090. + zeros_to_pad);
  7091. + if (fifo_result == 0) {
  7092. + EL_PRINT_W("zero pad failed, flushing fifo");
  7093. + spin_unlock_irqrestore(
  7094. + &elliptic_data->fifo_isr_spinlock,
  7095. + flags);
  7096. +
  7097. + ++elliptic_data->isr_fifo_flush_count;
  7098. + elliptic_data_flush_isr_fifo(elliptic_data);
  7099. + continue;
  7100. + }
  7101. + }
  7102. +
  7103. + ++elliptic_data->isr_write_total;
  7104. + spin_unlock_irqrestore(
  7105. + &elliptic_data->fifo_isr_spinlock, flags);
  7106. +
  7107. + queue_work(elliptic_data->wq, &elliptic_data->work);
  7108. + }
  7109. +
  7110. + return err;
  7111. +}
  7112. +
  7113. +
  7114. +/**
  7115. +*
  7116. +* @return Number of bytes read.
  7117. +*/
  7118. +static ssize_t device_read(struct file *fp, char __user *buff,
  7119. + size_t length, loff_t *ppos)
  7120. +{
  7121. + ssize_t bytes_read = 0;
  7122. + struct elliptic_device *elliptic_device;
  7123. + struct elliptic_data *elliptic_data;
  7124. +
  7125. + elliptic_device = (struct elliptic_device *)fp->private_data;
  7126. + elliptic_data = (struct elliptic_data *)&elliptic_device->el_data;
  7127. +
  7128. + bytes_read = elliptic_data_pop(elliptic_data, buff, length);
  7129. +
  7130. + return bytes_read;
  7131. +}
  7132. +
  7133. +/**
  7134. +*
  7135. +* @return number of bytes actually written
  7136. +*/
  7137. +static ssize_t device_write(struct file *fp, const char *buff,
  7138. + size_t length, loff_t *ppos)
  7139. +{
  7140. + ssize_t ret_val;
  7141. +
  7142. + ret_val = 0;
  7143. + if ((buff != NULL) && (length != 0))
  7144. + ret_val = elliptic_data_io_write(ELLIPTIC_ULTRASOUND_SET_PARAMS,
  7145. + buff, length);
  7146. +
  7147. + return ret_val >= 0 ? (ssize_t)length : 0;
  7148. +}
  7149. +
  7150. +
  7151. +static long device_ioctl(struct file *fp, unsigned int number,
  7152. + unsigned long param)
  7153. +{
  7154. + struct elliptic_device *device;
  7155. + struct elliptic_data *elliptic_data;
  7156. + int err;
  7157. + unsigned int mirror_tag, mirror_payload_size;
  7158. + unsigned char *data_ptr;
  7159. +
  7160. + device = (struct elliptic_device *)(fp->private_data);
  7161. + elliptic_data = &device->el_data;
  7162. +
  7163. + switch (number) {
  7164. + case IOCTL_ELLIPTIC_DATA_IO_CANCEL:
  7165. + EL_PRINT_D("IOCTL_ELLIPTIC_CANCEL_READ %ld",
  7166. + param);
  7167. + elliptic_data_io_cancel(elliptic_data);
  7168. + break;
  7169. +
  7170. + case IOCTL_ELLIPTIC_DATA_IO_MIRROR:
  7171. + data_ptr = (unsigned char *) param;
  7172. + mirror_tag = *(unsigned int *) data_ptr;
  7173. + mirror_payload_size = *((unsigned int *) data_ptr + 1);
  7174. +
  7175. + if ((mirror_tag == MIRROR_TAG) &&
  7176. + (mirror_payload_size != 0) &&
  7177. + (mirror_payload_size <=
  7178. + (ELLIPTIC_SET_PARAMS_SIZE * 4))) {
  7179. +
  7180. + err = elliptic_data_io_write(
  7181. + ELLIPTIC_ULTRASOUND_SET_PARAMS,
  7182. + (data_ptr + 8), mirror_payload_size);
  7183. +
  7184. + if (err != 0) {
  7185. + EL_PRINT_E("elliptic_data_io_write failed");
  7186. + return err;
  7187. + }
  7188. +
  7189. + } else {
  7190. + EL_PRINT_E("TAG or Length is not valid");
  7191. + }
  7192. +
  7193. + break;
  7194. +
  7195. + default:
  7196. + EL_PRINT_W("UNKNOWN IOCTL number=%d", number);
  7197. + break;
  7198. + }
  7199. +
  7200. + return 0;
  7201. +}
  7202. +
  7203. +
  7204. +static unsigned int device_poll(struct file *file,
  7205. + struct poll_table_struct *poll_table)
  7206. +{
  7207. + unsigned int mask;
  7208. +
  7209. + struct elliptic_device *device;
  7210. + struct elliptic_data *elliptic_data;
  7211. +
  7212. + mask = 0;
  7213. + device = (struct elliptic_device *)file->private_data;
  7214. + elliptic_data = (struct elliptic_data *)&device->el_data;
  7215. +
  7216. + poll_wait(file, &elliptic_data->fifo_usp_not_empty, poll_table);
  7217. +
  7218. + if (!kfifo_is_empty(&elliptic_data->fifo_userspace))
  7219. + mask = POLLIN | POLLRDNORM;
  7220. +
  7221. + return mask;
  7222. +}
  7223. +
  7224. +
  7225. +static int device_close(struct inode *inode, struct file *filp)
  7226. +{
  7227. + struct elliptic_device *device;
  7228. + struct elliptic_data *elliptic_data;
  7229. + unsigned int minor;
  7230. +
  7231. + device = filp->private_data;
  7232. + elliptic_data = &device->el_data;
  7233. + minor = iminor(inode);
  7234. + if (device == NULL) {
  7235. + EL_PRINT_E("device not found");
  7236. + return -ENODEV;
  7237. + }
  7238. +
  7239. + device->opened = 0;
  7240. + elliptic_data_update_debug_counters(elliptic_data);
  7241. + elliptic_data_print_debug_counters(elliptic_data);
  7242. +
  7243. + up(&device->sem);
  7244. +
  7245. + EL_PRINT_I("Closed device elliptic%u", minor);
  7246. + return 0;
  7247. +}
  7248. +
  7249. +/* defines the file operations provided by the driver */
  7250. +static const struct file_operations elliptic_fops = {
  7251. + .owner = THIS_MODULE, /* prevents unloading when operations are in use*/
  7252. + .open = device_open, /*to open the device*/
  7253. + .write = device_write, /*to write to the device*/
  7254. + .read = device_read, /*to read the device*/
  7255. + .poll = device_poll,
  7256. + .unlocked_ioctl = device_ioctl, /* IOCTL calls */
  7257. + .release = device_close, /*to close the device*/
  7258. +};
  7259. +
  7260. +
  7261. +static int elliptic_device_initialize(struct elliptic_device
  7262. + *elliptic_device, int minor, struct class *class)
  7263. +{
  7264. + int err;
  7265. + dev_t device_number;
  7266. + struct device *device;
  7267. +
  7268. + BUG_ON(elliptic_device == NULL || class == NULL);
  7269. +
  7270. + err = 0;
  7271. + device = NULL;
  7272. + device_number = MKDEV(elliptic_major, minor);
  7273. + /* Memory is to be allocated when the device is opened the first time */
  7274. + sema_init(&elliptic_device->sem, 1);
  7275. + cdev_init(&elliptic_device->cdev, &elliptic_fops);
  7276. + elliptic_device->cdev.owner = THIS_MODULE;
  7277. +
  7278. + err = cdev_add(&elliptic_device->cdev, device_number, 1);
  7279. +
  7280. + if (err) {
  7281. + EL_PRINT_E("error %d while trying to add %s%d",
  7282. + err, ELLIPTIC_DEVICENAME, minor);
  7283. + return err;
  7284. + }
  7285. +
  7286. + device = device_create(class, NULL, device_number,
  7287. + NULL, ELLIPTIC_DEVICENAME "%d", minor);
  7288. +
  7289. + if (IS_ERR(device)) {
  7290. + err = PTR_ERR(device);
  7291. + EL_PRINT_E("error %d while trying to create %s%d",
  7292. + err, ELLIPTIC_DEVICENAME, minor);
  7293. + cdev_del(&elliptic_device->cdev);
  7294. + return err;
  7295. + }
  7296. +
  7297. + if (err) {
  7298. + EL_PRINT_E("failed device initialize");
  7299. + return err;
  7300. + }
  7301. +
  7302. + return 0;
  7303. +}
  7304. +
  7305. +static void elliptic_device_cleanup(struct elliptic_device *dev, int minor,
  7306. + struct class *class)
  7307. +
  7308. +{
  7309. + BUG_ON(dev == NULL || class == NULL);
  7310. + device_destroy(class, MKDEV(elliptic_major, minor));
  7311. + cdev_del(&dev->cdev);
  7312. + up(&dev->sem);
  7313. +}
  7314. +
  7315. +static void elliptic_driver_cleanup(int devices_to_destroy)
  7316. +{
  7317. + int i;
  7318. +
  7319. + if (elliptic_devices) {
  7320. + elliptic_data_io_cleanup();
  7321. +
  7322. + for (i = 0; i < devices_to_destroy; ++i) {
  7323. + elliptic_data_cleanup(&elliptic_devices[i].el_data);
  7324. + elliptic_device_cleanup(
  7325. + &elliptic_devices[i], i, elliptic_class);
  7326. + }
  7327. +
  7328. + kfree(elliptic_devices);
  7329. + }
  7330. +
  7331. + if (elliptic_class)
  7332. + class_destroy(elliptic_class);
  7333. +
  7334. + unregister_chrdev_region(
  7335. + MKDEV(elliptic_major, 0), ELLIPTIC_NUM_DEVICES);
  7336. +}
  7337. +static int __init elliptic_driver_init(void)
  7338. +{
  7339. + int err;
  7340. + int i;
  7341. + int devices_to_destroy;
  7342. + dev_t device_number;
  7343. +
  7344. + err = alloc_chrdev_region(&device_number, 0, ELLIPTIC_NUM_DEVICES,
  7345. + ELLIPTIC_DEVICENAME);
  7346. +
  7347. + if (err < 0) {
  7348. + EL_PRINT_E("Failed to allocate cdev region");
  7349. + return err;
  7350. + }
  7351. +
  7352. + elliptic_major = MAJOR(device_number);
  7353. + elliptic_class = class_create(THIS_MODULE, "chardev");
  7354. +
  7355. + if (elliptic_class == NULL) {
  7356. + EL_PRINT_E("Class creation failed");
  7357. + goto fail;
  7358. + }
  7359. +
  7360. + err = elliptic_initialize_sysfs();
  7361. +
  7362. + if (err)
  7363. + goto fail;
  7364. +
  7365. + elliptic_devices = (struct elliptic_device *)
  7366. + kzalloc(sizeof(struct elliptic_device) * ELLIPTIC_NUM_DEVICES,
  7367. + GFP_KERNEL);
  7368. +
  7369. + if (elliptic_devices == NULL) {
  7370. + err = -ENOMEM;
  7371. + goto fail;
  7372. + }
  7373. +
  7374. + if (elliptic_data_io_initialize())
  7375. + goto fail;
  7376. +
  7377. +
  7378. + devices_to_destroy = 0;
  7379. +
  7380. + for (i = 0; i < ELLIPTIC_NUM_DEVICES; ++i) {
  7381. + if (elliptic_device_initialize(&elliptic_devices[i], i,
  7382. + elliptic_class)) {
  7383. + devices_to_destroy = i;
  7384. + goto fail;
  7385. + }
  7386. +
  7387. + if (elliptic_data_initialize(&elliptic_devices[i].el_data,
  7388. + ELLIPTIC_DATA_FIFO_SIZE, ELLIPTIC_WAKEUP_TIMEOUT, i)) {
  7389. + goto fail;
  7390. + }
  7391. + }
  7392. +
  7393. + wake_source = kmalloc(sizeof(struct wakeup_source), GFP_KERNEL);
  7394. +
  7395. + if (!wake_source) {
  7396. + EL_PRINT_E("failed to allocate wake source");
  7397. + return -ENOMEM;
  7398. + }
  7399. +
  7400. + wakeup_source_init(wake_source, "elliptic_wake_source");
  7401. +
  7402. + return 0;
  7403. +
  7404. +fail:
  7405. + elliptic_driver_cleanup(devices_to_destroy);
  7406. + return err;
  7407. +}
  7408. +
  7409. +static void elliptic_driver_exit(void)
  7410. +{
  7411. + if (wake_source) {
  7412. + wakeup_source_trash(wake_source);
  7413. + kfree(wake_source);
  7414. + }
  7415. +
  7416. + elliptic_cleanup_sysfs();
  7417. + elliptic_driver_cleanup(ELLIPTIC_NUM_DEVICES);
  7418. +}
  7419. +
  7420. +MODULE_AUTHOR("Elliptic Labs");
  7421. +MODULE_DESCRIPTION("Providing Interface to UPS data");
  7422. +MODULE_LICENSE("GPL");
  7423. +
  7424. +module_init(elliptic_driver_init);
  7425. +module_exit(elliptic_driver_exit);
  7426. diff --git a/drivers/elliptic/elliptic_data_io.h b/drivers/elliptic/elliptic_data_io.h
  7427. new file mode 100644
  7428. index 0000000..648e519
  7429. --- /dev/null
  7430. +++ b/drivers/elliptic/elliptic_data_io.h
  7431. @@ -0,0 +1,100 @@
  7432. +/**
  7433. +* Copyright Elliptic Labs 2015-2016
  7434. +* Copyright (C) 2017 XiaoMi, Inc.
  7435. +*
  7436. +*/
  7437. +
  7438. +#pragma once
  7439. +
  7440. +#include <linux/types.h>
  7441. +#include <linux/kfifo.h>
  7442. +#include <linux/spinlock.h>
  7443. +#include <linux/wait.h>
  7444. +#include <linux/module.h>
  7445. +#include <linux/kernel.h>
  7446. +#include <linux/workqueue.h>
  7447. +
  7448. +#define ELLIPTIC_DATA_IO_AP_TO_DSP 0
  7449. +#define ELLIPTIC_DATA_IO_DSP_TO_AP 1
  7450. +
  7451. +#define ELLIPTIC_DATA_IO_READ_OK 0
  7452. +#define ELLIPTIC_DATA_IO_READ_BUSY 1
  7453. +#define ELLIPTIC_DATA_IO_READ_CANCEL 2
  7454. +
  7455. +#define ELLIPTIC_MSG_BUF_SIZE 512
  7456. +
  7457. +/* wake source timeout in ms*/
  7458. +#define ELLIPTIC_WAKEUP_TIMEOUT 250
  7459. +
  7460. +#define ELLIPTIC_DATA_FIFO_SIZE (PAGE_SIZE)
  7461. +
  7462. +
  7463. +enum elliptic_message_id {
  7464. + ELLIPTIC_MESSAGE_PAYLOAD, /* Input to AP*/
  7465. + ELLIPTIC_MESSAGE_RAW, /* Output from AP*/
  7466. + ELLIPTIC_MESSAGE_CALIBRATION,
  7467. + ELLIPTIC_MAX_MESSAGE_IDS
  7468. +};
  7469. +
  7470. +struct elliptic_data {
  7471. + unsigned int wakeup_timeout; /* wake lock timeout */
  7472. +
  7473. + /* members for top half interrupt handling */
  7474. + struct kfifo fifo_isr;
  7475. + spinlock_t fifo_isr_spinlock;
  7476. +
  7477. + /* buffer to swap data from isr fifo to userspace fifo */
  7478. + uint8_t isr_swap_buffer[ELLIPTIC_MSG_BUF_SIZE];
  7479. +
  7480. + /* members for bottom half handling */
  7481. + struct kfifo fifo_userspace;
  7482. + struct mutex fifo_usp_lock;
  7483. + wait_queue_head_t fifo_usp_not_empty;
  7484. +
  7485. + atomic_t abort_io;
  7486. + struct work_struct work;
  7487. + struct workqueue_struct *wq;
  7488. +
  7489. + /* debug counters, reset between open/close */
  7490. + uint32_t isr_fifo_flush_count;
  7491. + uint32_t userspace_fifo_flush_count;
  7492. +
  7493. + /* debug counters, persistent */
  7494. + uint32_t isr_fifo_flush_count_total;
  7495. + uint32_t userspace_fifo_flush_count_total;
  7496. + uint32_t userspace_read_total;
  7497. + uint32_t isr_write_total;
  7498. +
  7499. +};
  7500. +
  7501. +/* Elliptic IO module API (implemented by IO module)*/
  7502. +
  7503. +int elliptic_data_io_initialize(void);
  7504. +int elliptic_data_io_cleanup(void);
  7505. +void elliptic_data_io_cancel(struct elliptic_data *);
  7506. +
  7507. +int32_t elliptic_data_io_write(uint32_t message_id, const char *data,
  7508. + size_t data_size);
  7509. +
  7510. +int32_t elliptic_data_io_transact(uint32_t message_id, const char *data,
  7511. + size_t data_size, char *output_data, size_t output_data_size);
  7512. +
  7513. +
  7514. +/* Elliptic driver API (implemented by main driver)*/
  7515. +int elliptic_data_initialize(struct elliptic_data *,
  7516. + size_t max_queue_size, unsigned int wakeup_timeout, int id);
  7517. +
  7518. +int elliptic_data_cleanup(struct elliptic_data *);
  7519. +
  7520. +void elliptic_data_reset_debug_counters(struct elliptic_data *);
  7521. +void elliptic_data_update_debug_counters(struct elliptic_data *);
  7522. +void elliptic_data_print_debug_counters(struct elliptic_data *);
  7523. +
  7524. +size_t elliptic_data_pop(struct elliptic_data *,
  7525. + char __user *buffer, size_t buffer_size);
  7526. +
  7527. +void elliptic_data_cancel(struct elliptic_data *);
  7528. +
  7529. +/* Called from IO module*/
  7530. +int elliptic_data_push(const char *buffer, size_t buffer_size);
  7531. +
  7532. diff --git a/drivers/elliptic/elliptic_device.h b/drivers/elliptic/elliptic_device.h
  7533. new file mode 100644
  7534. index 0000000..87c7b15
  7535. --- /dev/null
  7536. +++ b/drivers/elliptic/elliptic_device.h
  7537. @@ -0,0 +1,54 @@
  7538. +/**
  7539. + * Copyright Elliptic Labs
  7540. + * Copyright (C) 2017 XiaoMi, Inc.
  7541. + *
  7542. + */
  7543. +
  7544. +#pragma once
  7545. +
  7546. +#include <linux/ioctl.h>
  7547. +#include <linux/cdev.h>
  7548. +#include <linux/semaphore.h>
  7549. +#include "elliptic_data_io.h"
  7550. +
  7551. +#define ELLIPTIC_DEVICENAME "elliptic"
  7552. +#define ELLIPTIC_NUM_DEVICES 2
  7553. +
  7554. +#define IOCTL_ELLIPTIC_APP 197
  7555. +#define MIRROR_TAG 0x3D0A4842
  7556. +
  7557. +#define IOCTL_ELLIPTIC_DATA_IO_CANCEL \
  7558. + _IO(IOCTL_ELLIPTIC_APP, 2)
  7559. +
  7560. +#define IOCTL_ELLIPTIC_ACTIVATE_ENGINE \
  7561. + _IOW(IOCTL_ELLIPTIC_APP, 3, int)
  7562. +
  7563. +#define IOCTL_ELLIPTIC_SET_RAMP_DOWN \
  7564. + _IO(IOCTL_ELLIPTIC_APP, 4)
  7565. +
  7566. +#define IOCTL_ELLIPTIC_SYSTEM_CONFIGURATION \
  7567. + _IOW(IOCTL_ELLIPTIC_APP, 5, int)
  7568. +
  7569. +#define IOCTL_ELLIPTIC_DATA_IO_MIRROR \
  7570. + _IOW(IOCTL_ELLIPTIC_APP, 117, unsigned char *)
  7571. +
  7572. +struct elliptic_device {
  7573. + int opened;
  7574. + struct cdev cdev;
  7575. + struct semaphore sem;
  7576. + struct elliptic_data el_data;
  7577. +};
  7578. +
  7579. +
  7580. +#define EL_PRINT_E(string, arg...) \
  7581. + pr_err("[ELUS] : (%s) : " string "\n", __func__, ##arg)
  7582. +
  7583. +#define EL_PRINT_W(string, arg...) \
  7584. + pr_warn("[ELUS] : (%s) : " string "\n", __func__, ##arg)
  7585. +
  7586. +#define EL_PRINT_I(string, arg...) \
  7587. + pr_info("[ELUS] : (%s) : " string "\n", __func__, ##arg)
  7588. +
  7589. +#define EL_PRINT_D(string, arg...) \
  7590. + pr_debug("[ELUS] : (%s) : " string "\n", __func__, ##arg)
  7591. +
  7592. diff --git a/drivers/elliptic/elliptic_mixer_controls.h b/drivers/elliptic/elliptic_mixer_controls.h
  7593. new file mode 100644
  7594. index 0000000..356923d
  7595. --- /dev/null
  7596. +++ b/drivers/elliptic/elliptic_mixer_controls.h
  7597. @@ -0,0 +1,27 @@
  7598. +#pragma once
  7599. +#include <sound/core.h>
  7600. +#include <sound/pcm.h>
  7601. +#include <sound/soc.h>
  7602. +#include <linux/types.h>
  7603. +
  7604. +
  7605. +#define ELLIPTIC_OBJ_ID_CALIBRATION_DATA 1
  7606. +#define ELLIPTIC_OBJ_ID_VERSION_INFO 2
  7607. +#define ELLIPTIC_OBJ_ID_BRANCH_INFO 3
  7608. +
  7609. +struct elliptic_engine_version_info {
  7610. + uint32_t major;
  7611. + uint32_t minor;
  7612. + uint32_t build;
  7613. + uint32_t revision;
  7614. +};
  7615. +
  7616. +struct elliptic_shared_data_block {
  7617. + uint32_t object_id;
  7618. + size_t size;
  7619. + void *buffer;
  7620. +};
  7621. +
  7622. +struct elliptic_shared_data_block *elliptic_get_shared_obj(uint32_t
  7623. + object_id);
  7624. +
  7625. diff --git a/drivers/elliptic/elliptic_sysfs.c b/drivers/elliptic/elliptic_sysfs.c
  7626. new file mode 100644
  7627. index 0000000..680cc92
  7628. --- /dev/null
  7629. +++ b/drivers/elliptic/elliptic_sysfs.c
  7630. @@ -0,0 +1,182 @@
  7631. +#include <linux/kobject.h>
  7632. +#include <linux/sysfs.h>
  7633. +#include <linux/device.h>
  7634. +#include <linux/uaccess.h>
  7635. +#include <linux/module.h>
  7636. +#include "elliptic_device.h"
  7637. +#include "elliptic_sysfs.h"
  7638. +#include "elliptic_mixer_controls.h"
  7639. +
  7640. +static int kobject_create_and_add_failed;
  7641. +static int sysfs_create_group_failed;
  7642. +
  7643. +static ssize_t calibration_store(struct device *dev,
  7644. + struct device_attribute *attr, const char *buf, size_t count) {
  7645. +
  7646. + ssize_t result;
  7647. +
  7648. + struct elliptic_shared_data_block *calibration_obj =
  7649. + elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_CALIBRATION_DATA);
  7650. +
  7651. + if (calibration_obj == NULL) {
  7652. + EL_PRINT_E("calibration_obj is NULL");
  7653. + return -EINVAL;
  7654. + }
  7655. +
  7656. + if (count > calibration_obj->size) {
  7657. + EL_PRINT_E("write length %zu larger than buffer", count);
  7658. + return 0;
  7659. + }
  7660. +
  7661. + memcpy(calibration_obj->buffer, buf, count);
  7662. + result = (ssize_t)count;
  7663. + return result;
  7664. +}
  7665. +
  7666. +static ssize_t calibration_show(struct device *dev,
  7667. + struct device_attribute *attr, char *buf)
  7668. +{
  7669. + ssize_t result;
  7670. + int length;
  7671. + int i;
  7672. + uint8_t *caldata;
  7673. +
  7674. + struct elliptic_shared_data_block *calibration_obj =
  7675. + elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_CALIBRATION_DATA);
  7676. +
  7677. + if (kobject_create_and_add_failed)
  7678. + EL_PRINT_E("kobject_create_and_add_failed");
  7679. +
  7680. + if (sysfs_create_group_failed)
  7681. + EL_PRINT_E("sysfs_create_group_failed");
  7682. +
  7683. + if (calibration_obj == NULL) {
  7684. + EL_PRINT_E("calibration_obj is NULL");
  7685. + return -EINVAL;
  7686. + }
  7687. +
  7688. + if (calibration_obj->size > PAGE_SIZE) {
  7689. + EL_PRINT_E("calibration_obj->size > PAGE_SIZE");
  7690. + return -EINVAL;
  7691. + }
  7692. +
  7693. + caldata = (uint8_t *)calibration_obj->buffer;
  7694. + length = 0;
  7695. + for (i = 0; i < calibration_obj->size; ++i)
  7696. + length += snprintf(buf + length, PAGE_SIZE - length, "0x%02x ",
  7697. + caldata[i]);
  7698. +
  7699. + length += snprintf(buf + length, PAGE_SIZE - length, "\n");
  7700. + result = (ssize_t)length;
  7701. + return result;
  7702. +}
  7703. +
  7704. +static ssize_t version_show(struct device *dev,
  7705. + struct device_attribute *attr, char *buf)
  7706. +{
  7707. + ssize_t result;
  7708. + struct elliptic_engine_version_info *version_info;
  7709. + int length;
  7710. +
  7711. + struct elliptic_shared_data_block *version_obj =
  7712. + elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_VERSION_INFO);
  7713. +
  7714. + if (kobject_create_and_add_failed)
  7715. + EL_PRINT_E("kobject_create_and_add_failed");
  7716. +
  7717. + if (sysfs_create_group_failed)
  7718. + EL_PRINT_E("sysfs_create_group_failed");
  7719. +
  7720. + if (version_obj == NULL) {
  7721. + EL_PRINT_E("version_obj is NULL");
  7722. + return -EINVAL;
  7723. + }
  7724. +
  7725. + if (version_obj->size > PAGE_SIZE) {
  7726. + EL_PRINT_E("version_obj->size > PAGE_SIZE");
  7727. + return -EINVAL;
  7728. + }
  7729. +
  7730. + version_info = (struct elliptic_engine_version_info *)
  7731. + version_obj->buffer;
  7732. +
  7733. + length = snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
  7734. + version_info->major, version_info->minor, version_info->build,
  7735. + version_info->revision);
  7736. +
  7737. + result = (ssize_t)length;
  7738. + return result;
  7739. +}
  7740. +
  7741. +static ssize_t branch_show(struct device *dev,
  7742. + struct device_attribute *attr, char *buf)
  7743. +{
  7744. + int length;
  7745. +
  7746. + struct elliptic_shared_data_block *branch_obj =
  7747. + elliptic_get_shared_obj(ELLIPTIC_OBJ_ID_BRANCH_INFO);
  7748. +
  7749. + if (branch_obj == NULL) {
  7750. + EL_PRINT_E("branch_obj not found");
  7751. + return 0;
  7752. + }
  7753. +
  7754. + if (branch_obj->size > PAGE_SIZE) {
  7755. + EL_PRINT_E("branch_obj->size > PAGE_SIZE");
  7756. + return -EINVAL;
  7757. + }
  7758. +
  7759. + length = snprintf(buf, PAGE_SIZE - 1, "%s\n",
  7760. + (const char *)(branch_obj->buffer));
  7761. +
  7762. + return (ssize_t)length;
  7763. +}
  7764. +
  7765. +
  7766. +static struct device_attribute calibration_attr = __ATTR_RW(calibration);
  7767. +static struct device_attribute version_attr = __ATTR_RO(version);
  7768. +static struct device_attribute branch_attr = __ATTR_RO(branch);
  7769. +
  7770. +static struct attribute *elliptic_attrs[] = {
  7771. + &calibration_attr.attr,
  7772. + &version_attr.attr,
  7773. + &branch_attr.attr,
  7774. + NULL,
  7775. +};
  7776. +
  7777. +static struct attribute_group elliptic_attr_group = {
  7778. + .name = ELLIPTIC_SYSFS_ENGINE_FOLDER,
  7779. + .attrs = elliptic_attrs,
  7780. +};
  7781. +
  7782. +static struct kobject *elliptic_sysfs_kobj;
  7783. +
  7784. +int elliptic_initialize_sysfs(void)
  7785. +{
  7786. + int err;
  7787. +
  7788. + elliptic_sysfs_kobj = kobject_create_and_add(ELLIPTIC_SYSFS_ROOT_FOLDER,
  7789. + kernel_kobj->parent);
  7790. +
  7791. + if (!elliptic_sysfs_kobj) {
  7792. + kobject_create_and_add_failed = 1;
  7793. + EL_PRINT_E("failed to create kobj");
  7794. + return -ENOMEM;
  7795. + }
  7796. +
  7797. + err = sysfs_create_group(elliptic_sysfs_kobj, &elliptic_attr_group);
  7798. +
  7799. + if (err) {
  7800. + sysfs_create_group_failed = 1;
  7801. + EL_PRINT_E("failed to create sysfs group");
  7802. + kobject_put(elliptic_sysfs_kobj);
  7803. + return -ENOMEM;
  7804. + }
  7805. +
  7806. + return 0;
  7807. +}
  7808. +
  7809. +void elliptic_cleanup_sysfs(void)
  7810. +{
  7811. + kobject_put(elliptic_sysfs_kobj);
  7812. +}
  7813. diff --git a/drivers/elliptic/elliptic_sysfs.h b/drivers/elliptic/elliptic_sysfs.h
  7814. new file mode 100644
  7815. index 0000000..25a2187b
  7816. --- /dev/null
  7817. +++ b/drivers/elliptic/elliptic_sysfs.h
  7818. @@ -0,0 +1,10 @@
  7819. +#pragma once
  7820. +
  7821. +#define ELLIPTIC_SYSFS_ENGINE_FOLDER "engine"
  7822. +#define ELLIPTIC_SYSFS_ROOT_FOLDER "elliptic"
  7823. +#define ELLIPTIC_SYSFS_CALIBRATION_FILENAME "calibration"
  7824. +#define ELLIPTIC_SYSFS_VERSION_FILENAME "version"
  7825. +
  7826. +
  7827. +int elliptic_initialize_sysfs(void);
  7828. +void elliptic_cleanup_sysfs(void);
  7829. diff --git a/drivers/elliptic/io_modules/Makefile b/drivers/elliptic/io_modules/Makefile
  7830. new file mode 100644
  7831. index 0000000..66ee789
  7832. --- /dev/null
  7833. +++ b/drivers/elliptic/io_modules/Makefile
  7834. @@ -0,0 +1,2 @@
  7835. +# TODO: add config parameter for which io module to build
  7836. +#obj-y += userspace/
  7837. diff --git a/drivers/elliptic/io_modules/msm/elliptic_data_io.c b/drivers/elliptic/io_modules/msm/elliptic_data_io.c
  7838. new file mode 100644
  7839. index 0000000..a1b5105
  7840. --- /dev/null
  7841. +++ b/drivers/elliptic/io_modules/msm/elliptic_data_io.c
  7842. @@ -0,0 +1,94 @@
  7843. +/**
  7844. + * Copyright Elliptic Labs
  7845. + * Copyright (C) 2017 XiaoMi, Inc.
  7846. + *
  7847. + */
  7848. +
  7849. +#include <linux/module.h>
  7850. +#include <linux/kernel.h>
  7851. +#include <linux/init.h>
  7852. +#include <linux/fs.h>
  7853. +#include <linux/debugfs.h>
  7854. +#include <linux/slab.h>
  7855. +#include <linux/mm.h>
  7856. +
  7857. +
  7858. +#include <linux/module.h>
  7859. +#include <linux/kernel.h>
  7860. +#include <linux/version.h>
  7861. +/* includes the file structure, that is, file open read close */
  7862. +#include <linux/fs.h>
  7863. +
  7864. +/* include the character device, makes cdev avilable */
  7865. +#include <linux/cdev.h>
  7866. +#include <linux/semaphore.h>
  7867. +
  7868. +/* includes copy_user vice versa */
  7869. +#include <linux/uaccess.h>
  7870. +
  7871. +#include <linux/slab.h>
  7872. +#include <linux/stat.h>
  7873. +#include <linux/init.h>
  7874. +#include <linux/platform_device.h>
  7875. +#include <linux/types.h>
  7876. +#include <linux/kdev_t.h>
  7877. +#include <linux/device.h>
  7878. +
  7879. +
  7880. +#include <linux/kernel.h>
  7881. +#include <linux/version.h>
  7882. +#include <linux/types.h>
  7883. +#include <linux/sched.h>
  7884. +#include <linux/wait.h>
  7885. +#include <linux/mutex.h>
  7886. +#include <asm/atomic.h>
  7887. +#include <asm/uaccess.h>
  7888. +#include <linux/errno.h>
  7889. +
  7890. +#include "elliptic_data_io.h"
  7891. +#include "elliptic_device.h"
  7892. +
  7893. +#include <sound/apr_elliptic.h>
  7894. +#define IO_PING_PONG_BUFFER_SIZE 512
  7895. +
  7896. +struct elliptic_msm_io_device {
  7897. +};
  7898. +
  7899. +/* static struct elliptic_msm_io_device io_device;*/
  7900. +
  7901. +
  7902. +int elliptic_data_io_initialize(void)
  7903. +{
  7904. + return 0;
  7905. +}
  7906. +
  7907. +int elliptic_data_io_cleanup(void)
  7908. +{
  7909. + return 0;
  7910. +}
  7911. +
  7912. +void elliptic_data_io_cancel(struct elliptic_data *elliptic_data)
  7913. +{
  7914. + atomic_set(&elliptic_data->abort_io, 1);
  7915. + wake_up_interruptible(&elliptic_data->fifo_usp_not_empty);
  7916. +
  7917. +}
  7918. +
  7919. +int32_t elliptic_data_io_write(uint32_t message_id, const char *data,
  7920. + size_t data_size)
  7921. +{
  7922. + uint32_t port_id;
  7923. +
  7924. + port_id = ELLIPTIC_PORT_ID;
  7925. + return ultrasound_apr_set(port_id, &message_id, (u8 *)data,
  7926. + (int32_t)data_size);
  7927. +}
  7928. +
  7929. +int32_t elliptic_data_io_transact(uint32_t message_id, const char *data,
  7930. + size_t data_size, char *output_data, size_t output_data_size)
  7931. +{
  7932. + pr_err("%s : unimplemented\n", __func__);
  7933. + return -EINVAL;
  7934. +}
  7935. +
  7936. +
  7937. diff --git a/drivers/elliptic/io_modules/userspace/Makefile b/drivers/elliptic/io_modules/userspace/Makefile
  7938. new file mode 100644
  7939. index 0000000..907ddc2
  7940. --- /dev/null
  7941. +++ b/drivers/elliptic/io_modules/userspace/Makefile
  7942. @@ -0,0 +1,2 @@
  7943. +# TODO: add config parameter for which io module to build
  7944. +#obj-y += elliptic_data_io.o
  7945. diff --git a/drivers/elliptic/io_modules/userspace/elliptic_data_io.c b/drivers/elliptic/io_modules/userspace/elliptic_data_io.c
  7946. new file mode 100644
  7947. index 0000000..d82a6c9
  7948. --- /dev/null
  7949. +++ b/drivers/elliptic/io_modules/userspace/elliptic_data_io.c
  7950. @@ -0,0 +1,208 @@
  7951. +/**
  7952. + * Copyright Elliptic Labs
  7953. + * Copyright (C) 2017 XiaoMi, Inc.
  7954. + *
  7955. + */
  7956. +
  7957. +#include <linux/module.h>
  7958. +#include <linux/kernel.h>
  7959. +#include <linux/init.h>
  7960. +#include <linux/fs.h>
  7961. +#include <linux/debugfs.h>
  7962. +#include <linux/slab.h>
  7963. +#include <linux/mm.h>
  7964. +
  7965. +
  7966. +#include <linux/module.h>
  7967. +#include <linux/kernel.h>
  7968. +#include <linux/version.h>
  7969. +/* includes the file structure, that is, file open read close */
  7970. +#include <linux/fs.h>
  7971. +
  7972. +/* include the character device, makes cdev avilable */
  7973. +#include <linux/cdev.h>
  7974. +#include <linux/semaphore.h>
  7975. +
  7976. +/* includes copy_user vice versa */
  7977. +#include <linux/uaccess.h>
  7978. +
  7979. +#include <linux/slab.h>
  7980. +#include <linux/stat.h>
  7981. +#include <linux/init.h>
  7982. +#include <linux/platform_device.h>
  7983. +#include <linux/types.h>
  7984. +#include <linux/kdev_t.h>
  7985. +#include <linux/device.h>
  7986. +
  7987. +
  7988. +#include <linux/kernel.h>
  7989. +#include <linux/version.h>
  7990. +#include <linux/types.h>
  7991. +#include <linux/sched.h>
  7992. +#include <linux/wait.h>
  7993. +#include <linux/mutex.h>
  7994. +#include <asm/atomic.h>
  7995. +#include <asm/uaccess.h>
  7996. +#include <linux/errno.h>
  7997. +
  7998. +#include "elliptic_data_io.h"
  7999. +#include "elliptic_device.h"
  8000. +
  8001. +
  8002. +static dev_t elliptic_usermode_io_major;
  8003. +#define USERMODE_IO_DEVICE_NAME "elliptic_um_io"
  8004. +#define UM_IO_PING_PONG_BUFFER_SIZE 512
  8005. +struct elliptic_usermode_io_device {
  8006. + struct cdev cdev;
  8007. + struct semaphore sem;
  8008. + struct mutex lock;
  8009. + int ping_pong_idx;
  8010. + char tmp_buffer[2][UM_IO_PING_PONG_BUFFER_SIZE];
  8011. +};
  8012. +
  8013. +static struct elliptic_usermode_io_device io_device;
  8014. +
  8015. +static int device_open(struct inode *inode, struct file *filp)
  8016. +{
  8017. + if (inode->i_cdev != &io_device.cdev) {
  8018. + pr_warn("elliptic : dev pointer mismatch\n");
  8019. + return -ENODEV; /* No such device */
  8020. + }
  8021. +
  8022. + if (down_interruptible(&io_device.sem) != 0)
  8023. + return -EEXIST;
  8024. + return 0;
  8025. +}
  8026. +
  8027. +static ssize_t device_write(struct file *fp, const char __user *buff,
  8028. + size_t length, loff_t *ppos)
  8029. +{
  8030. + size_t write_len;
  8031. + size_t copy_result;
  8032. + int push_result;
  8033. + int err;
  8034. +
  8035. + err = mutex_lock_interruptible(&io_device.lock);
  8036. + if (err == -EINTR) {
  8037. + pr_warn("%s : locking interrupted\n", __func__);
  8038. + return 0;
  8039. + } else if (err < 0) {
  8040. + pr_warn("%s : failed to acquire lock\n", __func__);
  8041. + return 0;
  8042. + }
  8043. +
  8044. + write_len = min_t(size_t, UM_IO_PING_PONG_BUFFER_SIZE, length);
  8045. + copy_result = copy_from_user(
  8046. + io_device.tmp_buffer[io_device.ping_pong_idx], buff, write_len);
  8047. +
  8048. + if (copy_result > 0) {
  8049. + mutex_unlock(&io_device.lock);
  8050. + return (write_len - copy_result);
  8051. + }
  8052. +
  8053. + push_result = elliptic_data_push(
  8054. + io_device.tmp_buffer[io_device.ping_pong_idx], write_len);
  8055. +
  8056. + if (push_result) {
  8057. + pr_err("elliptic: %s failed to push fifo data\n", __func__);
  8058. + mutex_unlock(&io_device.lock);
  8059. + return 0;
  8060. + }
  8061. + io_device.ping_pong_idx = 1 - io_device.ping_pong_idx;
  8062. + mutex_unlock(&io_device.lock);
  8063. + return write_len;
  8064. +}
  8065. +
  8066. +static int device_close(struct inode *inode, struct file *filp)
  8067. +{
  8068. + up(&io_device.sem);
  8069. + return 0;
  8070. +}
  8071. +
  8072. +static const struct file_operations
  8073. +elliptic_usermode_io_fops = {
  8074. + .owner = THIS_MODULE,
  8075. + .open = device_open,
  8076. + .write = device_write,
  8077. + .release = device_close,
  8078. +};
  8079. +
  8080. +static int elliptic_usermode_io_driver_init(void)
  8081. +{
  8082. + struct device *device;
  8083. + dev_t device_number;
  8084. + int err;
  8085. +
  8086. + err = alloc_chrdev_region(
  8087. + &device_number, 0, 1, USERMODE_IO_DEVICE_NAME);
  8088. +
  8089. + if (err < 0) {
  8090. + pr_err("failed to allocate chrdev region\n");
  8091. + return err;
  8092. + }
  8093. +
  8094. + elliptic_usermode_io_major = MAJOR(device_number);
  8095. + device_number = MKDEV(elliptic_usermode_io_major, 0);
  8096. + device = device_create(
  8097. + elliptic_class, NULL, device_number,
  8098. + NULL, USERMODE_IO_DEVICE_NAME);
  8099. +
  8100. + if (IS_ERR(device)) {
  8101. + unregister_chrdev(
  8102. + elliptic_usermode_io_major, USERMODE_IO_DEVICE_NAME);
  8103. + pr_err("Failed to create the device\n");
  8104. + return PTR_ERR(device);
  8105. + }
  8106. +
  8107. + cdev_init(&io_device.cdev, &elliptic_usermode_io_fops);
  8108. + io_device.cdev.owner = THIS_MODULE;
  8109. + err = cdev_add(&io_device.cdev, device_number, 1);
  8110. + if (err) {
  8111. + pr_warn("elliptic : error %d while trying to add %s%d",
  8112. + err, ELLIPTIC_DEVICENAME, 0);
  8113. + return err;
  8114. + }
  8115. +
  8116. + sema_init(&io_device.sem, 1);
  8117. + mutex_init(&io_device.lock);
  8118. + return 0;
  8119. +}
  8120. +
  8121. +static void elliptic_usermode_io_driver_exit(void)
  8122. +{
  8123. + BUG_ON(elliptic_class == NULL);
  8124. + device_destroy(elliptic_class, MKDEV(elliptic_usermode_io_major, 0));
  8125. + cdev_del(&io_device.cdev);
  8126. + unregister_chrdev(elliptic_usermode_io_major, USERMODE_IO_DEVICE_NAME);
  8127. + up(&io_device.sem);
  8128. +}
  8129. +
  8130. +
  8131. +int elliptic_data_io_initialize(void)
  8132. +{
  8133. + elliptic_usermode_io_driver_init();
  8134. + return 0;
  8135. +}
  8136. +
  8137. +int elliptic_data_io_cleanup(void)
  8138. +{
  8139. + elliptic_usermode_io_driver_exit();
  8140. + return 0;
  8141. +}
  8142. +
  8143. +void elliptic_data_io_cancel(void)
  8144. +{
  8145. +
  8146. +}
  8147. +
  8148. +size_t elliptic_data_io_write(uint32_t message_id, const char *data,
  8149. + size_t data_size)
  8150. +{
  8151. + return 0;
  8152. +}
  8153. +
  8154. +size_t elliptic_data_io_transact(uint32_t message_id, const char *data,
  8155. + size_t data_size, char *output_data, size_t output_data_size)
  8156. +{
  8157. + return 0;
  8158. +}
  8159. diff --git a/drivers/elliptic/io_modules/userspace_test/Makefile b/drivers/elliptic/io_modules/userspace_test/Makefile
  8160. new file mode 100644
  8161. index 0000000..907ddc2
  8162. --- /dev/null
  8163. +++ b/drivers/elliptic/io_modules/userspace_test/Makefile
  8164. @@ -0,0 +1,2 @@
  8165. +# TODO: add config parameter for which io module to build
  8166. +#obj-y += elliptic_data_io.o
  8167. diff --git a/drivers/elliptic/io_modules/userspace_test/elliptic_data_io.c b/drivers/elliptic/io_modules/userspace_test/elliptic_data_io.c
  8168. new file mode 100644
  8169. index 0000000..23a136c
  8170. --- /dev/null
  8171. +++ b/drivers/elliptic/io_modules/userspace_test/elliptic_data_io.c
  8172. @@ -0,0 +1,126 @@
  8173. +/**
  8174. + * Copyright Elliptic Labs
  8175. + * Copyright (C) 2017 XiaoMi, Inc.
  8176. + *
  8177. + */
  8178. +
  8179. +#include <linux/kernel.h>
  8180. +#include <linux/version.h>
  8181. +#include <linux/types.h>
  8182. +#include <linux/sched.h>
  8183. +#include <linux/wait.h>
  8184. +#include <linux/mutex.h>
  8185. +#include <asm/atomic.h>
  8186. +#include <asm/uaccess.h>
  8187. +#include <linux/errno.h>
  8188. +#include <linux/slab.h>
  8189. +
  8190. +#include <linux/kernel.h>
  8191. +#include <linux/kthread.h>
  8192. +#include <linux/delay.h>
  8193. +#include <linux/sched.h>
  8194. +
  8195. +#include "elliptic_data_io.h"
  8196. +#include "elliptic_device.h"
  8197. +
  8198. +static struct task_struct *simulating_task;
  8199. +static atomic_t cancel;
  8200. +
  8201. +struct elliptic_data_io_state {
  8202. +};
  8203. +
  8204. +struct data_packet_header {
  8205. + int32_t t1;
  8206. + union {
  8207. + uint32_t t2;
  8208. + uint8_t t2s[4];
  8209. + };
  8210. + union {
  8211. + uint32_t s1;
  8212. + uint8_t s1s[4];
  8213. + };
  8214. +};
  8215. +
  8216. +
  8217. +#define APR_TEST_SIZE 460
  8218. +struct elliptic_message {
  8219. + struct data_packet_header header;
  8220. + uint8_t data[APR_TEST_SIZE - (sizeof(struct data_packet_header))];
  8221. +};
  8222. +
  8223. +static void fill_buffer(int32_t *buffer, size_t len, int32_t value)
  8224. +{
  8225. + size_t i;
  8226. +
  8227. + for (i = 0; i < len; ++i)
  8228. + buffer[i] = value;
  8229. +}
  8230. +
  8231. +
  8232. +static struct elliptic_message output_message;
  8233. +int simulating_thread(void *context)
  8234. +{
  8235. + static int32_t count;
  8236. + int result;
  8237. +
  8238. + count = 0;
  8239. + msleep(20);
  8240. +
  8241. + pr_debug("%s\n", __func__);
  8242. + output_message.header.t2s[0] = (1<<4) | 3;
  8243. + output_message.header.s1s[0] = 100;
  8244. +
  8245. + while (atomic_read(&cancel) == 0) {
  8246. + if (kthread_should_stop())
  8247. + do_exit(0);
  8248. +
  8249. + output_message.header.t1 = count;
  8250. +
  8251. +
  8252. + fill_buffer((int32_t *)output_message.data, 100, count);
  8253. + result = elliptic_data_push((const char *)&output_message,
  8254. + APR_TEST_SIZE);
  8255. +
  8256. + ++count;
  8257. + if (result != 0)
  8258. + pr_warn("failed to push data\n");
  8259. +
  8260. + msleep(20);
  8261. + }
  8262. + return 0;
  8263. +}
  8264. +
  8265. +int32_t elliptic_data_io_write(uint32_t message_id, const char *data,
  8266. + size_t data_size) {
  8267. + return 0;
  8268. + }
  8269. +
  8270. +int32_t elliptic_data_io_transact(uint32_t message_id, const char *data,
  8271. + size_t data_size, char *output_data, size_t output_data_size) {
  8272. + return 0;
  8273. +}
  8274. +
  8275. +
  8276. +void elliptic_data_io_cancel(struct elliptic_data *elliptic_data)
  8277. +{
  8278. + atomic_set(&elliptic_data->abort_io, 1);
  8279. + wake_up_interruptible(&elliptic_data->fifo_usp_not_empty);
  8280. +}
  8281. +
  8282. +
  8283. +int elliptic_data_io_initialize(void)
  8284. +{
  8285. + pr_debug("%s\n", __func__);
  8286. + atomic_set(&cancel, 0);
  8287. + simulating_task = kthread_run(&simulating_thread, NULL,
  8288. + "el_simulating_thread");
  8289. + return 0;
  8290. +}
  8291. +
  8292. +int elliptic_data_io_cleanup(void)
  8293. +{
  8294. + kthread_stop(simulating_task);
  8295. + atomic_set(&cancel, 1);
  8296. + msleep(200);
  8297. + return 0;
  8298. +}
  8299. diff --git a/drivers/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c
  8300. index 11bd3aa..aa2d856 100644
  8301. --- a/drivers/firmware/qcom/tz_log.c
  8302. +++ b/drivers/firmware/qcom/tz_log.c
  8303. @@ -27,8 +27,8 @@
  8304. #include <soc/qcom/scm.h>
  8305. #include <soc/qcom/qseecomi.h>
  8306.  
  8307. -/* QSEE_LOG_BUF_SIZE = 32K */
  8308. -#define QSEE_LOG_BUF_SIZE 0x8000
  8309. +/* QSEE_LOG_BUF_SIZE = 64K */
  8310. +#define QSEE_LOG_BUF_SIZE 0x10000
  8311.  
  8312.  
  8313. /* TZ Diagnostic Area legacy version number */
  8314. diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
  8315. index 2a9ac89..7a546983 100644
  8316. --- a/drivers/gpu/msm/kgsl.h
  8317. +++ b/drivers/gpu/msm/kgsl.h
  8318. @@ -50,7 +50,7 @@
  8319. /* The number of memstore arrays limits the number of contexts allowed.
  8320. * If more contexts are needed, update multiple for MEMSTORE_SIZE
  8321. */
  8322. -#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 2))
  8323. +#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 8))
  8324. #define KGSL_MEMSTORE_GLOBAL (0)
  8325. #define KGSL_PRIORITY_MAX_RB_LEVELS 4
  8326. #define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \
  8327. diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
  8328. index 0150d50..b17daf1 100644
  8329. --- a/drivers/gpu/msm/kgsl_pwrctrl.c
  8330. +++ b/drivers/gpu/msm/kgsl_pwrctrl.c
  8331. @@ -1,4 +1,5 @@
  8332. /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
  8333. + * Copyright (C) 2017 XiaoMi, Inc.
  8334. *
  8335. * This program is free software; you can redistribute it and/or modify
  8336. * it under the terms of the GNU General Public License version 2 and
  8337. @@ -33,6 +34,7 @@
  8338. #define KGSL_PWRFLAGS_AXI_ON 2
  8339. #define KGSL_PWRFLAGS_IRQ_ON 3
  8340. #define KGSL_PWRFLAGS_NAP_OFF 5
  8341. +#define KGSL_PWRFLAGS_RESTRICT_MAX_LEVEL_JUMP 6
  8342.  
  8343. #define UPDATE_BUSY_VAL 1000000
  8344.  
  8345. @@ -355,6 +357,16 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
  8346. */
  8347. kgsl_pwrctrl_set_thermal_cycle(pwr, new_level);
  8348.  
  8349. + /* Check any restriction over new level jump */
  8350. + if (test_bit(KGSL_PWRFLAGS_RESTRICT_MAX_LEVEL_JUMP,
  8351. + &device->pwrctrl.ctrl_flags)) {
  8352. + if (new_level == 0 &&
  8353. + old_level > device->pwrctrl.restrict_pwrlevel)
  8354. + new_level = device->pwrctrl.restrict_pwrlevel;
  8355. + else if (new_level == 0 && old_level == 0)
  8356. + new_level = device->pwrctrl.restrict_pwrlevel;
  8357. + }
  8358. +
  8359. if (new_level == old_level)
  8360. return;
  8361.  
  8362. @@ -2094,6 +2106,13 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
  8363. if (of_property_read_bool(pdev->dev.of_node, "qcom,no-nap"))
  8364. device->pwrctrl.ctrl_flags |= BIT(KGSL_PWRFLAGS_NAP_OFF);
  8365.  
  8366. + if (!of_property_read_u32(pdev->dev.of_node, "qcom,restrict-pwrlevel",
  8367. + &pwr->restrict_pwrlevel)) {
  8368. + device->pwrctrl.ctrl_flags |=
  8369. + BIT(KGSL_PWRFLAGS_RESTRICT_MAX_LEVEL_JUMP);
  8370. + KGSL_PWR_ERR(device, "qcom,restrict-pwrlevel is Enabled \n");
  8371. + }
  8372. +
  8373. if (pwr->num_pwrlevels == 0) {
  8374. KGSL_PWR_ERR(device, "No power levels are defined\n");
  8375. result = -EINVAL;
  8376. @@ -2499,6 +2518,7 @@ static int _init(struct kgsl_device *device)
  8377. static int _wake(struct kgsl_device *device)
  8378. {
  8379. struct kgsl_pwrctrl *pwr = &device->pwrctrl;
  8380. + bool limit_max_pwrlevel = false;
  8381. int status = 0;
  8382.  
  8383. switch (device->state) {
  8384. @@ -2521,6 +2541,18 @@ static int _wake(struct kgsl_device *device)
  8385. kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
  8386. kgsl_pwrscale_wake(device);
  8387. kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
  8388. +
  8389. + /*
  8390. + * Check any restriction on max power level, clk_set_rate()
  8391. + * wil set based on the active_pwrlevel.
  8392. + */
  8393. + if (test_bit(KGSL_PWRFLAGS_RESTRICT_MAX_LEVEL_JUMP,
  8394. + &pwr->ctrl_flags) &&
  8395. + (pwr->active_pwrlevel == 0)) {
  8396. + pwr->active_pwrlevel = pwr->restrict_pwrlevel;
  8397. + limit_max_pwrlevel = true;
  8398. + }
  8399. +
  8400. /* fall through */
  8401. case KGSL_STATE_NAP:
  8402. /* Turn on the core clocks */
  8403. @@ -2539,8 +2571,13 @@ static int _wake(struct kgsl_device *device)
  8404. */
  8405. kgsl_pwrctrl_pwrlevel_change_settings(device, 0);
  8406. kgsl_pwrctrl_pwrlevel_change_settings(device, 1);
  8407. +
  8408. /* All settings for power level transitions are complete*/
  8409. - pwr->previous_pwrlevel = pwr->active_pwrlevel;
  8410. + if (limit_max_pwrlevel)
  8411. + pwr->previous_pwrlevel = 0;
  8412. + else
  8413. + pwr->previous_pwrlevel = pwr->active_pwrlevel;
  8414. +
  8415. mod_timer(&device->idle_timer, jiffies +
  8416. device->pwrctrl.interval_timeout);
  8417. break;
  8418. diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
  8419. index 42f918b..7366ded 100644
  8420. --- a/drivers/gpu/msm/kgsl_pwrctrl.h
  8421. +++ b/drivers/gpu/msm/kgsl_pwrctrl.h
  8422. @@ -1,4 +1,5 @@
  8423. /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
  8424. + * Copyright (C) 2017 XiaoMi, Inc.
  8425. *
  8426. * This program is free software; you can redistribute it and/or modify
  8427. * it under the terms of the GNU General Public License version 2 and
  8428. @@ -117,6 +118,7 @@ struct kgsl_regulator {
  8429. * @previous_pwrlevel - The power level before transition
  8430. * @thermal_pwrlevel - maximum powerlevel constraint from thermal
  8431. * @default_pwrlevel - device wake up power level
  8432. + * @restrict_pwrlevel - maximum power level jump to restrict
  8433. * @max_pwrlevel - maximum allowable powerlevel per the user
  8434. * @min_pwrlevel - minimum allowable powerlevel per the user
  8435. * @num_pwrlevels - number of available power levels
  8436. @@ -171,6 +173,7 @@ struct kgsl_pwrctrl {
  8437. unsigned int previous_pwrlevel;
  8438. unsigned int thermal_pwrlevel;
  8439. unsigned int default_pwrlevel;
  8440. + unsigned int restrict_pwrlevel;
  8441. unsigned int wakeup_maxpwrlevel;
  8442. unsigned int max_pwrlevel;
  8443. unsigned int min_pwrlevel;
  8444. diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
  8445. index 700145b..4ad880d 100644
  8446. --- a/drivers/hid/usbhid/hiddev.c
  8447. +++ b/drivers/hid/usbhid/hiddev.c
  8448. @@ -1,6 +1,7 @@
  8449. /*
  8450. * Copyright (c) 2001 Paul Stewart
  8451. * Copyright (c) 2001 Vojtech Pavlik
  8452. + * Copyright (C) 2017 XiaoMi, Inc.
  8453. *
  8454. * HID char devices, giving access to raw HID device events.
  8455. *
  8456. @@ -510,17 +511,18 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
  8457. goto inval;
  8458.  
  8459. field = report->field[uref->field_index];
  8460. + }
  8461.  
  8462. - if (cmd == HIDIOCGCOLLECTIONINDEX) {
  8463. - if (uref->usage_index >= field->maxusage)
  8464. - goto inval;
  8465. - } else if (uref->usage_index >= field->report_count)
  8466. + if (cmd == HIDIOCGCOLLECTIONINDEX) {
  8467. + if (uref->usage_index >= field->maxusage)
  8468. goto inval;
  8469. - }
  8470. + } else if (uref->usage_index >= field->report_count)
  8471. + goto inval;
  8472.  
  8473. - if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
  8474. - (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
  8475. - uref->usage_index + uref_multi->num_values > field->report_count))
  8476. + else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
  8477. + (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
  8478. + uref->usage_index + uref_multi->num_values >
  8479. + field->report_count))
  8480. goto inval;
  8481.  
  8482. switch (cmd) {
  8483. diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
  8484. index 2557dcd..bf6d228 100644
  8485. --- a/drivers/input/Kconfig
  8486. +++ b/drivers/input/Kconfig
  8487. @@ -200,6 +200,13 @@ config INPUT_KEYCOMBO
  8488. ---help---
  8489. Say Y here if you want to take action when some keys are pressed;
  8490.  
  8491. +config LAST_TOUCH_EVENTS
  8492. + bool "Last touch events"
  8493. + default n
  8494. + depends on INPUT
  8495. + ---help---
  8496. + Say Y here if you want to get last touch events.
  8497. +
  8498. comment "Input Device Drivers"
  8499.  
  8500. source "drivers/input/keyboard/Kconfig"
  8501. @@ -214,6 +221,8 @@ source "drivers/input/touchscreen/Kconfig"
  8502.  
  8503. source "drivers/input/misc/Kconfig"
  8504.  
  8505. +source "drivers/input/fingerprint/Kconfig"
  8506. +
  8507. endif
  8508.  
  8509. menu "Hardware I/O ports"
  8510. diff --git a/drivers/input/Makefile b/drivers/input/Makefile
  8511. index 2a6d05a..d74a160 100644
  8512. --- a/drivers/input/Makefile
  8513. +++ b/drivers/input/Makefile
  8514. @@ -24,6 +24,7 @@ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
  8515. obj-$(CONFIG_INPUT_TABLET) += tablet/
  8516. obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
  8517. obj-$(CONFIG_INPUT_MISC) += misc/
  8518. +obj-$(CONFIG_INPUT_FINGERPRINT) += fingerprint/
  8519.  
  8520. obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
  8521. obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o
  8522. diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
  8523. index e9ae3d5..7fbfb9b 100644
  8524. --- a/drivers/input/evdev.c
  8525. +++ b/drivers/input/evdev.c
  8526. @@ -2,6 +2,7 @@
  8527. * Event char devices, giving access to raw input device events.
  8528. *
  8529. * Copyright (c) 1999-2002 Vojtech Pavlik
  8530. + * Copyright (C) 2017 XiaoMi, Inc.
  8531. *
  8532. * This program is free software; you can redistribute it and/or modify it
  8533. * under the terms of the GNU General Public License version 2 as published by
  8534. @@ -107,51 +108,6 @@ static bool __evdev_is_filtered(struct evdev_client *client,
  8535. return mask && !test_bit(code, mask);
  8536. }
  8537.  
  8538. -/* flush queued events of type @type, caller must hold client->buffer_lock */
  8539. -static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
  8540. -{
  8541. - unsigned int i, head, num;
  8542. - unsigned int mask = client->bufsize - 1;
  8543. - bool is_report;
  8544. - struct input_event *ev;
  8545. -
  8546. - BUG_ON(type == EV_SYN);
  8547. -
  8548. - head = client->tail;
  8549. - client->packet_head = client->tail;
  8550. -
  8551. - /* init to 1 so a leading SYN_REPORT will not be dropped */
  8552. - num = 1;
  8553. -
  8554. - for (i = client->tail; i != client->head; i = (i + 1) & mask) {
  8555. - ev = &client->buffer[i];
  8556. - is_report = ev->type == EV_SYN && ev->code == SYN_REPORT;
  8557. -
  8558. - if (ev->type == type) {
  8559. - /* drop matched entry */
  8560. - continue;
  8561. - } else if (is_report && !num) {
  8562. - /* drop empty SYN_REPORT groups */
  8563. - continue;
  8564. - } else if (head != i) {
  8565. - /* move entry to fill the gap */
  8566. - client->buffer[head].time = ev->time;
  8567. - client->buffer[head].type = ev->type;
  8568. - client->buffer[head].code = ev->code;
  8569. - client->buffer[head].value = ev->value;
  8570. - }
  8571. -
  8572. - num++;
  8573. - head = (head + 1) & mask;
  8574. -
  8575. - if (is_report) {
  8576. - num = 0;
  8577. - client->packet_head = head;
  8578. - }
  8579. - }
  8580. -
  8581. - client->head = head;
  8582. -}
  8583.  
  8584. static void __evdev_queue_syn_dropped(struct evdev_client *client)
  8585. {
  8586. @@ -179,14 +135,6 @@ static void __evdev_queue_syn_dropped(struct evdev_client *client)
  8587. }
  8588. }
  8589.  
  8590. -static void evdev_queue_syn_dropped(struct evdev_client *client)
  8591. -{
  8592. - unsigned long flags;
  8593. -
  8594. - spin_lock_irqsave(&client->buffer_lock, flags);
  8595. - __evdev_queue_syn_dropped(client);
  8596. - spin_unlock_irqrestore(&client->buffer_lock, flags);
  8597. -}
  8598.  
  8599. static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
  8600. {
  8601. @@ -898,53 +846,6 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
  8602. return input_set_keycode(dev, &ke);
  8603. }
  8604.  
  8605. -/*
  8606. - * If we transfer state to the user, we should flush all pending events
  8607. - * of the same type from the client's queue. Otherwise, they might end up
  8608. - * with duplicate events, which can screw up client's state tracking.
  8609. - * If bits_to_user fails after flushing the queue, we queue a SYN_DROPPED
  8610. - * event so user-space will notice missing events.
  8611. - *
  8612. - * LOCKING:
  8613. - * We need to take event_lock before buffer_lock to avoid dead-locks. But we
  8614. - * need the even_lock only to guarantee consistent state. We can safely release
  8615. - * it while flushing the queue. This allows input-core to handle filters while
  8616. - * we flush the queue.
  8617. - */
  8618. -static int evdev_handle_get_val(struct evdev_client *client,
  8619. - struct input_dev *dev, unsigned int type,
  8620. - unsigned long *bits, unsigned int maxbit,
  8621. - unsigned int maxlen, void __user *p,
  8622. - int compat)
  8623. -{
  8624. - int ret;
  8625. - unsigned long *mem;
  8626. - size_t len;
  8627. -
  8628. - len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long);
  8629. - mem = kmalloc(len, GFP_KERNEL);
  8630. - if (!mem)
  8631. - return -ENOMEM;
  8632. -
  8633. - spin_lock_irq(&dev->event_lock);
  8634. - spin_lock(&client->buffer_lock);
  8635. -
  8636. - memcpy(mem, bits, len);
  8637. -
  8638. - spin_unlock(&dev->event_lock);
  8639. -
  8640. - __evdev_flush_queue(client, type);
  8641. -
  8642. - spin_unlock_irq(&client->buffer_lock);
  8643. -
  8644. - ret = bits_to_user(mem, maxbit, maxlen, p, compat);
  8645. - if (ret < 0)
  8646. - evdev_queue_syn_dropped(client);
  8647. -
  8648. - kfree(mem);
  8649. -
  8650. - return ret;
  8651. -}
  8652.  
  8653. static int evdev_handle_mt_request(struct input_dev *dev,
  8654. unsigned int size,
  8655. @@ -1182,20 +1083,16 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
  8656. return evdev_handle_mt_request(dev, size, ip);
  8657.  
  8658. case EVIOCGKEY(0):
  8659. - return evdev_handle_get_val(client, dev, EV_KEY, dev->key,
  8660. - KEY_MAX, size, p, compat_mode);
  8661. + return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
  8662.  
  8663. case EVIOCGLED(0):
  8664. - return evdev_handle_get_val(client, dev, EV_LED, dev->led,
  8665. - LED_MAX, size, p, compat_mode);
  8666. + return bits_to_user(dev->led, LED_MAX, size, p, compat_mode);
  8667.  
  8668. case EVIOCGSND(0):
  8669. - return evdev_handle_get_val(client, dev, EV_SND, dev->snd,
  8670. - SND_MAX, size, p, compat_mode);
  8671. + return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode);
  8672.  
  8673. case EVIOCGSW(0):
  8674. - return evdev_handle_get_val(client, dev, EV_SW, dev->sw,
  8675. - SW_MAX, size, p, compat_mode);
  8676. + return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode);
  8677.  
  8678. case EVIOCGNAME(0):
  8679. return str_to_user(dev->name, size, p);
  8680. diff --git a/drivers/input/fingerprint/Kconfig b/drivers/input/fingerprint/Kconfig
  8681. new file mode 100644
  8682. index 0000000..16b1eeb
  8683. --- /dev/null
  8684. +++ b/drivers/input/fingerprint/Kconfig
  8685. @@ -0,0 +1,18 @@
  8686. +#
  8687. +# Fingerprint driver configuration
  8688. +#
  8689. +menuconfig INPUT_FINGERPRINT
  8690. + bool "Fingerprints"
  8691. + help
  8692. + Say Y here, and a list of supported fingerprints will be displayed.
  8693. + This option doesn't affect the kernel.
  8694. +
  8695. + If unsure, say Y.
  8696. +
  8697. +if INPUT_FINGERPRINT
  8698. +
  8699. +source "drivers/input/fingerprint/goodix/Kconfig"
  8700. +source "drivers/input/fingerprint/goodix_ta/Kconfig"
  8701. +source "drivers/input/fingerprint/fpc1268_tee/Kconfig"
  8702. +
  8703. +endif
  8704. diff --git a/drivers/input/fingerprint/Makefile b/drivers/input/fingerprint/Makefile
  8705. new file mode 100644
  8706. index 0000000..21bb763
  8707. --- /dev/null
  8708. +++ b/drivers/input/fingerprint/Makefile
  8709. @@ -0,0 +1,9 @@
  8710. +#
  8711. +# Makefile for the fingerprint drivers.
  8712. +#
  8713. +
  8714. +# Each configuration option enables a list of files.
  8715. +
  8716. +obj-$(CONFIG_FINGERPRINT_GOODIX) += goodix/
  8717. +obj-$(CONFIG_FINGERPRINT_GOODIX_TA) += goodix_ta/
  8718. +obj-$(CONFIG_FINGERPRINT_FPC1268_TEE) += fpc1268_tee/
  8719. diff --git a/drivers/input/fingerprint/fpc1268_tee/Kconfig b/drivers/input/fingerprint/fpc1268_tee/Kconfig
  8720. new file mode 100644
  8721. index 0000000..918a582
  8722. --- /dev/null
  8723. +++ b/drivers/input/fingerprint/fpc1268_tee/Kconfig
  8724. @@ -0,0 +1,10 @@
  8725. +config FINGERPRINT_FPC1268_TEE
  8726. + tristate "Finger print card fpc1268"
  8727. + depends on INPUT_FINGERPRINT
  8728. + help
  8729. + Say Y here to enable support for retrieving self-test reports.
  8730. +
  8731. + If unsure, say N.
  8732. +
  8733. + To compile this driver as a module, choose M here.
  8734. +
  8735. diff --git a/drivers/input/fingerprint/fpc1268_tee/Makefile b/drivers/input/fingerprint/fpc1268_tee/Makefile
  8736. new file mode 100644
  8737. index 0000000..f32432e
  8738. --- /dev/null
  8739. +++ b/drivers/input/fingerprint/fpc1268_tee/Makefile
  8740. @@ -0,0 +1 @@
  8741. +obj-$(CONFIG_FINGERPRINT_FPC1268_TEE) += fpc1020_tee.o
  8742. diff --git a/drivers/input/fingerprint/fpc1268_tee/fpc1020_tee.c b/drivers/input/fingerprint/fpc1268_tee/fpc1020_tee.c
  8743. new file mode 100644
  8744. index 0000000..2bec8a7
  8745. --- /dev/null
  8746. +++ b/drivers/input/fingerprint/fpc1268_tee/fpc1020_tee.c
  8747. @@ -0,0 +1,633 @@
  8748. +/*
  8749. + * FPC1020 Fingerprint sensor device driver
  8750. + *
  8751. + * This driver will control the platform resources that the FPC fingerprint
  8752. + * sensor needs to operate. The major things are probing the sensor to check
  8753. + * that it is actually connected and let the Kernel know this and with that also
  8754. + * enabling and disabling of regulators, controlling GPIOs such as sensor reset
  8755. + * line, sensor IRQ line.
  8756. + *
  8757. + * The driver will expose most of its available functionality in sysfs which
  8758. + * enables dynamic control of these features from eg. a user space process.
  8759. + *
  8760. + * The sensor's IRQ events will be pushed to Kernel's event handling system and
  8761. + * are exposed in the drivers event node.
  8762. + *
  8763. + * This driver will NOT send any commands to the sensor it only controls the
  8764. + * electrical parts.
  8765. + *
  8766. + *
  8767. + * Copyright (c) 2015 Fingerprint Cards AB <tech@fingerprints.com>
  8768. + * Copyright (C) 2017 XiaoMi, Inc.
  8769. + *
  8770. + * This program is free software; you can redistribute it and/or
  8771. + * modify it under the terms of the GNU General Public License Version 2
  8772. + * as published by the Free Software Foundation.
  8773. + */
  8774. +
  8775. +#include <linux/atomic.h>
  8776. +#include <linux/delay.h>
  8777. +#include <linux/gpio.h>
  8778. +#include <linux/interrupt.h>
  8779. +#include <linux/kernel.h>
  8780. +#include <linux/module.h>
  8781. +#include <linux/mutex.h>
  8782. +#include <linux/of.h>
  8783. +#include <linux/of_gpio.h>
  8784. +#include <linux/platform_device.h>
  8785. +#include <linux/regulator/consumer.h>
  8786. +#include <linux/wakelock.h>
  8787. +#include <linux/hwinfo.h>
  8788. +#include <asm/hwconf_manager.h>
  8789. +
  8790. +#define FPC_TTW_HOLD_TIME 2000
  8791. +
  8792. +#define RESET_LOW_SLEEP_MIN_US 5000
  8793. +#define RESET_LOW_SLEEP_MAX_US (RESET_LOW_SLEEP_MIN_US + 100)
  8794. +#define RESET_HIGH_SLEEP1_MIN_US 100
  8795. +#define RESET_HIGH_SLEEP1_MAX_US (RESET_HIGH_SLEEP1_MIN_US + 100)
  8796. +#define RESET_HIGH_SLEEP2_MIN_US 5000
  8797. +#define RESET_HIGH_SLEEP2_MAX_US (RESET_HIGH_SLEEP2_MIN_US + 100)
  8798. +#define PWR_ON_SLEEP_MIN_US 100
  8799. +#define PWR_ON_SLEEP_MAX_US (PWR_ON_SLEEP_MIN_US + 900)
  8800. +
  8801. +#define NUM_PARAMS_REG_ENABLE_SET 2
  8802. +
  8803. +
  8804. +static const char * const pctl_names[] = {
  8805. + "fpc1020_reset_reset",
  8806. + "fpc1020_reset_active",
  8807. + "fpc1020_irq_active",
  8808. +};
  8809. +
  8810. +struct vreg_config {
  8811. + char *name;
  8812. + unsigned long vmin;
  8813. + unsigned long vmax;
  8814. + int ua_load;
  8815. +};
  8816. +
  8817. +static const struct vreg_config const vreg_conf[] = {
  8818. + { "vdd_ana", 1800000UL, 1800000UL, 6000, },
  8819. +};
  8820. +
  8821. +struct fpc1020_data {
  8822. + struct device *dev;
  8823. +
  8824. + struct pinctrl *fingerprint_pinctrl;
  8825. + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
  8826. + struct regulator *vreg[ARRAY_SIZE(vreg_conf)];
  8827. +
  8828. + struct wake_lock ttw_wl;
  8829. + int irq_gpio;
  8830. + int rst_gpio;
  8831. + struct mutex lock; /* To set/get exported values in sysfs */
  8832. + bool prepared;
  8833. + atomic_t wakeup_enabled; /* Used both in ISR and non-ISR */
  8834. + int irqf;
  8835. +};
  8836. +
  8837. +static irqreturn_t fpc1020_irq_handler(int irq, void *handle);
  8838. +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020,
  8839. + const char *label, int *gpio);
  8840. +
  8841. +static int vreg_setup(struct fpc1020_data *fpc1020, const char *name,
  8842. + bool enable)
  8843. +{
  8844. + size_t i;
  8845. + int rc;
  8846. + struct regulator *vreg;
  8847. + struct device *dev = fpc1020->dev;
  8848. +
  8849. + for (i = 0; i < ARRAY_SIZE(fpc1020->vreg); i++) {
  8850. + const char *n = vreg_conf[i].name;
  8851. +
  8852. + if (!strncmp(n, name, strlen(n)))
  8853. + goto found;
  8854. + }
  8855. +
  8856. + dev_err(dev, "Regulator %s not found\n", name);
  8857. +
  8858. + return -EINVAL;
  8859. +
  8860. +found:
  8861. + vreg = fpc1020->vreg[i];
  8862. + if (enable) {
  8863. + if (!vreg) {
  8864. + vreg = regulator_get(dev, name);
  8865. + if (IS_ERR(vreg)) {
  8866. + dev_err(dev, "Unable to get %s\n", name);
  8867. + return PTR_ERR(vreg);
  8868. + }
  8869. + }
  8870. + rc = regulator_enable(vreg);
  8871. + if (rc) {
  8872. + dev_err(dev, "error enabling %s: %d\n", name, rc);
  8873. + regulator_put(vreg);
  8874. + vreg = NULL;
  8875. + }
  8876. + fpc1020->vreg[i] = vreg;
  8877. + } else {
  8878. + if (vreg) {
  8879. + if (regulator_is_enabled(vreg)) {
  8880. + regulator_disable(vreg);
  8881. + dev_dbg(dev, "disabled %s\n", name);
  8882. + }
  8883. + regulator_put(vreg);
  8884. + fpc1020->vreg[i] = NULL;
  8885. + }
  8886. + rc = 0;
  8887. + }
  8888. +
  8889. + return rc;
  8890. +}
  8891. +
  8892. +/**
  8893. + * sysfs node for controlling clocks.
  8894. + *
  8895. + * This is disabled in platform variant of this driver but kept for
  8896. + * backwards compatibility. Only prints a debug print that it is
  8897. + * disabled.
  8898. + */
  8899. +static ssize_t clk_enable_set(struct device *dev,
  8900. + struct device_attribute *attr,
  8901. + const char *buf, size_t count)
  8902. +{
  8903. + dev_dbg(dev,
  8904. + "clk_enable sysfs node not enabled in platform driver\n");
  8905. +
  8906. + return count;
  8907. +}
  8908. +static DEVICE_ATTR(clk_enable, S_IWUSR, NULL, clk_enable_set);
  8909. +
  8910. +/**
  8911. + * Will try to select the set of pins (GPIOS) defined in a pin control node of
  8912. + * the device tree named @p name.
  8913. + *
  8914. + * The node can contain several eg. GPIOs that is controlled when selecting it.
  8915. + * The node may activate or deactivate the pins it contains, the action is
  8916. + * defined in the device tree node itself and not here. The states used
  8917. + * internally is fetched at probe time.
  8918. + *
  8919. + * @see pctl_names
  8920. + * @see fpc1020_probe
  8921. + */
  8922. +static int select_pin_ctl(struct fpc1020_data *fpc1020, const char *name)
  8923. +{
  8924. + size_t i;
  8925. + int rc;
  8926. + struct device *dev = fpc1020->dev;
  8927. +
  8928. + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) {
  8929. + const char *n = pctl_names[i];
  8930. +
  8931. + if (!strncmp(n, name, strlen(n))) {
  8932. + rc = pinctrl_select_state(fpc1020->fingerprint_pinctrl,
  8933. + fpc1020->pinctrl_state[i]);
  8934. + if (rc)
  8935. + dev_err(dev, "cannot select '%s'\n", name);
  8936. + else
  8937. + dev_dbg(dev, "Selected '%s'\n", name);
  8938. + goto exit;
  8939. + }
  8940. + }
  8941. +
  8942. + rc = -EINVAL;
  8943. + dev_err(dev, "%s:'%s' not found\n", __func__, name);
  8944. +
  8945. +exit:
  8946. + return rc;
  8947. +}
  8948. +
  8949. +static ssize_t pinctl_set(struct device *dev,
  8950. + struct device_attribute *attr, const char *buf, size_t count)
  8951. +{
  8952. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  8953. + int rc;
  8954. +
  8955. + mutex_lock(&fpc1020->lock);
  8956. + rc = select_pin_ctl(fpc1020, buf);
  8957. + mutex_unlock(&fpc1020->lock);
  8958. +
  8959. + return rc ? rc : count;
  8960. +}
  8961. +static DEVICE_ATTR(pinctl_set, S_IWUSR, NULL, pinctl_set);
  8962. +
  8963. +static ssize_t regulator_enable_set(struct device *dev,
  8964. + struct device_attribute *attr, const char *buf, size_t count)
  8965. +{
  8966. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  8967. + char op;
  8968. + char name[16];
  8969. + int rc;
  8970. + bool enable;
  8971. +
  8972. + if (NUM_PARAMS_REG_ENABLE_SET != sscanf(buf, "%15[^,],%c", name, &op))
  8973. + return -EINVAL;
  8974. + if (op == 'e')
  8975. + enable = true;
  8976. + else if (op == 'd')
  8977. + enable = false;
  8978. + else
  8979. + return -EINVAL;
  8980. +
  8981. + mutex_lock(&fpc1020->lock);
  8982. + rc = vreg_setup(fpc1020, name, enable);
  8983. + mutex_unlock(&fpc1020->lock);
  8984. +
  8985. + return rc ? rc : count;
  8986. +}
  8987. +static DEVICE_ATTR(regulator_enable, S_IWUSR, NULL, regulator_enable_set);
  8988. +
  8989. +static int hw_reset(struct fpc1020_data *fpc1020)
  8990. +{
  8991. + int irq_gpio;
  8992. + struct device *dev = fpc1020->dev;
  8993. + int rc = select_pin_ctl(fpc1020, "fpc1020_reset_active");
  8994. +
  8995. + if (rc)
  8996. + goto exit;
  8997. + usleep_range(RESET_HIGH_SLEEP1_MIN_US, RESET_HIGH_SLEEP1_MAX_US);
  8998. +
  8999. + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset");
  9000. + if (rc)
  9001. + goto exit;
  9002. + usleep_range(RESET_LOW_SLEEP_MIN_US, RESET_LOW_SLEEP_MAX_US);
  9003. +
  9004. + rc = select_pin_ctl(fpc1020, "fpc1020_reset_active");
  9005. + if (rc)
  9006. + goto exit;
  9007. + usleep_range(RESET_HIGH_SLEEP2_MIN_US, RESET_HIGH_SLEEP2_MAX_US);
  9008. +
  9009. + irq_gpio = gpio_get_value(fpc1020->irq_gpio);
  9010. + dev_info(dev, "IRQ after reset %d\n", irq_gpio);
  9011. +
  9012. +exit:
  9013. + return rc;
  9014. +}
  9015. +
  9016. +static ssize_t hw_reset_set(struct device *dev,
  9017. + struct device_attribute *attr, const char *buf, size_t count)
  9018. +{
  9019. + int rc;
  9020. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  9021. +
  9022. + if (!strncmp(buf, "reset", strlen("reset"))) {
  9023. + mutex_lock(&fpc1020->lock);
  9024. + rc = hw_reset(fpc1020);
  9025. + mutex_unlock(&fpc1020->lock);
  9026. + } else {
  9027. + return -EINVAL;
  9028. + }
  9029. +
  9030. + return rc ? rc : count;
  9031. +}
  9032. +static DEVICE_ATTR(hw_reset, S_IWUSR, NULL, hw_reset_set);
  9033. +
  9034. +/**
  9035. + * Will setup GPIOs, and regulators to correctly initialize the touch sensor to
  9036. + * be ready for work.
  9037. + *
  9038. + * In the correct order according to the sensor spec this function will
  9039. + * enable/disable regulators, and reset line, all to set the sensor in a
  9040. + * correct power on or off state "electrical" wise.
  9041. + *
  9042. + * @see device_prepare_set
  9043. + * @note This function will not send any commands to the sensor it will only
  9044. + * control it "electrically".
  9045. + */
  9046. +static int device_prepare(struct fpc1020_data *fpc1020, bool enable)
  9047. +{
  9048. + int rc;
  9049. + struct device *dev = fpc1020->dev;
  9050. +
  9051. + mutex_lock(&fpc1020->lock);
  9052. + if (enable && !fpc1020->prepared) {
  9053. + rc = select_pin_ctl(fpc1020, "fpc1020_irq_active");
  9054. + if (rc) {
  9055. + pr_err("irq gpio set active failed\n");
  9056. + goto exit;
  9057. + }
  9058. +
  9059. + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_irq",
  9060. + &fpc1020->irq_gpio);
  9061. + if (rc) {
  9062. + pr_err("irq gpio request failed\n");
  9063. + goto exit;
  9064. + }
  9065. + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_rst",
  9066. + &fpc1020->rst_gpio);
  9067. + if (rc) {
  9068. + pr_err("reset gpio request failed\n");
  9069. + goto irq_gpio_exit;
  9070. + }
  9071. + rc = devm_request_threaded_irq(dev, gpio_to_irq(fpc1020->irq_gpio),
  9072. + NULL, fpc1020_irq_handler, fpc1020->irqf,
  9073. + dev_name(dev), fpc1020);
  9074. + if (rc) {
  9075. + pr_err("could not request irq %d\n",
  9076. + gpio_to_irq(fpc1020->irq_gpio));
  9077. + goto rst_gpio_exit;
  9078. + }
  9079. +
  9080. + dev_dbg(dev, "requested irq %d\n", gpio_to_irq(fpc1020->irq_gpio));
  9081. +
  9082. + /* Request that the interrupt should be wakeable */
  9083. + enable_irq_wake(gpio_to_irq(fpc1020->irq_gpio));
  9084. + select_pin_ctl(fpc1020, "fpc1020_reset_reset");
  9085. + rc = vreg_setup(fpc1020, "vdd_ana", true);
  9086. + if (rc)
  9087. + goto free_irq_exit;
  9088. +
  9089. + usleep_range(PWR_ON_SLEEP_MIN_US, PWR_ON_SLEEP_MAX_US);
  9090. +
  9091. + /* As we can't control chip select here the other part of the
  9092. + * sensor driver eg. the TEE driver needs to do a _SOFT_ reset
  9093. + * on the sensor after power up to be sure that the sensor is
  9094. + * in a good state after power up. Okeyed by ASIC. */
  9095. +
  9096. + (void)select_pin_ctl(fpc1020, "fpc1020_reset_active");
  9097. + hw_reset(fpc1020);
  9098. + fpc1020->prepared = true;
  9099. + } else if (!enable && fpc1020->prepared) {
  9100. + rc = 0;
  9101. + (void)select_pin_ctl(fpc1020, "fpc1020_reset_reset");
  9102. +
  9103. + usleep_range(PWR_ON_SLEEP_MIN_US, PWR_ON_SLEEP_MAX_US);
  9104. +
  9105. + (void)vreg_setup(fpc1020, "vdd_ana", false);
  9106. +free_irq_exit:
  9107. + disable_irq(gpio_to_irq(fpc1020->irq_gpio));
  9108. + devm_free_irq(dev, gpio_to_irq(fpc1020->irq_gpio), fpc1020);
  9109. +rst_gpio_exit:
  9110. + devm_gpio_free(dev, fpc1020->rst_gpio);
  9111. +irq_gpio_exit:
  9112. + devm_gpio_free(dev, fpc1020->irq_gpio);
  9113. +exit:
  9114. + fpc1020->prepared = false;
  9115. + } else {
  9116. + rc = 0;
  9117. + }
  9118. + mutex_unlock(&fpc1020->lock);
  9119. +
  9120. + return rc;
  9121. +}
  9122. +
  9123. +/**
  9124. + * sysfs node to enable/disable (power up/power down) the touch sensor
  9125. + *
  9126. + * @see device_prepare
  9127. + */
  9128. +static ssize_t device_prepare_set(struct device *dev,
  9129. + struct device_attribute *attr, const char *buf, size_t count)
  9130. +{
  9131. + int rc;
  9132. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  9133. +
  9134. + if (!strncmp(buf, "enable", strlen("enable")))
  9135. + rc = device_prepare(fpc1020, true);
  9136. + else if (!strncmp(buf, "disable", strlen("disable")))
  9137. + rc = device_prepare(fpc1020, false);
  9138. + else
  9139. + return -EINVAL;
  9140. +
  9141. + return rc ? rc : count;
  9142. +}
  9143. +static DEVICE_ATTR(device_prepare, S_IWUSR, NULL, device_prepare_set);
  9144. +
  9145. +/**
  9146. + * sysfs node for controlling whether the driver is allowed
  9147. + * to wake up the platform on interrupt.
  9148. + */
  9149. +static ssize_t wakeup_enable_set(struct device *dev,
  9150. + struct device_attribute *attr, const char *buf, size_t count)
  9151. +{
  9152. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  9153. + ssize_t ret = count;
  9154. +
  9155. + mutex_lock(&fpc1020->lock);
  9156. + mutex_unlock(&fpc1020->lock);
  9157. +
  9158. + return ret;
  9159. +}
  9160. +static DEVICE_ATTR(wakeup_enable, S_IWUSR, NULL, wakeup_enable_set);
  9161. +
  9162. +/**
  9163. + * sysf node to check the interrupt status of the sensor, the interrupt
  9164. + * handler should perform sysf_notify to allow userland to poll the node.
  9165. + */
  9166. +static ssize_t irq_get(struct device *dev,
  9167. + struct device_attribute *attr,
  9168. + char *buf)
  9169. +{
  9170. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  9171. + int irq = gpio_get_value(fpc1020->irq_gpio);
  9172. +
  9173. + return scnprintf(buf, PAGE_SIZE, "%i\n", irq);
  9174. +}
  9175. +
  9176. +/**
  9177. + * writing to the irq node will just drop a printk message
  9178. + * and return success, used for latency measurement.
  9179. + */
  9180. +static ssize_t irq_ack(struct device *dev,
  9181. + struct device_attribute *attr,
  9182. + const char *buf, size_t count)
  9183. +{
  9184. + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev);
  9185. +
  9186. + dev_dbg(fpc1020->dev, "%s\n", __func__);
  9187. +
  9188. + return count;
  9189. +}
  9190. +static DEVICE_ATTR(irq, S_IRUSR | S_IWUSR, irq_get, irq_ack);
  9191. +
  9192. +static struct attribute *attributes[] = {
  9193. + &dev_attr_pinctl_set.attr,
  9194. + &dev_attr_device_prepare.attr,
  9195. + &dev_attr_regulator_enable.attr,
  9196. + &dev_attr_hw_reset.attr,
  9197. + &dev_attr_wakeup_enable.attr,
  9198. + &dev_attr_clk_enable.attr,
  9199. + &dev_attr_irq.attr,
  9200. + NULL
  9201. +};
  9202. +
  9203. +static const struct attribute_group attribute_group = {
  9204. + .attrs = attributes,
  9205. +};
  9206. +
  9207. +static irqreturn_t fpc1020_irq_handler(int irq, void *handle)
  9208. +{
  9209. + struct fpc1020_data *fpc1020 = handle;
  9210. +
  9211. + dev_dbg(fpc1020->dev, "%s\n", __func__);
  9212. +
  9213. + if (atomic_read(&fpc1020->wakeup_enabled)) {
  9214. + wake_lock_timeout(&fpc1020->ttw_wl,
  9215. + msecs_to_jiffies(FPC_TTW_HOLD_TIME));
  9216. + }
  9217. +
  9218. + sysfs_notify(&fpc1020->dev->kobj, NULL, dev_attr_irq.attr.name);
  9219. +
  9220. + return IRQ_HANDLED;
  9221. +}
  9222. +
  9223. +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020,
  9224. + const char *label, int *gpio)
  9225. +{
  9226. + struct device *dev = fpc1020->dev;
  9227. + struct device_node *np = dev->of_node;
  9228. + int rc = of_get_named_gpio(np, label, 0);
  9229. +
  9230. + if (rc < 0) {
  9231. + dev_err(dev, "failed to get '%s'\n", label);
  9232. + return rc;
  9233. + }
  9234. + *gpio = rc;
  9235. +
  9236. + rc = devm_gpio_request(dev, *gpio, label);
  9237. + if (rc) {
  9238. + dev_err(dev, "failed to request gpio %d\n", *gpio);
  9239. + return rc;
  9240. + }
  9241. + dev_dbg(dev, "%s %d\n", label, *gpio);
  9242. +
  9243. + return 0;
  9244. +}
  9245. +
  9246. +static int fpc1020_probe(struct platform_device *pdev)
  9247. +{
  9248. + struct device *dev = &pdev->dev;
  9249. + int rc = 0;
  9250. + size_t i;
  9251. +
  9252. + struct device_node *np = dev->of_node;
  9253. + struct fpc1020_data *fpc1020 = devm_kzalloc(dev, sizeof(*fpc1020),
  9254. + GFP_KERNEL);
  9255. +
  9256. + if (!fpc1020) {
  9257. + dev_err(dev,
  9258. + "failed to allocate memory for struct fpc1020_data\n");
  9259. + rc = -ENOMEM;
  9260. + goto exit;
  9261. + }
  9262. +
  9263. + fpc1020->dev = dev;
  9264. + platform_set_drvdata(pdev, fpc1020);
  9265. +
  9266. + if (!np) {
  9267. + dev_err(dev, "no of node found\n");
  9268. + rc = -EINVAL;
  9269. + goto exit;
  9270. + }
  9271. +
  9272. + fpc1020->fingerprint_pinctrl = devm_pinctrl_get(dev);
  9273. + if (IS_ERR(fpc1020->fingerprint_pinctrl)) {
  9274. + if (PTR_ERR(fpc1020->fingerprint_pinctrl) == -EPROBE_DEFER) {
  9275. + dev_info(dev, "pinctrl not ready\n");
  9276. + rc = -EPROBE_DEFER;
  9277. + goto exit;
  9278. + }
  9279. + dev_err(dev, "Target does not use pinctrl\n");
  9280. + fpc1020->fingerprint_pinctrl = NULL;
  9281. + rc = -EINVAL;
  9282. + goto exit;
  9283. + }
  9284. +
  9285. + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) {
  9286. + const char *n = pctl_names[i];
  9287. + struct pinctrl_state *state =
  9288. + pinctrl_lookup_state(fpc1020->fingerprint_pinctrl, n);
  9289. + if (IS_ERR(state)) {
  9290. + dev_err(dev, "cannot find '%s'\n", n);
  9291. + rc = -EINVAL;
  9292. + goto exit;
  9293. + }
  9294. + dev_info(dev, "found pin control %s\n", n);
  9295. + fpc1020->pinctrl_state[i] = state;
  9296. + }
  9297. +
  9298. + atomic_set(&fpc1020->wakeup_enabled, 1);
  9299. +
  9300. + fpc1020->irqf = IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_NO_SUSPEND;
  9301. + device_init_wakeup(dev, 1);
  9302. +/*
  9303. + if (of_property_read_bool(dev->of_node, "fpc,enable-wakeup")) {
  9304. + fpc1020->irqf |= IRQF_NO_SUSPEND;
  9305. + device_init_wakeup(dev, 1);
  9306. + }
  9307. +*/
  9308. + mutex_init(&fpc1020->lock);
  9309. +
  9310. + wake_lock_init(&fpc1020->ttw_wl, WAKE_LOCK_SUSPEND, "fpc_ttw_wl");
  9311. +
  9312. + rc = sysfs_create_group(&dev->kobj, &attribute_group);
  9313. + if (rc) {
  9314. + dev_err(dev, "could not create sysfs\n");
  9315. + goto exit;
  9316. + }
  9317. +
  9318. + if (of_property_read_bool(dev->of_node, "fpc,enable-on-boot")) {
  9319. + dev_info(dev, "Enabling hardware\n");
  9320. + (void)device_prepare(fpc1020, true);
  9321. + }
  9322. + dev_info(dev, "%s: ok\n", __func__);
  9323. +exit:
  9324. + return rc;
  9325. +}
  9326. +
  9327. +static int fpc1020_remove(struct platform_device *pdev)
  9328. +{
  9329. + struct fpc1020_data *fpc1020 = platform_get_drvdata(pdev);
  9330. +
  9331. + sysfs_remove_group(&pdev->dev.kobj, &attribute_group);
  9332. + mutex_destroy(&fpc1020->lock);
  9333. + wake_lock_destroy(&fpc1020->ttw_wl);
  9334. + (void)vreg_setup(fpc1020, "vdd_ana", false);
  9335. + dev_info(&pdev->dev, "%s\n", __func__);
  9336. +
  9337. + return 0;
  9338. +}
  9339. +
  9340. +static struct of_device_id fpc1020_of_match[] = {
  9341. + { .compatible = "fpc,fpc1020", },
  9342. + {}
  9343. +};
  9344. +MODULE_DEVICE_TABLE(of, fpc1020_of_match);
  9345. +
  9346. +static struct platform_driver fpc1020_driver = {
  9347. + .driver = {
  9348. + .name = "fpc1020",
  9349. + .owner = THIS_MODULE,
  9350. + .of_match_table = fpc1020_of_match,
  9351. + },
  9352. + .probe = fpc1020_probe,
  9353. + .remove = fpc1020_remove,
  9354. +};
  9355. +
  9356. +static int __init fpc1020_init(void)
  9357. +{
  9358. + int rc = platform_driver_register(&fpc1020_driver);
  9359. +
  9360. + if (!rc)
  9361. + pr_info("%s OK\n", __func__);
  9362. + else
  9363. + pr_err("%s %d\n", __func__, rc);
  9364. +
  9365. + return rc;
  9366. +}
  9367. +
  9368. +static void __exit fpc1020_exit(void)
  9369. +{
  9370. + pr_info("%s\n", __func__);
  9371. + platform_driver_unregister(&fpc1020_driver);
  9372. +}
  9373. +
  9374. +module_init(fpc1020_init);
  9375. +module_exit(fpc1020_exit);
  9376. +
  9377. +MODULE_LICENSE("GPL v2");
  9378. +MODULE_AUTHOR("Aleksej Makarov");
  9379. +MODULE_AUTHOR("Henrik Tillman <henrik.tillman@fingerprints.com>");
  9380. +MODULE_DESCRIPTION("FPC1020 Fingerprint sensor device driver.");
  9381. diff --git a/drivers/input/fingerprint/goodix/Kconfig b/drivers/input/fingerprint/goodix/Kconfig
  9382. new file mode 100644
  9383. index 0000000..a86948d
  9384. --- /dev/null
  9385. +++ b/drivers/input/fingerprint/goodix/Kconfig
  9386. @@ -0,0 +1,10 @@
  9387. +config FINGERPRINT_GOODIX
  9388. + tristate "Finger print card FPC"
  9389. + depends on INPUT_FINGERPRINT
  9390. + help
  9391. + Say Y here to enable support for retrieving self-test reports.
  9392. +
  9393. + If unsure, say N.
  9394. +
  9395. + To compile this driver as a module, choose M here.
  9396. +
  9397. diff --git a/drivers/input/fingerprint/goodix/Makefile b/drivers/input/fingerprint/goodix/Makefile
  9398. new file mode 100644
  9399. index 0000000..c235359
  9400. --- /dev/null
  9401. +++ b/drivers/input/fingerprint/goodix/Makefile
  9402. @@ -0,0 +1 @@
  9403. +obj-$(CONFIG_FINGERPRINT_GOODIX) += gf_spi.o platform.o gf_common.o
  9404. diff --git a/drivers/input/fingerprint/goodix/gf_common.c b/drivers/input/fingerprint/goodix/gf_common.c
  9405. new file mode 100644
  9406. index 0000000..af876a6
  9407. --- /dev/null
  9408. +++ b/drivers/input/fingerprint/goodix/gf_common.c
  9409. @@ -0,0 +1,331 @@
  9410. +#include "gf_common.h"
  9411. +#include "gf_spi.h"
  9412. +
  9413. +#if defined(USE_SPI_BUS)
  9414. +#include <linux/spi/spi.h>
  9415. +#include <linux/spi/spidev.h>
  9416. +#elif defined(USE_PLATFORM_BUS)
  9417. +#include <linux/platform_device.h>
  9418. +#endif
  9419. +
  9420. +
  9421. +/******************** Function Definitions *************************/
  9422. +
  9423. +#ifdef SPI_ASYNC
  9424. +static void gf_spi_complete(void *arg)
  9425. +{
  9426. + complete(arg);
  9427. +}
  9428. +#endif
  9429. +
  9430. +int gf_spi_read_bytes(struct gf_dev *gf_dev, unsigned short addr, unsigned short data_len,
  9431. + unsigned char *rx_buf)
  9432. +{
  9433. +#ifdef SPI_ASYNC
  9434. + DECLARE_COMPLETION_ONSTACK(write_done);
  9435. +#endif
  9436. + struct spi_message msg;
  9437. + struct spi_transfer *xfer;
  9438. + int ret = 0;
  9439. +
  9440. + xfer = kzalloc(sizeof(*xfer)*2, GFP_KERNEL);
  9441. + if (xfer == NULL) {
  9442. + pr_err("%s, No memory for command.\n", __func__);
  9443. + return -ENOMEM;
  9444. + }
  9445. +
  9446. + /*send gf command to device.*/
  9447. + spi_message_init(&msg);
  9448. + rx_buf[0] = GF_W;
  9449. + rx_buf[1] = (unsigned char)((addr >> 8)&0xFF);
  9450. + rx_buf[2] = (unsigned char)(addr & 0xFF);
  9451. + xfer[0].tx_buf = rx_buf;
  9452. + xfer[0].len = 3;
  9453. + spi_message_add_tail(&xfer[0], &msg);
  9454. +
  9455. + /*if wanted to read data from gf.
  9456. + *Should write Read command to device
  9457. + *before read any data from device.
  9458. + */
  9459. + spi_sync(gf_dev->spi, &msg);
  9460. + spi_message_init(&msg);
  9461. + memset(rx_buf, 0xff, data_len + 4);
  9462. + rx_buf[3] = GF_R;
  9463. + xfer[1].tx_buf = &rx_buf[3];
  9464. + xfer[1].rx_buf = &rx_buf[3];
  9465. + xfer[1].len = data_len + 1;
  9466. +
  9467. + spi_message_add_tail(&xfer[1], &msg);
  9468. +
  9469. +#ifdef SPI_ASYNC
  9470. + msg.complete = gf_spi_complete;
  9471. + msg.context = &write_done;
  9472. +
  9473. + spin_lock_irq(&gf_dev->spi_lock);
  9474. + ret = spi_async(gf_dev->spi, &msg);
  9475. + spin_unlock_irq(&gf_dev->spi_lock);
  9476. + if (ret == 0) {
  9477. + wait_for_completion(&write_done);
  9478. + if (msg.status == 0)
  9479. + ret = msg.actual_length - 1;
  9480. + }
  9481. +#else
  9482. + ret = spi_sync(gf_dev->spi, &msg);
  9483. + if (ret == 0) {
  9484. + ret = msg.actual_length - 1;
  9485. + }
  9486. +#endif
  9487. + kfree(xfer);
  9488. + if (xfer != NULL)
  9489. + xfer = NULL;
  9490. +
  9491. + return 0;
  9492. +}
  9493. +
  9494. +int gf_spi_write_bytes(struct gf_dev *gf_dev, unsigned short addr, unsigned short data_len,
  9495. + unsigned char *tx_buf)
  9496. +{
  9497. +#ifdef SPI_ASYNC
  9498. + DECLARE_COMPLETION_ONSTACK(read_done);
  9499. +#endif
  9500. + struct spi_message msg;
  9501. + struct spi_transfer *xfer;
  9502. + int ret = 0;
  9503. +
  9504. + xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
  9505. + if (xfer == NULL) {
  9506. + pr_err("%s, No memory for command.\n", __func__);
  9507. + return -ENOMEM;
  9508. + }
  9509. +
  9510. + /*send gf command to device.*/
  9511. + spi_message_init(&msg);
  9512. + tx_buf[0] = GF_W;
  9513. + tx_buf[1] = (unsigned char)((addr >> 8)&0xFF);
  9514. + tx_buf[2] = (unsigned char)(addr & 0xFF);
  9515. + xfer[0].tx_buf = tx_buf;
  9516. + xfer[0].len = data_len + 3;
  9517. + spi_message_add_tail(xfer, &msg);
  9518. +#ifdef SPI_ASYNC
  9519. + msg.complete = gf_spi_complete;
  9520. + msg.context = &read_done;
  9521. +
  9522. + spin_lock_irq(&gf_dev->spi_lock);
  9523. + ret = spi_async(gf_dev->spi, &msg);
  9524. + spin_unlock_irq(&gf_dev->spi_lock);
  9525. + if (ret == 0) {
  9526. + wait_for_completion(&read_done);
  9527. + if (msg.status == 0)
  9528. + ret = msg.actual_length - GF_WDATA_OFFSET;
  9529. + }
  9530. +#else
  9531. + ret = spi_sync(gf_dev->spi, &msg);
  9532. + if (ret == 0) {
  9533. + ret = msg.actual_length - GF_WDATA_OFFSET;
  9534. + }
  9535. +#endif
  9536. + kfree(xfer);
  9537. + if (xfer != NULL)
  9538. + xfer = NULL;
  9539. +
  9540. + return 0;
  9541. +}
  9542. +
  9543. +int gf_spi_read_word(struct gf_dev *gf_dev, unsigned short addr, unsigned short *value)
  9544. +{
  9545. + int status = 0;
  9546. + u8 *buf = NULL;
  9547. + mutex_lock(&gf_dev->buf_lock);
  9548. + status = gf_spi_read_bytes(gf_dev, addr, 2, gf_dev->gBuffer);
  9549. + buf = gf_dev->gBuffer + GF_RDATA_OFFSET;
  9550. + *value = ((unsigned short)(buf[0]<<8)) | buf[1];
  9551. + mutex_unlock(&gf_dev->buf_lock);
  9552. + return status;
  9553. +}
  9554. +
  9555. +int gf_spi_write_word(struct gf_dev *gf_dev, unsigned short addr, unsigned short value)
  9556. +{
  9557. + int status = 0;
  9558. + mutex_lock(&gf_dev->buf_lock);
  9559. + gf_dev->gBuffer[GF_WDATA_OFFSET] = 0x00;
  9560. + gf_dev->gBuffer[GF_WDATA_OFFSET+1] = 0x01;
  9561. + gf_dev->gBuffer[GF_WDATA_OFFSET+2] = (u8)(value>>8);
  9562. + gf_dev->gBuffer[GF_WDATA_OFFSET+3] = (u8)(value & 0x00ff);
  9563. + status = gf_spi_write_bytes(gf_dev, addr, 4, gf_dev->gBuffer);
  9564. + mutex_unlock(&gf_dev->buf_lock);
  9565. +
  9566. + return status;
  9567. +}
  9568. +
  9569. +void endian_exchange(int len, unsigned char *buf)
  9570. +{
  9571. + int i;
  9572. + u8 buf_tmp;
  9573. + for (i = 0; i < len/2; i++) {
  9574. + buf_tmp = buf[2*i+1];
  9575. + buf[2*i+1] = buf[2*i] ;
  9576. + buf[2*i] = buf_tmp;
  9577. + }
  9578. +}
  9579. +
  9580. +int gf_spi_read_data(struct gf_dev *gf_dev, unsigned short addr, int len, unsigned char *value)
  9581. +{
  9582. + int status;
  9583. +
  9584. + mutex_lock(&gf_dev->buf_lock);
  9585. + status = gf_spi_read_bytes(gf_dev, addr, len, gf_dev->gBuffer);
  9586. + memcpy(value, gf_dev->gBuffer+GF_RDATA_OFFSET, len);
  9587. + mutex_unlock(&gf_dev->buf_lock);
  9588. +
  9589. + return status;
  9590. +}
  9591. +
  9592. +int gf_spi_read_data_bigendian(struct gf_dev *gf_dev, unsigned short addr, int len, unsigned char *value)
  9593. +{
  9594. + int status;
  9595. +
  9596. + mutex_lock(&gf_dev->buf_lock);
  9597. + status = gf_spi_read_bytes(gf_dev, addr, len, gf_dev->gBuffer);
  9598. + memcpy(value, gf_dev->gBuffer+GF_RDATA_OFFSET, len);
  9599. + mutex_unlock(&gf_dev->buf_lock);
  9600. +
  9601. + endian_exchange(len, value);
  9602. + return status;
  9603. +}
  9604. +
  9605. +int gf_spi_write_data(struct gf_dev *gf_dev, unsigned short addr, int len, unsigned char *value)
  9606. +{
  9607. + int status = 0;
  9608. + unsigned short addr_len = 0;
  9609. + unsigned char *buf = NULL;
  9610. +
  9611. + if (len > 1024 * 10) {
  9612. + pr_err("%s length is large.\n", __func__);
  9613. + return -EPERM;
  9614. + }
  9615. +
  9616. + addr_len = len / 2;
  9617. +
  9618. + buf = kzalloc(len + 2, GFP_KERNEL);
  9619. + if (buf == NULL) {
  9620. + pr_err("%s, No memory for gBuffer.\n", __func__);
  9621. + return -ENOMEM;
  9622. + }
  9623. +
  9624. + buf[0] = (unsigned char) ((addr_len & 0xFF00) >> 8);
  9625. + buf[1] = (unsigned char) (addr_len & 0x00FF);
  9626. + memcpy(buf+2, value, len);
  9627. + endian_exchange(len, buf+2);
  9628. +
  9629. + mutex_lock(&gf_dev->buf_lock);
  9630. + memcpy(gf_dev->gBuffer+GF_WDATA_OFFSET, buf, len+2);
  9631. + kfree(buf);
  9632. +
  9633. + status = gf_spi_write_bytes(gf_dev, addr, len+2, gf_dev->gBuffer);
  9634. + mutex_unlock(&gf_dev->buf_lock);
  9635. +
  9636. + return status;
  9637. +}
  9638. +
  9639. +/***
  9640. + * Yfpan Change gf_spi_send_cmd()interface for Milan HV Series.
  9641. + * (Now add for MilanE HV)
  9642. + ***/
  9643. +int gf_spi_send_cmd(struct gf_dev *gf_dev, unsigned char *cmd, int len)
  9644. +{
  9645. + struct spi_message msg;
  9646. + struct spi_transfer *xfer;
  9647. + int ret;
  9648. +
  9649. + /***
  9650. + * Add for HV Enable and Voltage value
  9651. + **/
  9652. + unsigned short cmd_15v_enable = 0x08D0;
  9653. + unsigned short cmd_14v_enable = 0x18D0;
  9654. + unsigned short cmd_13v_enable = 0x28D0;
  9655. + unsigned short cmd_12v_enable = 0x38D0;
  9656. + unsigned short cmd_11v_enable = 0x48D0;
  9657. + unsigned short cmd_10v_enable = 0x58D0;
  9658. + unsigned short cmd_9v_enable = 0x68D0;
  9659. + unsigned short cmd_8v_enable = 0x78D0;
  9660. + unsigned short cmd_7v_enable = 0x88D0;
  9661. + unsigned short cmd_hv_disable = 0x00D0;
  9662. +
  9663. + spi_message_init(&msg);
  9664. + xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
  9665. +
  9666. + if (xfer == NULL) {
  9667. + pr_err("%s, No memory for command.\n", __func__);
  9668. + return -ENOMEM;
  9669. + }
  9670. +
  9671. + switch (*cmd) {
  9672. + case 0x08:
  9673. + pr_info("%s Enable HV and set voltage to 15v.", __func__);
  9674. + xfer->tx_buf = &cmd_15v_enable;
  9675. + xfer->len = 2;
  9676. + break;
  9677. + case 0x18:
  9678. + pr_info("%s Enable HV and set voltage to 14v.", __func__);
  9679. + xfer->tx_buf = &cmd_14v_enable;
  9680. + xfer->len = 2;
  9681. + break;
  9682. + case 0x28:
  9683. + pr_info("%s Enable HV and set voltage to 13v.", __func__);
  9684. + xfer->tx_buf = &cmd_13v_enable;
  9685. + xfer->len = 2;
  9686. + break;
  9687. + case 0x38:
  9688. + pr_info("%s Enable HV and set voltage to 12v.", __func__);
  9689. + xfer->tx_buf = &cmd_12v_enable;
  9690. + xfer->len = 2;
  9691. + break;
  9692. + case 0x48:
  9693. + pr_info("%s Enable HV and set voltage to 11v.", __func__);
  9694. + xfer->tx_buf = &cmd_11v_enable;
  9695. + xfer->len = 2;
  9696. + break;
  9697. + case 0x58:
  9698. + pr_info("%s Enable HV and set voltage to 10v.", __func__);
  9699. + xfer->tx_buf = &cmd_10v_enable;
  9700. + xfer->len = 2;
  9701. + break;
  9702. + case 0x68:
  9703. + pr_info("%s Enable HV and set voltage to 9v.", __func__);
  9704. + xfer->tx_buf = &cmd_9v_enable;
  9705. + xfer->len = 2;
  9706. + break;
  9707. + case 0x78:
  9708. + pr_info("%s Enable HV and set voltage to 8v.", __func__);
  9709. + xfer->tx_buf = &cmd_8v_enable;
  9710. + xfer->len = 2;
  9711. + break;
  9712. + case 0x88:
  9713. + case 0x98:
  9714. + case 0xa8:
  9715. + case 0xb8:
  9716. + case 0xd8:
  9717. + pr_info("%s Enable HV and set voltage to 7v.", __func__);
  9718. + xfer->tx_buf = &cmd_7v_enable;
  9719. + xfer->len = 2;
  9720. + break;
  9721. + case 0x00:
  9722. + pr_info("%s Disable HV.", __func__);
  9723. + xfer->tx_buf = &cmd_hv_disable;
  9724. + xfer->len = 2;
  9725. + break;
  9726. + default:
  9727. + xfer->tx_buf = cmd;
  9728. + xfer->len = len;
  9729. + break;
  9730. + }
  9731. +
  9732. + spi_message_add_tail(xfer, &msg);
  9733. + ret = spi_sync(gf_dev->spi, &msg);
  9734. +
  9735. + kfree(xfer);
  9736. + if (xfer != NULL)
  9737. + xfer = NULL;
  9738. +
  9739. + return ret;
  9740. +}
  9741. diff --git a/drivers/input/fingerprint/goodix/gf_common.h b/drivers/input/fingerprint/goodix/gf_common.h
  9742. new file mode 100644
  9743. index 0000000..7c10ef9
  9744. --- /dev/null
  9745. +++ b/drivers/input/fingerprint/goodix/gf_common.h
  9746. @@ -0,0 +1,27 @@
  9747. +#ifndef __GF_COMMON_H__
  9748. +#define __GF_COMMON_H__
  9749. +
  9750. +#include "gf_spi.h"
  9751. +
  9752. +/****************Function prototypes*****************/
  9753. +int gf_spi_read_bytes(struct gf_dev *gf_dev, unsigned short addr,
  9754. + unsigned short data_len, unsigned char *rx_buf);
  9755. +
  9756. +int gf_spi_write_bytes(struct gf_dev *gf_dev, unsigned short addr,
  9757. + unsigned short data_len, unsigned char *tx_buf);
  9758. +
  9759. +int gf_spi_read_word(struct gf_dev *gf_dev, unsigned short addr, unsigned short *value);
  9760. +
  9761. +int gf_spi_write_word(struct gf_dev *gf_dev, unsigned short addr, unsigned short value);
  9762. +
  9763. +int gf_spi_read_data(struct gf_dev *gf_dev, unsigned short addr,
  9764. + int len, unsigned char *value);
  9765. +
  9766. +int gf_spi_read_data_bigendian(struct gf_dev *gf_dev, unsigned short addr,
  9767. + int len, unsigned char *value);
  9768. +
  9769. +int gf_spi_write_data(struct gf_dev *gf_dev, unsigned short addr,
  9770. + int len, unsigned char *value);
  9771. +
  9772. +int gf_spi_send_cmd(struct gf_dev *gf_dev, unsigned char *cmd, int len);
  9773. +#endif
  9774. diff --git a/drivers/input/fingerprint/goodix/gf_spi.c b/drivers/input/fingerprint/goodix/gf_spi.c
  9775. new file mode 100644
  9776. index 0000000..63769bd
  9777. --- /dev/null
  9778. +++ b/drivers/input/fingerprint/goodix/gf_spi.c
  9779. @@ -0,0 +1,986 @@
  9780. +/*Simple synchronous userspace interface to SPI devices
  9781. + *
  9782. + * Copyright (C) 2006 SWAPP
  9783. + * Andrea Paterniani <a.paterniani@swapp-eng.it>
  9784. + * Copyright (C) 2007 David Brownell (simplification, cleanup)
  9785. + * Copyright (C) 2017 XiaoMi, Inc.
  9786. + *
  9787. + * This program is free software; you can redistribute it and/or modify
  9788. + * it under the terms of the GNU General Public License as published by
  9789. + * the Free Software Foundation; either version 2 of the License, or
  9790. + * (at your option) any later version.
  9791. + *
  9792. + * This program is distributed in the hope that it will be useful,
  9793. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9794. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9795. + * GNU General Public License for more details.
  9796. + *
  9797. + * You should have received a copy of the GNU General Public License
  9798. + * along with this program; if not, write to the Free Software
  9799. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  9800. + */
  9801. +#include <linux/init.h>
  9802. +#include <linux/module.h>
  9803. +#include <linux/ioctl.h>
  9804. +#include <linux/fs.h>
  9805. +#include <linux/device.h>
  9806. +#include <linux/input.h>
  9807. +#include <linux/clk.h>
  9808. +#include <linux/err.h>
  9809. +#include <linux/list.h>
  9810. +#include <linux/errno.h>
  9811. +#include <linux/mutex.h>
  9812. +#include <linux/slab.h>
  9813. +#include <linux/compat.h>
  9814. +#include <linux/delay.h>
  9815. +#include <asm/uaccess.h>
  9816. +#include <linux/ktime.h>
  9817. +#include <linux/interrupt.h>
  9818. +#include <linux/irq.h>
  9819. +#include <linux/gpio.h>
  9820. +#include <linux/regulator/consumer.h>
  9821. +#include <linux/of_gpio.h>
  9822. +#include <linux/timer.h>
  9823. +#include <linux/notifier.h>
  9824. +#include <linux/fb.h>
  9825. +#include <linux/pm_qos.h>
  9826. +#include <linux/cpufreq.h>
  9827. +#include <linux/wakelock.h>
  9828. +#include "gf_spi.h"
  9829. +#include "gf_common.h"
  9830. +
  9831. +#if defined(USE_SPI_BUS)
  9832. +#include <linux/spi/spi.h>
  9833. +#include <linux/spi/spidev.h>
  9834. +#elif defined(USE_PLATFORM_BUS)
  9835. +#include <linux/platform_device.h>
  9836. +#endif
  9837. +
  9838. +#define GF_SPIDEV_NAME "goodix,fingerprint"
  9839. +/*device name after register in charater*/
  9840. +#define GF_DEV_NAME "goodix_fp"
  9841. +#define GF_INPUT_NAME "qwerty" /*"goodix_fp" */
  9842. +
  9843. +#define CHRD_DRIVER_NAME "goodix_fp_spi"
  9844. +#define CLASS_NAME "goodix_fp"
  9845. +
  9846. +#define SPIDEV_MAJOR 214 /* assigned */
  9847. +#define N_SPI_MINORS 32 /* ... up to 256 */
  9848. +
  9849. +
  9850. +/*GF regs*/
  9851. +#define GF_CHIP_ID_LO 0x0000
  9852. +#define GF_CHIP_ID_HI 0x0002
  9853. +#define GF_VENDOR_ID 0x0006
  9854. +#define GF_IRQ_CTRL2 0x0124
  9855. +#define GF_IRQ_CTRL3 0x0126
  9856. +
  9857. +/*GF input keys*/
  9858. +#define GF_KEY_POWER KEY_POWER
  9859. +#define GF_KEY_HOME KEY_HOME
  9860. +#define GF_KEY_MENU KEY_MENU
  9861. +#define GF_KEY_BACK KEY_BACK
  9862. +#define GF_UP_KEY KEY_UP
  9863. +#define GF_DOWN_KEY KEY_DOWN
  9864. +#define GF_LEFT_KEY KEY_LEFT
  9865. +#define GF_RIGHT_KEY KEY_RIGHT
  9866. +#define GF_KEY_FORCE KEY_F9
  9867. +#define GF_APP_SWITCH KEY_F19
  9868. +#define GF_KEY_F1 KEY_F1
  9869. +#define GF_KEY_F2 KEY_F2
  9870. +#define GF_KEY_F3 KEY_F3
  9871. +/**************************debug******************************/
  9872. +#define GF_DEBUG
  9873. +/*#undef GF_DEBUG*/
  9874. +
  9875. +#ifdef GF_DEBUG
  9876. +#define gf_dbg(fmt, args...) do { \
  9877. + pr_info("gf:" fmt, ##args);\
  9878. +} while (0)
  9879. +#define FUNC_ENTRY() pr_info("gf:%s, entry\n", __func__)
  9880. +#define FUNC_EXIT() pr_info("gf:%s, exit\n", __func__)
  9881. +#else
  9882. +#define gf_dbg(fmt, args...)
  9883. +#define FUNC_ENTRY()
  9884. +#define FUNC_EXIT()
  9885. +#endif
  9886. +
  9887. +/*Global variables*/
  9888. +static DECLARE_BITMAP(minors, N_SPI_MINORS);
  9889. +static LIST_HEAD(device_list);
  9890. +static DEFINE_MUTEX(device_list_lock);
  9891. +
  9892. +static struct gf_dev gf;
  9893. +static unsigned int bufsiz = 22180;
  9894. +static unsigned char g_frame_buf[22180] = {0};
  9895. +static unsigned short g_vendorID = 0;
  9896. +static unsigned int g_chipID = 0;
  9897. +static struct wake_lock fp_wakelock;
  9898. +static unsigned int gf_spi_speed[GF_SPI_KEEP_SPEED] = {4800000, 4800000};
  9899. +
  9900. +/******************* CLK Related Start ****************/
  9901. +static long spi_clk_max_rate(struct clk *clk, unsigned long rate)
  9902. +{
  9903. + long lowest_available, nearest_low, step_size, cur;
  9904. + long step_direction = -1;
  9905. + long guess = rate;
  9906. + int max_steps = 10;
  9907. +
  9908. + FUNC_ENTRY();
  9909. + cur = clk_round_rate(clk, rate);
  9910. + if (cur == rate)
  9911. + return rate;
  9912. +
  9913. + /* if we got here then: cur > rate */
  9914. + lowest_available = clk_round_rate(clk, 0);
  9915. + if (lowest_available > rate)
  9916. + return -EINVAL;
  9917. +
  9918. + step_size = (rate - lowest_available) >> 1;
  9919. + nearest_low = lowest_available;
  9920. +
  9921. + while (max_steps-- && step_size) {
  9922. + guess += step_size * step_direction;
  9923. + cur = clk_round_rate(clk, guess);
  9924. +
  9925. + if ((cur < rate) && (cur > nearest_low))
  9926. + nearest_low = cur;
  9927. + /*
  9928. + * if we stepped too far, then start stepping in the other
  9929. + * direction with half the step size
  9930. + */
  9931. + if (((cur > rate) && (step_direction > 0))
  9932. + || ((cur < rate) && (step_direction < 0))) {
  9933. + step_direction = -step_direction;
  9934. + step_size >>= 1;
  9935. + }
  9936. + }
  9937. + return nearest_low;
  9938. +}
  9939. +
  9940. +static void spi_clock_set(struct gf_dev *gf_dev, int speed)
  9941. +{
  9942. + long rate;
  9943. + int rc;
  9944. + FUNC_ENTRY();
  9945. +
  9946. + rate = spi_clk_max_rate(gf_dev->core_clk, speed);
  9947. + if (rate < 0) {
  9948. + pr_info("%s: no match found for requested clock frequency:%d",
  9949. + __func__, speed);
  9950. + return;
  9951. + }
  9952. +
  9953. + rc = clk_set_rate(gf_dev->core_clk, rate);
  9954. +}
  9955. +
  9956. +#ifdef USE_SPI_BUS
  9957. +static int gfspi_ioctl_clk_init(struct spi_device *spi, struct gf_dev *data)
  9958. +{
  9959. + pr_debug("%s: enter\n", __func__);
  9960. +
  9961. + FUNC_ENTRY();
  9962. + data->clk_enabled = 0;
  9963. + data->core_clk = clk_get(&spi->dev, "core_clk");
  9964. + if (IS_ERR_OR_NULL(data->core_clk)) {
  9965. + pr_err("%s: fail to get core_clk\n", __func__);
  9966. + return -EPERM;
  9967. + }
  9968. + data->iface_clk = clk_get(&spi->dev, "iface_clk");
  9969. + if (IS_ERR_OR_NULL(data->iface_clk)) {
  9970. + pr_err("%s: fail to get iface_clk\n", __func__);
  9971. + clk_put(data->core_clk);
  9972. + data->core_clk = NULL;
  9973. + return -ENOENT;
  9974. + }
  9975. + return 0;
  9976. +}
  9977. +
  9978. +static int gfspi_ioctl_clk_enable(struct gf_dev *data)
  9979. +{
  9980. + int err;
  9981. +
  9982. + pr_debug("%s: enter\n", __func__);
  9983. + FUNC_ENTRY();
  9984. +
  9985. + if (data->clk_enabled)
  9986. + return 0;
  9987. +
  9988. + err = clk_prepare_enable(data->core_clk);
  9989. + if (err) {
  9990. + pr_err("%s: fail to enable core_clk\n", __func__);
  9991. + return -EPERM;
  9992. + }
  9993. +
  9994. + err = clk_prepare_enable(data->iface_clk);
  9995. + if (err) {
  9996. + pr_err("%s: fail to enable iface_clk\n", __func__);
  9997. + clk_disable_unprepare(data->core_clk);
  9998. + return -ENOENT;
  9999. + }
  10000. +
  10001. + data->clk_enabled = 1;
  10002. +
  10003. + return 0;
  10004. +}
  10005. +
  10006. +static int gfspi_ioctl_clk_disable(struct gf_dev *data)
  10007. +{
  10008. + FUNC_ENTRY();
  10009. +
  10010. + if (!data->clk_enabled)
  10011. + return 0;
  10012. +
  10013. + clk_disable_unprepare(data->core_clk);
  10014. + clk_disable_unprepare(data->iface_clk);
  10015. + data->clk_enabled = 0;
  10016. +
  10017. + return 0;
  10018. +}
  10019. +
  10020. +static int gfspi_ioctl_clk_uninit(struct gf_dev *data)
  10021. +{
  10022. + pr_debug("%s: enter\n", __func__);
  10023. +
  10024. + FUNC_ENTRY();
  10025. + if (data->clk_enabled)
  10026. + gfspi_ioctl_clk_disable(data);
  10027. +
  10028. + if (!IS_ERR_OR_NULL(data->core_clk)) {
  10029. + clk_put(data->core_clk);
  10030. + data->core_clk = NULL;
  10031. + }
  10032. +
  10033. + if (!IS_ERR_OR_NULL(data->iface_clk)) {
  10034. + clk_put(data->iface_clk);
  10035. + data->iface_clk = NULL;
  10036. + }
  10037. +
  10038. + return 0;
  10039. +}
  10040. +#endif
  10041. +/******************* CLK Related End ****************/
  10042. +
  10043. +/******************* Enable/Disable IRQ Start ****************/
  10044. +static void gf_enable_irq(struct gf_dev *gf_dev)
  10045. +{
  10046. + FUNC_ENTRY();
  10047. +
  10048. + if (gf_dev->irq_enabled) {
  10049. + pr_warn("IRQ has been enabled.\n");
  10050. + } else {
  10051. + enable_irq(gf_dev->irq);
  10052. + gf_dev->irq_enabled = 1;
  10053. + }
  10054. +
  10055. + FUNC_EXIT();
  10056. +}
  10057. +
  10058. +static void gf_disable_irq(struct gf_dev *gf_dev)
  10059. +{
  10060. + FUNC_ENTRY();
  10061. +
  10062. + if (gf_dev->irq_enabled) {
  10063. + gf_dev->irq_enabled = 0;
  10064. + disable_irq(gf_dev->irq);
  10065. + } else {
  10066. + pr_warn("IRQ has been disabled.\n");
  10067. + }
  10068. +
  10069. + FUNC_EXIT();
  10070. +}
  10071. +/******************* Enable/Disable IRQ End ****************/
  10072. +
  10073. +void gf_spi_setup(struct gf_dev *gf_dev, enum gf_spi_transfer_speed speed)
  10074. +{
  10075. +
  10076. + int ret = 0;
  10077. +
  10078. + pr_info("####### %s %d \n", __func__, __LINE__);
  10079. + if (speed == GF_SPI_KEEP_SPEED)
  10080. + return;
  10081. + gf_dev->spi->mode = SPI_MODE_0;
  10082. + gf_dev->spi->max_speed_hz = gf_spi_speed[speed];
  10083. + gf_dev->spi->bits_per_word = 8;
  10084. + ret = spi_setup(gf_dev->spi);
  10085. + pr_info("%s spi_setup ret = %d", __func__, ret);
  10086. +}
  10087. +
  10088. +static int gf_write_configs(struct gf_dev *gf_dev, struct gf_configs *config, int len)
  10089. +{
  10090. + int cnt;
  10091. + int length = len;
  10092. + int ret = 0;
  10093. + for (cnt = 0; cnt < length; cnt++) {
  10094. + ret = gf_spi_write_word(gf_dev, config[cnt].addr, config[cnt].value);
  10095. + if (ret < 0) {
  10096. + pr_info("%s failed. \n", __func__);
  10097. + return ret;
  10098. + }
  10099. + }
  10100. +
  10101. + return 0;
  10102. +}
  10103. +
  10104. +static ssize_t gf_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  10105. +{
  10106. + struct gf_dev *gf_dev = filp->private_data;
  10107. + int status = 0;
  10108. + int len = 0;
  10109. +
  10110. + if (buf == NULL || count > bufsiz) {
  10111. + pr_info("%s input parameters invalid. bufsiz = %d,count = %d \n",
  10112. + __func__, bufsiz, (int)count);
  10113. + return -EMSGSIZE;
  10114. + }
  10115. +
  10116. + len = gf_spi_read_data(gf_dev, 0xAAAA, count, g_frame_buf);
  10117. + status = copy_to_user(buf, g_frame_buf, count);
  10118. + if (status != 0) {
  10119. + pr_info("%s copy_to_user failed. status = %d \n", __func__, status);
  10120. + return -EFAULT;
  10121. + }
  10122. + return 0;
  10123. +}
  10124. +
  10125. +
  10126. +static long gf_ioctl(struct file *filp, unsigned int cmd,
  10127. + unsigned long arg)
  10128. +{
  10129. + struct gf_dev *gf_dev = NULL;
  10130. + struct gf_ioc_transfer *ioc = NULL;
  10131. + struct gf_key gf_key = {0};
  10132. + u8 *tmpbuf = NULL;
  10133. + int ret = 0;
  10134. + int retval = 0;
  10135. + int err = 0;
  10136. + unsigned char command = 0;
  10137. + struct gf_configs *p_cfg = NULL;
  10138. + unsigned char cfg_len = 0;
  10139. + struct gf_mode_config *p_mode_cfg = NULL;
  10140. + enum gf_spi_transfer_speed speed;
  10141. +
  10142. + if (_IOC_TYPE(cmd) != GF_IOC_MAGIC)
  10143. + return -ENOTTY;
  10144. + /* Check access direction once here; don't repeat below.
  10145. + * IOC_DIR is from the user perspective, while access_ok is
  10146. + * from the kernel perspective; so they look reversed.
  10147. + */
  10148. + if (_IOC_DIR(cmd) & _IOC_READ)
  10149. + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
  10150. + if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
  10151. + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
  10152. + if (err)
  10153. + return -EFAULT;
  10154. +
  10155. + gf_dev = (struct gf_dev *)filp->private_data;
  10156. + switch (cmd) {
  10157. + case GF_IOC_RW:
  10158. + ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
  10159. + if (ioc == NULL) {
  10160. + pr_info("kzalloc ioc failed. \n");
  10161. + retval = -ENOMEM;
  10162. + break;
  10163. + }
  10164. +
  10165. + /*copy command data from user to kernel.*/
  10166. + if (copy_from_user(ioc, (struct gf_ioc_transfer *)arg, sizeof(*ioc))) {
  10167. + pr_info("Failed to copy command from user to kernel.\n");
  10168. + retval = -EFAULT;
  10169. + break;
  10170. + }
  10171. +
  10172. + tmpbuf = kzalloc(ioc->len, GFP_KERNEL);
  10173. + if (tmpbuf == NULL) {
  10174. + pr_info("kzalloc buf failed. \n");
  10175. + retval = -ENOMEM;
  10176. + break;
  10177. + }
  10178. + if ((ioc->len > bufsiz) || (ioc->len == 0)) {
  10179. + pr_info("%s The request length[%d] is longer than supported maximum buffer length[%d].\n"
  10180. + , __func__, ioc->len, bufsiz);
  10181. + retval = -EMSGSIZE;
  10182. + break;
  10183. + }
  10184. +
  10185. + if (ioc->cmd == GF_R) {
  10186. + mutex_lock(&gf_dev->frame_lock);
  10187. + gf_spi_read_data(gf_dev, ioc->addr, ioc->len, tmpbuf);
  10188. +
  10189. + ret = copy_to_user((void __user *)ioc->buf, tmpbuf, ioc->len);
  10190. + mutex_unlock(&gf_dev->frame_lock);
  10191. +
  10192. + if (ret) {
  10193. + pr_info("%s Failed to copy data from kernel to user.\n", __func__);
  10194. + retval = -EFAULT;
  10195. + break;
  10196. + }
  10197. + } else if (ioc->cmd == GF_W) {
  10198. + ret = copy_from_user(tmpbuf, (void __user *)ioc->buf, ioc->len);
  10199. + if (ret) {
  10200. + pr_info("%s Failed to copy data from user to kernel.\n", __func__);
  10201. + retval = -EFAULT;
  10202. + break;
  10203. + }
  10204. + mutex_lock(&gf_dev->frame_lock);
  10205. + gf_spi_write_data(gf_dev, ioc->addr, ioc->len, tmpbuf);
  10206. + mutex_unlock(&gf_dev->frame_lock);
  10207. + } else {
  10208. + pr_warn("%s Error command for ioc->cmd.\n", __func__);
  10209. + retval = -EFAULT;
  10210. + }
  10211. + break;
  10212. + case GF_IOC_CMD:
  10213. + retval = __get_user(command , (u32 __user *)arg);
  10214. + mutex_lock(&gf_dev->frame_lock);
  10215. + gf_spi_send_cmd(gf_dev, &command, 1);
  10216. + mutex_unlock(&gf_dev->frame_lock);
  10217. + mdelay(1);
  10218. + break;
  10219. + case GF_IOC_CONFIG:
  10220. + p_mode_cfg = kzalloc(sizeof(*p_mode_cfg), GFP_KERNEL);
  10221. + if (p_mode_cfg == NULL) {
  10222. + pr_info("kzalloc p_mode_cfg failed. \n");
  10223. + retval = -ENOMEM;
  10224. + break;
  10225. + }
  10226. +
  10227. + if (copy_from_user(p_mode_cfg, (struct gf_mode_config *)arg, sizeof(*p_mode_cfg))) {
  10228. + pr_info("Failed to copy command from user to kernel.\n");
  10229. + retval = -EFAULT;
  10230. + break;
  10231. + }
  10232. +
  10233. + cfg_len = p_mode_cfg->cfg_len*sizeof(struct gf_configs);
  10234. + if (cfg_len > 0) {
  10235. + p_cfg = kzalloc(cfg_len, GFP_KERNEL);
  10236. + if (p_mode_cfg == NULL) {
  10237. + pr_info("kzalloc p_cfg failed. \n");
  10238. + retval = -ENOMEM;
  10239. + break;
  10240. + }
  10241. + } else {
  10242. + pr_info("err cfg_len = %d\n", cfg_len);
  10243. + retval = -EFAULT;
  10244. + break;
  10245. + }
  10246. +
  10247. + if (copy_from_user(p_cfg, p_mode_cfg->p_cfg, cfg_len)) {
  10248. + pr_info("Failed to copy command from user to kernel.\n");
  10249. + retval = -EFAULT;
  10250. + break;
  10251. + }
  10252. + gf_write_configs(gf_dev, p_cfg, p_mode_cfg->cfg_len);
  10253. + break;
  10254. + case GF_IOC_RESET:
  10255. + pr_info("%s GF_IOC_REINIT \n", __func__);
  10256. +
  10257. + gf_hw_reset(gf_dev, 0);
  10258. + break;
  10259. + case GF_IOC_ENABLE_IRQ:
  10260. + pr_info("%s ++++++++++++ GF_IOC_ENABLE_IRQ \n", __func__);
  10261. + gf_enable_irq(gf_dev);
  10262. + break;
  10263. + case GF_IOC_DISABLE_IRQ:
  10264. + pr_info("%s ------------ GF_IOC_DISABLE_IRQ \n", __func__);
  10265. + gf_disable_irq(gf_dev);
  10266. + break;
  10267. + case GF_IOC_SENDKEY:
  10268. + if (copy_from_user
  10269. + (&gf_key, (struct gf_key *)arg, sizeof(struct gf_key))) {
  10270. + pr_warn("Failed to copy data from user space,line=%d.\n", __LINE__);
  10271. + retval = -EFAULT;
  10272. + break;
  10273. +
  10274. + }
  10275. + input_report_key(gf_dev->input, gf_key.key, gf_key.value);
  10276. + input_sync(gf_dev->input);
  10277. + break;
  10278. + case GF_IOC_SETSPEED:
  10279. + retval = __get_user(speed, (u32 __user *)arg);
  10280. + gf_spi_setup(gf_dev, speed);
  10281. + break;
  10282. + default:
  10283. + pr_info("%s gf doesn't support this command.\n", __func__);
  10284. + pr_info("%s CMD = 0x%x,_IOC_DIR:0x%x,_IOC_TYPE:0x%x,IOC_NR:0x%x,IOC_SIZE:0x%x\n",
  10285. + __func__, cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
  10286. + retval = -EFAULT;
  10287. + break;
  10288. + }
  10289. +
  10290. + if (tmpbuf != NULL) {
  10291. + kfree(tmpbuf);
  10292. + tmpbuf = NULL;
  10293. + }
  10294. + if (ioc != NULL) {
  10295. + kfree(ioc);
  10296. + ioc = NULL;
  10297. + }
  10298. + if (p_cfg != NULL) {
  10299. + kfree(p_cfg);
  10300. + p_cfg = NULL;
  10301. + }
  10302. + if (p_mode_cfg != NULL) {
  10303. + kfree(p_mode_cfg);
  10304. + p_mode_cfg = NULL;
  10305. + }
  10306. + return retval;
  10307. +}
  10308. +
  10309. +#ifdef CONFIG_COMPAT
  10310. + static long
  10311. +gf_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  10312. +{
  10313. + return gf_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
  10314. +}
  10315. +#endif /*CONFIG_COMPAT*/
  10316. +
  10317. +static irqreturn_t gf_irq(int irq, void *handle)
  10318. +{
  10319. + struct gf_dev *gf_dev = &gf;
  10320. + unsigned short irq_reg = 0;
  10321. +
  10322. + wake_lock(&fp_wakelock);
  10323. +#ifdef GF_FASYNC
  10324. + gf_spi_read_word(gf_dev, GF_IRQ_CTRL3, &irq_reg);
  10325. + if (irq_reg != 0x08) {
  10326. + if (gf_dev->async)
  10327. + kill_fasync(&gf_dev->async, SIGIO, POLL_IN);
  10328. + }
  10329. +#endif
  10330. +
  10331. + return IRQ_HANDLED;
  10332. +}
  10333. +
  10334. +static int gf_open(struct inode *inode, struct file *filp)
  10335. +{
  10336. + struct gf_dev *gf_dev;
  10337. + int status = -ENXIO;
  10338. + int cnt = 0;
  10339. + unsigned short reg = 0;
  10340. +
  10341. + FUNC_ENTRY();
  10342. +
  10343. + mutex_lock(&device_list_lock);
  10344. +
  10345. + list_for_each_entry(gf_dev, &device_list, device_entry) {
  10346. + if (gf_dev->devt == inode->i_rdev) {
  10347. + gf_dbg("Found\n");
  10348. + status = 0;
  10349. + break;
  10350. + }
  10351. + }
  10352. +
  10353. + if (status == 0) {
  10354. + if (status == 0) {
  10355. + gf_dev->users++;
  10356. + filp->private_data = gf_dev;
  10357. +
  10358. + gf_hw_reset(gf_dev, 0);
  10359. + while (cnt < 5) {
  10360. + gf_spi_read_word(gf_dev, GF_IRQ_CTRL3, &reg);
  10361. + if (reg == 0x100 || reg == 0x400 || reg == 0x800) {
  10362. + gf_spi_write_word(gf_dev, GF_IRQ_CTRL2, reg);
  10363. + gf_dbg("reg = 0x%04x cnt = %d\n", reg, cnt);
  10364. + break;
  10365. + }
  10366. + cnt++;
  10367. + }
  10368. +
  10369. + nonseekable_open(inode, filp);
  10370. + gf_dbg("Succeed to open device. irq = %d, user = %d\n",
  10371. + gf_dev->irq, gf_dev->users);
  10372. + if (gf_dev->users == 1) {
  10373. + gf_enable_irq(gf_dev);
  10374. + }
  10375. + }
  10376. + } else {
  10377. + gf_dbg("No device for minor %d\n", iminor(inode));
  10378. + }
  10379. +
  10380. + mutex_unlock(&device_list_lock);
  10381. + FUNC_EXIT();
  10382. + return status;
  10383. +}
  10384. +
  10385. +#ifdef GF_FASYNC
  10386. +static int gf_fasync(int fd, struct file *filp, int mode)
  10387. +{
  10388. + struct gf_dev *gf_dev = filp->private_data;
  10389. + int ret;
  10390. +
  10391. + FUNC_ENTRY();
  10392. + ret = fasync_helper(fd, filp, mode, &gf_dev->async);
  10393. + FUNC_EXIT();
  10394. + gf_dbg("ret = %d\n", ret);
  10395. + return ret;
  10396. +}
  10397. +#endif
  10398. +
  10399. +static int gf_release(struct inode *inode, struct file *filp)
  10400. +{
  10401. + struct gf_dev *gf_dev;
  10402. + int status = 0;
  10403. +
  10404. + FUNC_ENTRY();
  10405. + mutex_lock(&device_list_lock);
  10406. + gf_dev = filp->private_data;
  10407. + filp->private_data = NULL;
  10408. +
  10409. + /*last close?? */
  10410. + gf_dev->users--;
  10411. + if (!gf_dev->users) {
  10412. +
  10413. + gf_dbg("disble_irq. irq = %d\n", gf_dev->irq);
  10414. + gf_disable_irq(gf_dev);
  10415. + }
  10416. + mutex_unlock(&device_list_lock);
  10417. + FUNC_EXIT();
  10418. + return status;
  10419. +}
  10420. +
  10421. +static const struct file_operations gf_fops = {
  10422. + .owner = THIS_MODULE,
  10423. + /* REVISIT switch to aio primitives, so that userspace
  10424. + * gets more complete API coverage. It'll simplify things
  10425. + * too, except for the locking.
  10426. + */
  10427. + .unlocked_ioctl = gf_ioctl,
  10428. +#ifdef CONFIG_COMPAT
  10429. + .compat_ioctl = gf_compat_ioctl,
  10430. +#endif /*CONFIG_COMPAT*/
  10431. + .open = gf_open,
  10432. + .release = gf_release,
  10433. + .read = gf_read,
  10434. +#ifdef GF_FASYNC
  10435. + .fasync = gf_fasync,
  10436. +#endif
  10437. +};
  10438. +
  10439. +static void gf_reg_key_kernel(struct gf_dev *gf_dev)
  10440. +{
  10441. + __set_bit(EV_KEY, gf_dev->input->evbit);
  10442. + __set_bit(GF_KEY_POWER, gf_dev->input->keybit);
  10443. + __set_bit(GF_KEY_HOME, gf_dev->input->keybit);
  10444. + __set_bit(GF_KEY_MENU, gf_dev->input->keybit);
  10445. + __set_bit(GF_KEY_BACK, gf_dev->input->keybit);
  10446. + __set_bit(GF_UP_KEY, gf_dev->input->keybit);
  10447. + __set_bit(GF_RIGHT_KEY, gf_dev->input->keybit);
  10448. + __set_bit(GF_LEFT_KEY, gf_dev->input->keybit);
  10449. + __set_bit(GF_DOWN_KEY, gf_dev->input->keybit);
  10450. + __set_bit(GF_KEY_FORCE, gf_dev->input->keybit);
  10451. + __set_bit(GF_APP_SWITCH, gf_dev->input->keybit);
  10452. +
  10453. +
  10454. + __set_bit(GF_KEY_F1, gf_dev->input->keybit);
  10455. + __set_bit(GF_KEY_F2, gf_dev->input->keybit);
  10456. + __set_bit(GF_KEY_F3, gf_dev->input->keybit);
  10457. +
  10458. + gf_dev->input->name = GF_INPUT_NAME;
  10459. + if (input_register_device(gf_dev->input))
  10460. + pr_warn("Failed to register GF as input device.\n");
  10461. +}
  10462. +
  10463. +static struct class *gf_class;
  10464. +#if defined(USE_SPI_BUS)
  10465. +static int gf_probe(struct spi_device *spi)
  10466. +#elif defined(USE_PLATFORM_BUS)
  10467. +static int gf_probe(struct platform_device *pdev)
  10468. +#endif
  10469. +{
  10470. + struct gf_dev *gf_dev = &gf;
  10471. + int status = -EINVAL;
  10472. + unsigned long minor;
  10473. + int ret;
  10474. + unsigned short chip_id_1 = 0;
  10475. + unsigned short chip_id_2 = 0;
  10476. + FUNC_ENTRY();
  10477. + /* Initialize the driver data */
  10478. + INIT_LIST_HEAD(&gf_dev->device_entry);
  10479. +#if defined(USE_SPI_BUS)
  10480. + gf_dev->spi = spi;
  10481. +#elif defined(USE_PLATFORM_BUS)
  10482. + gf_dev->spi = pdev;
  10483. +#endif
  10484. + gf_dev->irq_gpio = -EINVAL;
  10485. + gf_dev->reset_gpio = -EINVAL;
  10486. + gf_dev->pwr_gpio = -EINVAL;
  10487. + gf_dev->device_available = 0;
  10488. + gf_dev->fb_black = 0;
  10489. +
  10490. + mutex_init(&gf_dev->buf_lock);
  10491. + mutex_init(&gf_dev->frame_lock);
  10492. + spin_lock_init(&gf_dev->spi_lock);
  10493. +
  10494. + if (gf_parse_dts(gf_dev))
  10495. + goto error;
  10496. +
  10497. + if (gf_power_on(gf_dev))
  10498. + goto error;
  10499. +
  10500. + if (gf_hw_reset(gf_dev, 0))
  10501. + goto error;
  10502. +
  10503. + /* If we can allocate a minor number, hook up this device.
  10504. + * Reusing minors is fine so long as udev or mdev is working.
  10505. + */
  10506. + mutex_lock(&device_list_lock);
  10507. + minor = find_first_zero_bit(minors, N_SPI_MINORS);
  10508. + if (minor < N_SPI_MINORS) {
  10509. + struct device *dev;
  10510. +
  10511. + gf_dev->devt = MKDEV(SPIDEV_MAJOR, minor);
  10512. + dev = device_create(gf_class, &gf_dev->spi->dev, gf_dev->devt,
  10513. + gf_dev, GF_DEV_NAME);
  10514. + status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
  10515. + } else {
  10516. + dev_dbg(&gf_dev->spi->dev, "no minor number available!\n");
  10517. + status = -ENODEV;
  10518. + }
  10519. +
  10520. + if (status == 0) {
  10521. + set_bit(minor, minors);
  10522. + list_add(&gf_dev->device_entry, &device_list);
  10523. + } else {
  10524. + gf_dev->devt = 0;
  10525. + }
  10526. + mutex_unlock(&device_list_lock);
  10527. + wake_lock_init(&fp_wakelock, WAKE_LOCK_SUSPEND, "fp_wakelock");
  10528. +
  10529. + if (status == 0) {
  10530. + gf_dev->gBuffer = kzalloc(bufsiz + GF_RDATA_OFFSET, GFP_KERNEL);
  10531. + if (gf_dev->gBuffer == NULL) {
  10532. + return -ENOMEM;
  10533. + }
  10534. +
  10535. + /*input device subsystem */
  10536. + gf_dev->input = input_allocate_device();
  10537. + if (gf_dev->input == NULL) {
  10538. + dev_dbg(&gf_dev->input->dev,
  10539. + "Faile to allocate input device.\n");
  10540. + status = -ENOMEM;
  10541. + }
  10542. +#ifdef USE_SPI_BUS
  10543. + /* Enable spi clock */
  10544. + if (gfspi_ioctl_clk_init(spi, gf_dev))
  10545. + goto gfspi_probe_clk_init_failed;
  10546. +
  10547. + if (gfspi_ioctl_clk_enable(gf_dev))
  10548. + goto gfspi_probe_clk_enable_failed;
  10549. +
  10550. + spi_clock_set(gf_dev, 9600000);
  10551. +#else
  10552. + pr_info("Get the clk resource.\n");
  10553. + gf_dev->core_clk = clk_get(&pdev->dev, "core_clk");
  10554. + if (IS_ERR(gf_dev->core_clk)) {
  10555. + pr_warn("Failed to get core_clk.\n");
  10556. + goto error;
  10557. + }
  10558. + gf_dev->iface_clk = clk_get(&pdev->dev, "iface_clk");
  10559. + if (IS_ERR(gf_dev->iface_clk)) {
  10560. + pr_warn("Failed to get iface_clk.\n");
  10561. + goto error;
  10562. + }
  10563. +#endif
  10564. +
  10565. + gf_reg_key_kernel(gf_dev);
  10566. +
  10567. + gf_spi_setup(gf_dev, GF_SPI_HIGH_SPEED);
  10568. + gf_dev->irq = gf_irq_num(gf_dev);
  10569. + ret = request_threaded_irq(gf_dev->irq, NULL, gf_irq,
  10570. + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  10571. + "gf", gf_dev);
  10572. + if (!ret) {
  10573. + pr_info("%s called enable_irq_wake.\n", __func__);
  10574. + enable_irq_wake(gf_dev->irq);
  10575. +
  10576. + gf_dev->irq_enabled = 1;
  10577. + gf_disable_irq(gf_dev);
  10578. + }
  10579. + }
  10580. + gf_spi_write_word(gf_dev, GF_IRQ_CTRL2, 0xFFFF); /*0x0124, 0x0400 clean reset INT*/
  10581. +
  10582. + /*Get vendorID */
  10583. + gf_spi_read_word(gf_dev, GF_VENDOR_ID, &g_vendorID);
  10584. + pr_info("%s vendorID = 0x%04X\n", __func__, g_vendorID);
  10585. +
  10586. + gf_spi_read_word(gf_dev, GF_CHIP_ID_LO, &chip_id_1);
  10587. + gf_spi_read_word(gf_dev, GF_CHIP_ID_HI, &chip_id_2);
  10588. + g_chipID = ((chip_id_2<<16)|(chip_id_1)) >> 8;
  10589. + pr_info("%s: chip_id_hi = 0x%x, chip_id_low = 0x%x, g_chipID is 0x%08x \n", __func__, chip_id_2, chip_id_1, g_chipID);
  10590. +
  10591. + pr_info("succeed to probe.\n");
  10592. + gf_dev->device_available = 1;
  10593. + return status;
  10594. +
  10595. +error:
  10596. + gf_cleanup(gf_dev);
  10597. + gf_dev->device_available = 0;
  10598. + if (gf_dev->devt != 0) {
  10599. + pr_info("Err: status = %d\n", status);
  10600. + mutex_lock(&device_list_lock);
  10601. + list_del(&gf_dev->device_entry);
  10602. + device_destroy(gf_class, gf_dev->devt);
  10603. + clear_bit(MINOR(gf_dev->devt), minors);
  10604. + mutex_unlock(&device_list_lock);
  10605. +#ifdef USE_SPI_BUS
  10606. +gfspi_probe_clk_enable_failed:
  10607. + gfspi_ioctl_clk_uninit(gf_dev);
  10608. +gfspi_probe_clk_init_failed:
  10609. +#else
  10610. + if (gf_dev->iface_clk != NULL)
  10611. + clk_put(gf_dev->iface_clk);
  10612. +
  10613. + if (gf_dev->core_clk != NULL)
  10614. + clk_put(gf_dev->core_clk);
  10615. +
  10616. +#endif
  10617. + if (gf_dev->input != NULL)
  10618. + input_unregister_device(gf_dev->input);
  10619. +
  10620. +
  10621. + }
  10622. + if (gf_dev->gBuffer != NULL) {
  10623. + kfree(gf_dev->gBuffer);
  10624. + }
  10625. +
  10626. + FUNC_EXIT();
  10627. + return status;
  10628. +}
  10629. +
  10630. +/*static int __devexit gf_remove(struct spi_device *spi)*/
  10631. +#if defined(USE_SPI_BUS)
  10632. +static int gf_remove(struct spi_device *spi)
  10633. +#elif defined(USE_PLATFORM_BUS)
  10634. +static int gf_remove(struct platform_device *pdev)
  10635. +#endif
  10636. +{
  10637. + struct gf_dev *gf_dev = &gf;
  10638. + FUNC_ENTRY();
  10639. +
  10640. + wake_lock_destroy(&fp_wakelock);
  10641. + /* make sure ops on existing fds can abort cleanly */
  10642. + if (gf_dev->irq)
  10643. + free_irq(gf_dev->irq, gf_dev);
  10644. +
  10645. + if (gf_dev->input != NULL)
  10646. + input_unregister_device(gf_dev->input);
  10647. + input_free_device(gf_dev->input);
  10648. +
  10649. + /* prevent new opens */
  10650. + mutex_lock(&device_list_lock);
  10651. + list_del(&gf_dev->device_entry);
  10652. + device_destroy(gf_class, gf_dev->devt);
  10653. + clear_bit(MINOR(gf_dev->devt), minors);
  10654. +
  10655. + gf_cleanup(gf_dev);
  10656. + gf_dev->device_available = 0;
  10657. + fb_unregister_client(&gf_dev->notifier);
  10658. +
  10659. +#ifdef USE_SPI_BUS
  10660. + gfspi_ioctl_clk_uninit(gf_dev);
  10661. +#else
  10662. + if (gf_dev->iface_clk != NULL)
  10663. + clk_put(gf_dev->iface_clk);
  10664. +
  10665. + if (gf_dev->core_clk != NULL)
  10666. + clk_put(gf_dev->core_clk);
  10667. +
  10668. +#endif
  10669. +
  10670. +
  10671. + if (gf_dev->users == 0) {
  10672. + if (gf_dev->gBuffer)
  10673. + kfree(gf_dev->gBuffer);
  10674. + } else {
  10675. + pr_info("Not free_pages.\n");
  10676. + }
  10677. +
  10678. + mutex_unlock(&device_list_lock);
  10679. +
  10680. + FUNC_EXIT();
  10681. + return 0;
  10682. +}
  10683. +
  10684. +static struct of_device_id gx_match_table[] = {
  10685. + {.compatible = GF_SPIDEV_NAME,},
  10686. + {},
  10687. +};
  10688. +
  10689. +#if defined(USE_SPI_BUS)
  10690. +static struct spi_driver gf_driver = {
  10691. +#elif defined(USE_PLATFORM_BUS)
  10692. + static struct platform_driver gf_driver = {
  10693. +#endif
  10694. + .driver = {
  10695. + .name = GF_DEV_NAME,
  10696. + .owner = THIS_MODULE,
  10697. +#if defined(USE_SPI_BUS)
  10698. +#endif
  10699. + .of_match_table = gx_match_table,
  10700. + },
  10701. + .probe = gf_probe,
  10702. + .remove = gf_remove,
  10703. + };
  10704. +
  10705. +static int __init gf_init(void)
  10706. +{
  10707. + int status;
  10708. + FUNC_ENTRY();
  10709. +
  10710. + /* Claim our 256 reserved device numbers. Then register a class
  10711. + * that will key udev/mdev to add/remove /dev nodes. Last, register
  10712. + * the driver which manages those device numbers.
  10713. + */
  10714. +
  10715. + BUILD_BUG_ON(N_SPI_MINORS > 256);
  10716. + status = register_chrdev(SPIDEV_MAJOR, CHRD_DRIVER_NAME, &gf_fops);
  10717. + pr_info("SPIDEV_MAJOR = %d\n", SPIDEV_MAJOR);
  10718. + if (status < 0) {
  10719. + pr_warn("Failed to register char device!\n");
  10720. + FUNC_EXIT();
  10721. + return status;
  10722. + }
  10723. + gf_class = class_create(THIS_MODULE, CLASS_NAME);
  10724. + if (IS_ERR(gf_class)) {
  10725. + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name);
  10726. + pr_warn("Failed to create class.\n");
  10727. + FUNC_EXIT();
  10728. + return PTR_ERR(gf_class);
  10729. + }
  10730. +#if defined(USE_PLATFORM_BUS)
  10731. + status = platform_driver_register(&gf_driver);
  10732. +#elif defined(USE_SPI_BUS)
  10733. + status = spi_register_driver(&gf_driver);
  10734. +#endif
  10735. + if (status < 0) {
  10736. + class_destroy(gf_class);
  10737. + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name);
  10738. + pr_warn("Failed to register SPI driver.\n");
  10739. + }
  10740. +
  10741. + pr_info(" status = 0x%x\n", status);
  10742. + FUNC_EXIT();
  10743. + return 0;
  10744. +}
  10745. +
  10746. +module_init(gf_init);
  10747. +
  10748. +static void __exit gf_exit(void)
  10749. +{
  10750. + FUNC_ENTRY();
  10751. +#if defined(USE_PLATFORM_BUS)
  10752. + platform_driver_unregister(&gf_driver);
  10753. +#elif defined(USE_SPI_BUS)
  10754. + spi_unregister_driver(&gf_driver);
  10755. +#endif
  10756. + class_destroy(gf_class);
  10757. + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name);
  10758. + FUNC_EXIT();
  10759. +}
  10760. +
  10761. +module_exit(gf_exit);
  10762. +
  10763. +MODULE_DESCRIPTION("User mode SPI device interface");
  10764. +MODULE_LICENSE("GPL");
  10765. +MODULE_ALIAS("spi:gf-spi");
  10766. diff --git a/drivers/input/fingerprint/goodix/gf_spi.h b/drivers/input/fingerprint/goodix/gf_spi.h
  10767. new file mode 100644
  10768. index 0000000..2d96c88
  10769. --- /dev/null
  10770. +++ b/drivers/input/fingerprint/goodix/gf_spi.h
  10771. @@ -0,0 +1,102 @@
  10772. +#ifndef __GF_SPI_H
  10773. +#define __GF_SPI_H
  10774. +
  10775. +#include <linux/types.h>
  10776. +#include <linux/notifier.h>
  10777. +/**********************************************************/
  10778. +#define USE_SPI_BUS 1
  10779. +#define GF_FASYNC 1 /* If support fasync mechanism.*/
  10780. +
  10781. +/****************Chip Specific***********************/
  10782. +#define GF_W 0xF0
  10783. +#define GF_R 0xF1
  10784. +#define GF_WDATA_OFFSET (0x3)
  10785. +#define GF_RDATA_OFFSET (0x4)
  10786. +
  10787. +struct gf_configs {
  10788. + unsigned short addr;
  10789. + unsigned short value;
  10790. +};
  10791. +
  10792. +struct gf_mode_config {
  10793. + struct gf_configs *p_cfg;
  10794. + unsigned int cfg_len;
  10795. +};
  10796. +
  10797. +enum gf_spi_transfer_speed {
  10798. + GF_SPI_LOW_SPEED = 0,
  10799. + GF_SPI_HIGH_SPEED,
  10800. + GF_SPI_KEEP_SPEED,
  10801. +};
  10802. +
  10803. +#define GF_IOC_MAGIC 'g'
  10804. +#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 0)
  10805. +#define GF_IOC_RW _IOWR(GF_IOC_MAGIC, 1, struct gf_ioc_transfer)
  10806. +#define GF_IOC_CMD _IOW(GF_IOC_MAGIC, 2, unsigned char)
  10807. +#define GF_IOC_CONFIG _IOW(GF_IOC_MAGIC, 3, void*)
  10808. +#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 4)
  10809. +#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 5)
  10810. +#define GF_IOC_SENDKEY _IOW(GF_IOC_MAGIC, 6, struct gf_key)
  10811. +#define GF_IOC_SETSPEED _IOW(GF_IOC_MAGIC, 7, enum gf_spi_transfer_speed)
  10812. +#define GF_IOC_MAXNR 8
  10813. +
  10814. +struct gf_ioc_transfer {
  10815. + unsigned char cmd;
  10816. + unsigned char reserve;
  10817. + unsigned short addr;
  10818. + unsigned int len;
  10819. + unsigned char *buf;
  10820. +};
  10821. +
  10822. +struct gf_key {
  10823. + unsigned int key;
  10824. + int value;
  10825. +};
  10826. +
  10827. +struct gf_key_map {
  10828. + char *name;
  10829. + unsigned short val;
  10830. +};
  10831. +
  10832. +struct gf_dev {
  10833. + dev_t devt;
  10834. + spinlock_t spi_lock;
  10835. + struct list_head device_entry;
  10836. +#if defined(USE_SPI_BUS)
  10837. + struct spi_device *spi;
  10838. +#elif defined(USE_PLATFORM_BUS)
  10839. + struct platform_device *spi;
  10840. +#endif
  10841. + struct clk *core_clk;
  10842. + struct clk *iface_clk;
  10843. +
  10844. + struct input_dev *input;
  10845. + /* buffer is NULL unless this device is open (users > 0) */
  10846. + unsigned users;
  10847. + signed irq_gpio;
  10848. + signed reset_gpio;
  10849. + signed pwr_gpio;
  10850. + int irq;
  10851. + int irq_enabled;
  10852. + int clk_enabled;
  10853. +#ifdef GF_FASYNC
  10854. + struct fasync_struct *async;
  10855. +#endif
  10856. + struct notifier_block notifier;
  10857. + char device_available;
  10858. + char fb_black;
  10859. + unsigned char *gBuffer;
  10860. + struct mutex buf_lock;
  10861. + struct mutex frame_lock;
  10862. +};
  10863. +
  10864. +int gf_parse_dts(struct gf_dev *gf_dev);
  10865. +void gf_cleanup(struct gf_dev *gf_dev);
  10866. +
  10867. +int gf_power_on(struct gf_dev *gf_dev);
  10868. +int gf_power_off(struct gf_dev *gf_dev);
  10869. +
  10870. +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms);
  10871. +int gf_irq_num(struct gf_dev *gf_dev);
  10872. +
  10873. +#endif /*__GF_SPI_H*/
  10874. diff --git a/drivers/input/fingerprint/goodix/platform.c b/drivers/input/fingerprint/goodix/platform.c
  10875. new file mode 100644
  10876. index 0000000..0d1b03e
  10877. --- /dev/null
  10878. +++ b/drivers/input/fingerprint/goodix/platform.c
  10879. @@ -0,0 +1,134 @@
  10880. +#include <linux/delay.h>
  10881. +#include <linux/workqueue.h>
  10882. +#include <linux/of_gpio.h>
  10883. +#include <linux/gpio.h>
  10884. +#include <linux/regulator/consumer.h>
  10885. +#include <linux/timer.h>
  10886. +#include <linux/err.h>
  10887. +
  10888. +#include "gf_spi.h"
  10889. +
  10890. +#if defined(USE_SPI_BUS)
  10891. +#include <linux/spi/spi.h>
  10892. +#include <linux/spi/spidev.h>
  10893. +#elif defined(USE_PLATFORM_BUS)
  10894. +#include <linux/platform_device.h>
  10895. +#endif
  10896. +
  10897. +/*GPIO pins reference.*/
  10898. +int gf_parse_dts(struct gf_dev *gf_dev)
  10899. +{
  10900. + int rc = 0;
  10901. + /*get pwr resource*/
  10902. + gf_dev->pwr_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node, "goodix, gpio_pwr", 0);
  10903. + if (!gpio_is_valid(gf_dev->pwr_gpio)) {
  10904. + pr_info("PWR GPIO is invalid.\n");
  10905. + return -EPERM;
  10906. + }
  10907. + rc = gpio_request(gf_dev->pwr_gpio, "goodix_pwr");
  10908. + if (rc) {
  10909. + dev_err(&gf_dev->spi->dev, "Failed to request PWR GPIO. rc = %d\n", rc);
  10910. + return -EPERM;
  10911. + }
  10912. +
  10913. + /*get reset resource*/
  10914. + gf_dev->reset_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node, "goodix, gpio_reset", 0);
  10915. + if (!gpio_is_valid(gf_dev->reset_gpio)) {
  10916. + pr_info("RESET GPIO is invalid.\n");
  10917. + return -EPERM;
  10918. + }
  10919. + rc = gpio_request(gf_dev->reset_gpio, "goodix_reset");
  10920. + if (rc) {
  10921. + dev_err(&gf_dev->spi->dev, "Failed to request RESET GPIO. rc = %d\n", rc);
  10922. + return -EPERM;
  10923. + }
  10924. + gpio_direction_output(gf_dev->reset_gpio, 1);
  10925. +
  10926. + /*get irq resourece*/
  10927. + gf_dev->irq_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node, "goodix, gpio_irq", 0);
  10928. + pr_info("gf:irq_gpio:%d\n", gf_dev->irq_gpio);
  10929. + if (!gpio_is_valid(gf_dev->irq_gpio)) {
  10930. + pr_info("IRQ GPIO is invalid.\n");
  10931. + return -EPERM;
  10932. + }
  10933. +
  10934. + rc = gpio_request(gf_dev->irq_gpio, "goodix_irq");
  10935. + if (rc) {
  10936. + dev_err(&gf_dev->spi->dev, "Failed to request IRQ GPIO. rc = %d\n", rc);
  10937. + return -EPERM;
  10938. + }
  10939. + gpio_direction_input(gf_dev->irq_gpio);
  10940. +
  10941. + //power on
  10942. + gpio_direction_output(gf_dev->pwr_gpio, 1);
  10943. +
  10944. + return 0;
  10945. +}
  10946. +
  10947. +void gf_cleanup(struct gf_dev *gf_dev)
  10948. +{
  10949. + pr_info("[info] %s\n", __func__);
  10950. + if (gpio_is_valid(gf_dev->irq_gpio)) {
  10951. + gpio_free(gf_dev->irq_gpio);
  10952. + pr_info("remove irq_gpio success\n");
  10953. + }
  10954. + if (gpio_is_valid(gf_dev->reset_gpio)) {
  10955. + gpio_free(gf_dev->reset_gpio);
  10956. + pr_info("remove reset_gpio success\n");
  10957. + }
  10958. + if (gpio_is_valid(gf_dev->pwr_gpio)) {
  10959. + gpio_free(gf_dev->pwr_gpio);
  10960. + pr_info("remove pwr_gpio success\n");
  10961. + }
  10962. +}
  10963. +
  10964. +/*power management*/
  10965. +int gf_power_on(struct gf_dev *gf_dev)
  10966. +{
  10967. + int rc = 0;
  10968. + if (gpio_is_valid(gf_dev->pwr_gpio)) {
  10969. + gpio_set_value(gf_dev->pwr_gpio, 1);
  10970. + }
  10971. + msleep(10);
  10972. + pr_info("---- power on ok ----\n");
  10973. +
  10974. + return rc;
  10975. +}
  10976. +
  10977. +int gf_power_off(struct gf_dev* gf_dev)
  10978. +{
  10979. + int rc = 0;
  10980. + if (gpio_is_valid(gf_dev->pwr_gpio)) {
  10981. + gpio_set_value(gf_dev->pwr_gpio, 1);
  10982. + }
  10983. + pr_info("---- power off ----\n");
  10984. + return rc;
  10985. +}
  10986. +
  10987. +/********************************************************************
  10988. + *CPU output low level in RST pin to reset GF. This is the MUST action for GF.
  10989. + *Take care of this function. IO Pin driver strength / glitch and so on.
  10990. + ********************************************************************/
  10991. +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms)
  10992. +{
  10993. + if (gf_dev == NULL) {
  10994. + pr_info("Input buff is NULL.\n");
  10995. + return -EPERM;
  10996. + }
  10997. + gpio_direction_output(gf_dev->reset_gpio, 1);
  10998. + gpio_set_value(gf_dev->reset_gpio, 0);
  10999. + mdelay(delay_ms > 3 ? delay_ms : 3);
  11000. + gpio_set_value(gf_dev->reset_gpio, 1);
  11001. + return 0;
  11002. +}
  11003. +
  11004. +int gf_irq_num(struct gf_dev *gf_dev)
  11005. +{
  11006. + if (gf_dev == NULL) {
  11007. + pr_info("Input buff is NULL.\n");
  11008. + return -EPERM;
  11009. + } else {
  11010. + return gpio_to_irq(gf_dev->irq_gpio);
  11011. + }
  11012. +}
  11013. +
  11014. diff --git a/drivers/input/fingerprint/goodix_ta/Kconfig b/drivers/input/fingerprint/goodix_ta/Kconfig
  11015. new file mode 100644
  11016. index 0000000..34b1554
  11017. --- /dev/null
  11018. +++ b/drivers/input/fingerprint/goodix_ta/Kconfig
  11019. @@ -0,0 +1,10 @@
  11020. +config FINGERPRINT_GOODIX_TA
  11021. + tristate "Finger print card goodix"
  11022. + depends on INPUT_FINGERPRINT
  11023. + help
  11024. + Say Y here to enable support for retrieving self-test reports.
  11025. +
  11026. + If unsure, say N.
  11027. +
  11028. + To compile this driver as a module, choose M here.
  11029. +
  11030. diff --git a/drivers/input/fingerprint/goodix_ta/Makefile b/drivers/input/fingerprint/goodix_ta/Makefile
  11031. new file mode 100644
  11032. index 0000000..43929c1
  11033. --- /dev/null
  11034. +++ b/drivers/input/fingerprint/goodix_ta/Makefile
  11035. @@ -0,0 +1 @@
  11036. +obj-$(CONFIG_FINGERPRINT_GOODIX_TA) += gf_spi.o platform.o netlink.o
  11037. diff --git a/drivers/input/fingerprint/goodix_ta/gf_spi.c b/drivers/input/fingerprint/goodix_ta/gf_spi.c
  11038. new file mode 100644
  11039. index 0000000..1e76d3e
  11040. --- /dev/null
  11041. +++ b/drivers/input/fingerprint/goodix_ta/gf_spi.c
  11042. @@ -0,0 +1,906 @@
  11043. +/*
  11044. + * TEE driver for goodix fingerprint sensor
  11045. + * Copyright (C) 2016 Goodix
  11046. + * Copyright (C) 2017 XiaoMi, Inc.
  11047. + *
  11048. + * This program is free software; you can redistribute it and/or modify
  11049. + * it under the terms of the GNU General Public License as published by
  11050. + * the Free Software Foundation; either version 2 of the License, or
  11051. + * (at your option) any later version.
  11052. + *
  11053. + * This program is distributed in the hope that it will be useful,
  11054. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11055. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11056. + * GNU General Public License for more details.
  11057. + */
  11058. +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11059. +
  11060. +#include <linux/init.h>
  11061. +#include <linux/module.h>
  11062. +#include <linux/ioctl.h>
  11063. +#include <linux/fs.h>
  11064. +#include <linux/device.h>
  11065. +#include <linux/input.h>
  11066. +#include <linux/clk.h>
  11067. +#include <linux/err.h>
  11068. +#include <linux/list.h>
  11069. +#include <linux/errno.h>
  11070. +#include <linux/mutex.h>
  11071. +#include <linux/slab.h>
  11072. +#include <linux/compat.h>
  11073. +#include <linux/delay.h>
  11074. +#include <asm/uaccess.h>
  11075. +#include <linux/ktime.h>
  11076. +#include <linux/interrupt.h>
  11077. +#include <linux/irq.h>
  11078. +#include <linux/gpio.h>
  11079. +#include <linux/regulator/consumer.h>
  11080. +#include <linux/of_gpio.h>
  11081. +#include <linux/timer.h>
  11082. +#include <linux/notifier.h>
  11083. +#include <linux/fb.h>
  11084. +#include <linux/pm_qos.h>
  11085. +#include <linux/cpufreq.h>
  11086. +#include <linux/wakelock.h>
  11087. +
  11088. +#include "gf_spi.h"
  11089. +
  11090. +#if defined(USE_SPI_BUS)
  11091. +#include <linux/spi/spi.h>
  11092. +#include <linux/spi/spidev.h>
  11093. +#elif defined(USE_PLATFORM_BUS)
  11094. +#include <linux/platform_device.h>
  11095. +#endif
  11096. +
  11097. +#define VER_MAJOR 1
  11098. +#define VER_MINOR 2
  11099. +#define PATCH_LEVEL 1
  11100. +
  11101. +#define GF_SPIDEV_NAME "goodix,fingerprint"
  11102. +/*device name after register in charater*/
  11103. +#define GF_DEV_NAME "goodix_fp"
  11104. +#define GF_INPUT_NAME "uinput-goodix" /*"goodix_fp" */
  11105. +
  11106. +#define CHRD_DRIVER_NAME "goodix_fp_spi"
  11107. +#define CLASS_NAME "goodix_fp"
  11108. +
  11109. +#define N_SPI_MINORS 32 /* ... up to 256 */
  11110. +static int SPIDEV_MAJOR;
  11111. +
  11112. +static DECLARE_BITMAP(minors, N_SPI_MINORS);
  11113. +static LIST_HEAD(device_list);
  11114. +static DEFINE_MUTEX(device_list_lock);
  11115. +static struct wake_lock fp_wakelock;
  11116. +static struct gf_dev gf;
  11117. +
  11118. +struct gf_key_map maps[] = {
  11119. + { EV_KEY, GF_KEY_INPUT_HOME },
  11120. + { EV_KEY, GF_KEY_INPUT_MENU },
  11121. + { EV_KEY, GF_KEY_INPUT_BACK },
  11122. + { EV_KEY, GF_KEY_INPUT_POWER },
  11123. +#if defined(SUPPORT_NAV_EVENT)
  11124. + { EV_KEY, GF_NAV_INPUT_UP },
  11125. + { EV_KEY, GF_NAV_INPUT_DOWN },
  11126. + { EV_KEY, GF_NAV_INPUT_RIGHT },
  11127. + { EV_KEY, GF_NAV_INPUT_LEFT },
  11128. + { EV_KEY, GF_KEY_INPUT_CAMERA },
  11129. + { EV_KEY, GF_NAV_INPUT_CLICK },
  11130. + { EV_KEY, GF_NAV_INPUT_DOUBLE_CLICK },
  11131. + { EV_KEY, GF_NAV_INPUT_LONG_PRESS },
  11132. + { EV_KEY, GF_NAV_INPUT_HEAVY },
  11133. +#endif
  11134. +};
  11135. +
  11136. +static void gf_enable_irq(struct gf_dev *gf_dev)
  11137. +{
  11138. + if (gf_dev->irq_enabled) {
  11139. + pr_warn("IRQ has been enabled.\n");
  11140. + } else {
  11141. + enable_irq(gf_dev->irq);
  11142. + gf_dev->irq_enabled = 1;
  11143. + }
  11144. +}
  11145. +
  11146. +static void gf_disable_irq(struct gf_dev *gf_dev)
  11147. +{
  11148. + if (gf_dev->irq_enabled) {
  11149. + gf_dev->irq_enabled = 0;
  11150. + disable_irq(gf_dev->irq);
  11151. + } else {
  11152. + pr_warn("IRQ has been disabled.\n");
  11153. + }
  11154. +}
  11155. +
  11156. +#ifdef AP_CONTROL_CLK
  11157. +static long spi_clk_max_rate(struct clk *clk, unsigned long rate)
  11158. +{
  11159. + long lowest_available, nearest_low, step_size, cur;
  11160. + long step_direction = -1;
  11161. + long guess = rate;
  11162. + int max_steps = 10;
  11163. +
  11164. + cur = clk_round_rate(clk, rate);
  11165. + if (cur == rate)
  11166. + return rate;
  11167. +
  11168. + /* if we got here then: cur > rate */
  11169. + lowest_available = clk_round_rate(clk, 0);
  11170. + if (lowest_available > rate)
  11171. + return -EINVAL;
  11172. +
  11173. + step_size = (rate - lowest_available) >> 1;
  11174. + nearest_low = lowest_available;
  11175. +
  11176. + while (max_steps-- && step_size) {
  11177. + guess += step_size * step_direction;
  11178. + cur = clk_round_rate(clk, guess);
  11179. +
  11180. + if ((cur < rate) && (cur > nearest_low))
  11181. + nearest_low = cur;
  11182. + /*
  11183. + * if we stepped too far, then start stepping in the other
  11184. + * direction with half the step size
  11185. + */
  11186. + if (((cur > rate) && (step_direction > 0))
  11187. + || ((cur < rate) && (step_direction < 0))) {
  11188. + step_direction = -step_direction;
  11189. + step_size >>= 1;
  11190. + }
  11191. + }
  11192. + return nearest_low;
  11193. +}
  11194. +
  11195. +static void spi_clock_set(struct gf_dev *gf_dev, int speed)
  11196. +{
  11197. + long rate;
  11198. + int rc;
  11199. +
  11200. + rate = spi_clk_max_rate(gf_dev->core_clk, speed);
  11201. + if (rate < 0) {
  11202. + pr_debug("%s: no match found for requested clock frequency:%d",
  11203. + __func__, speed);
  11204. + return;
  11205. + }
  11206. +
  11207. + rc = clk_set_rate(gf_dev->core_clk, rate);
  11208. +}
  11209. +
  11210. +static int gfspi_ioctl_clk_init(struct gf_dev *data)
  11211. +{
  11212. + pr_debug("%s: enter\n", __func__);
  11213. +
  11214. + data->clk_enabled = 0;
  11215. + data->core_clk = clk_get(&data->spi->dev, "core_clk");
  11216. + if (IS_ERR_OR_NULL(data->core_clk)) {
  11217. + pr_err("%s: fail to get core_clk\n", __func__);
  11218. + return -EPERM;
  11219. + }
  11220. + data->iface_clk = clk_get(&data->spi->dev, "iface_clk");
  11221. + if (IS_ERR_OR_NULL(data->iface_clk)) {
  11222. + pr_err("%s: fail to get iface_clk\n", __func__);
  11223. + clk_put(data->core_clk);
  11224. + data->core_clk = NULL;
  11225. + return -ENOENT;
  11226. + }
  11227. + return 0;
  11228. +}
  11229. +
  11230. +static int gfspi_ioctl_clk_enable(struct gf_dev *data)
  11231. +{
  11232. + int err;
  11233. +
  11234. + pr_debug("%s: enter\n", __func__);
  11235. +
  11236. + if (data->clk_enabled)
  11237. + return 0;
  11238. +
  11239. + err = clk_prepare_enable(data->core_clk);
  11240. + if (err) {
  11241. + pr_err("%s: fail to enable core_clk\n", __func__);
  11242. + return -EPERM;
  11243. + }
  11244. +
  11245. + err = clk_prepare_enable(data->iface_clk);
  11246. + if (err) {
  11247. + pr_err("%s: fail to enable iface_clk\n", __func__);
  11248. + clk_disable_unprepare(data->core_clk);
  11249. + return -ENOENT;
  11250. + }
  11251. +
  11252. + data->clk_enabled = 1;
  11253. +
  11254. + return 0;
  11255. +}
  11256. +
  11257. +static int gfspi_ioctl_clk_disable(struct gf_dev *data)
  11258. +{
  11259. + pr_debug("%s: enter\n", __func__);
  11260. +
  11261. + if (!data->clk_enabled)
  11262. + return 0;
  11263. +
  11264. + clk_disable_unprepare(data->core_clk);
  11265. + clk_disable_unprepare(data->iface_clk);
  11266. + data->clk_enabled = 0;
  11267. +
  11268. + return 0;
  11269. +}
  11270. +
  11271. +static int gfspi_ioctl_clk_uninit(struct gf_dev *data)
  11272. +{
  11273. + pr_debug("%s: enter\n", __func__);
  11274. +
  11275. + if (data->clk_enabled)
  11276. + gfspi_ioctl_clk_disable(data);
  11277. +
  11278. + if (!IS_ERR_OR_NULL(data->core_clk)) {
  11279. + clk_put(data->core_clk);
  11280. + data->core_clk = NULL;
  11281. + }
  11282. +
  11283. + if (!IS_ERR_OR_NULL(data->iface_clk)) {
  11284. + clk_put(data->iface_clk);
  11285. + data->iface_clk = NULL;
  11286. + }
  11287. +
  11288. + return 0;
  11289. +}
  11290. +#endif
  11291. +
  11292. +static void nav_event_input(struct gf_dev *gf_dev, gf_nav_event_t nav_event)
  11293. +{
  11294. + uint32_t nav_input = 0;
  11295. +
  11296. + switch (nav_event) {
  11297. + case GF_NAV_FINGER_DOWN:
  11298. + pr_debug("%s nav finger down\n", __func__);
  11299. + break;
  11300. +
  11301. + case GF_NAV_FINGER_UP:
  11302. + pr_debug("%s nav finger up\n", __func__);
  11303. + break;
  11304. +
  11305. + case GF_NAV_DOWN:
  11306. + nav_input = GF_NAV_INPUT_DOWN;
  11307. + pr_debug("%s nav down\n", __func__);
  11308. + break;
  11309. +
  11310. + case GF_NAV_UP:
  11311. + nav_input = GF_NAV_INPUT_UP;
  11312. + pr_debug("%s nav up\n", __func__);
  11313. + break;
  11314. +
  11315. + case GF_NAV_LEFT:
  11316. + nav_input = GF_NAV_INPUT_LEFT;
  11317. + pr_debug("%s nav left\n", __func__);
  11318. + break;
  11319. +
  11320. + case GF_NAV_RIGHT:
  11321. + nav_input = GF_NAV_INPUT_RIGHT;
  11322. + pr_debug("%s nav right\n", __func__);
  11323. + break;
  11324. +
  11325. + case GF_NAV_CLICK:
  11326. + nav_input = GF_NAV_INPUT_CLICK;
  11327. + pr_debug("%s nav click\n", __func__);
  11328. + break;
  11329. +
  11330. + case GF_NAV_HEAVY:
  11331. + nav_input = GF_NAV_INPUT_HEAVY;
  11332. + pr_debug("%s nav heavy\n", __func__);
  11333. + break;
  11334. +
  11335. + case GF_NAV_LONG_PRESS:
  11336. + nav_input = GF_NAV_INPUT_LONG_PRESS;
  11337. + pr_debug("%s nav long press\n", __func__);
  11338. + break;
  11339. +
  11340. + case GF_NAV_DOUBLE_CLICK:
  11341. + nav_input = GF_NAV_INPUT_DOUBLE_CLICK;
  11342. + pr_debug("%s nav double click\n", __func__);
  11343. + break;
  11344. +
  11345. + default:
  11346. + pr_warn("%s unknown nav event: %d\n", __func__, nav_event);
  11347. + break;
  11348. + }
  11349. +
  11350. + if ((nav_event != GF_NAV_FINGER_DOWN) && (nav_event != GF_NAV_FINGER_UP)) {
  11351. + input_report_key(gf_dev->input, nav_input, 1);
  11352. + input_sync(gf_dev->input);
  11353. + input_report_key(gf_dev->input, nav_input, 0);
  11354. + input_sync(gf_dev->input);
  11355. + }
  11356. +}
  11357. +
  11358. +
  11359. +static void gf_kernel_key_input(struct gf_dev *gf_dev, struct gf_key *gf_key)
  11360. +{
  11361. + uint32_t key_input = 0;
  11362. +
  11363. + if (GF_KEY_HOME == gf_key->key) {
  11364. + key_input = GF_KEY_INPUT_HOME;
  11365. + } else if (GF_KEY_POWER == gf_key->key) {
  11366. + key_input = GF_KEY_INPUT_POWER;
  11367. + } else if (GF_KEY_CAMERA == gf_key->key) {
  11368. + key_input = GF_KEY_INPUT_CAMERA;
  11369. + } else {
  11370. + /* add special key define */
  11371. + key_input = gf_key->key;
  11372. + }
  11373. + pr_debug("%s: received key event[%d], key=%d, value=%d\n",
  11374. + __func__, key_input, gf_key->key, gf_key->value);
  11375. +
  11376. + if ((GF_KEY_POWER == gf_key->key || GF_KEY_CAMERA == gf_key->key)
  11377. + && (gf_key->value == 1)) {
  11378. + input_report_key(gf_dev->input, key_input, 1);
  11379. + input_sync(gf_dev->input);
  11380. + input_report_key(gf_dev->input, key_input, 0);
  11381. + input_sync(gf_dev->input);
  11382. + }
  11383. +
  11384. + if (GF_KEY_HOME == gf_key->key) {
  11385. + input_report_key(gf_dev->input, key_input, gf_key->value);
  11386. + input_sync(gf_dev->input);
  11387. + }
  11388. +}
  11389. +
  11390. +static long gf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  11391. +{
  11392. + struct gf_dev *gf_dev = &gf;
  11393. + struct gf_key gf_key;
  11394. +#if defined(SUPPORT_NAV_EVENT)
  11395. + gf_nav_event_t nav_event = GF_NAV_NONE;
  11396. +#endif
  11397. + int retval = 0;
  11398. + u8 netlink_route = NETLINK_TEST;
  11399. + struct gf_ioc_chip_info info;
  11400. +
  11401. + if (_IOC_TYPE(cmd) != GF_IOC_MAGIC)
  11402. + return -ENODEV;
  11403. +
  11404. + if (_IOC_DIR(cmd) & _IOC_READ)
  11405. + retval = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
  11406. + else if (_IOC_DIR(cmd) & _IOC_WRITE)
  11407. + retval = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
  11408. + if (retval)
  11409. + return -EFAULT;
  11410. +
  11411. + if (gf_dev->device_available == 0) {
  11412. + if ((cmd == GF_IOC_ENABLE_POWER) || (cmd == GF_IOC_DISABLE_POWER)) {
  11413. + pr_debug("power cmd\n");
  11414. + } else {
  11415. + pr_debug("Sensor is power off currently.\n");
  11416. + return -ENODEV;
  11417. + }
  11418. + }
  11419. +
  11420. + switch (cmd) {
  11421. + case GF_IOC_INIT:
  11422. + pr_debug("%s GF_IOC_INIT\n", __func__);
  11423. + if (copy_to_user((void __user *)arg, (void *)&netlink_route, sizeof(u8))) {
  11424. + retval = -EFAULT;
  11425. + break;
  11426. + }
  11427. + break;
  11428. + case GF_IOC_EXIT:
  11429. + pr_debug("%s GF_IOC_EXIT\n", __func__);
  11430. + break;
  11431. + case GF_IOC_DISABLE_IRQ:
  11432. + pr_debug("%s GF_IOC_DISABEL_IRQ\n", __func__);
  11433. + gf_disable_irq(gf_dev);
  11434. + break;
  11435. + case GF_IOC_ENABLE_IRQ:
  11436. + pr_debug("%s GF_IOC_ENABLE_IRQ\n", __func__);
  11437. + gf_enable_irq(gf_dev);
  11438. + break;
  11439. + case GF_IOC_RESET:
  11440. + pr_debug("%s GF_IOC_RESET.\n", __func__);
  11441. + gf_hw_reset(gf_dev, 3);
  11442. + break;
  11443. + case GF_IOC_INPUT_KEY_EVENT:
  11444. + if (copy_from_user(&gf_key, (struct gf_key *)arg, sizeof(struct gf_key))) {
  11445. + pr_debug("Failed to copy input key event from user to kernel\n");
  11446. + retval = -EFAULT;
  11447. + break;
  11448. + }
  11449. +
  11450. + gf_kernel_key_input(gf_dev, &gf_key);
  11451. + break;
  11452. +#if defined(SUPPORT_NAV_EVENT)
  11453. + case GF_IOC_NAV_EVENT:
  11454. + pr_debug("%s GF_IOC_NAV_EVENT\n", __func__);
  11455. + if (copy_from_user(&nav_event, (gf_nav_event_t *)arg, sizeof(gf_nav_event_t))) {
  11456. + pr_debug("Failed to copy nav event from user to kernel\n");
  11457. + retval = -EFAULT;
  11458. + break;
  11459. + }
  11460. +
  11461. + nav_event_input(gf_dev, nav_event);
  11462. + break;
  11463. +#endif
  11464. +
  11465. + case GF_IOC_ENABLE_SPI_CLK:
  11466. + pr_debug("%s GF_IOC_ENABLE_SPI_CLK\n", __func__);
  11467. +#ifdef AP_CONTROL_CLK
  11468. + gfspi_ioctl_clk_enable(gf_dev);
  11469. +#else
  11470. + pr_debug("Doesn't support control clock.\n");
  11471. +#endif
  11472. + break;
  11473. + case GF_IOC_DISABLE_SPI_CLK:
  11474. + pr_debug("%s GF_IOC_DISABLE_SPI_CLK\n", __func__);
  11475. +#ifdef AP_CONTROL_CLK
  11476. + gfspi_ioctl_clk_disable(gf_dev);
  11477. +#else
  11478. + pr_debug("Doesn't support control clock\n");
  11479. +#endif
  11480. + break;
  11481. + case GF_IOC_ENABLE_POWER:
  11482. + pr_debug("%s GF_IOC_ENABLE_POWER\n", __func__);
  11483. + if (gf_dev->device_available == 1)
  11484. + pr_debug("Sensor has already powered-on.\n");
  11485. + else
  11486. + gf_power_on(gf_dev);
  11487. + gf_dev->device_available = 1;
  11488. + break;
  11489. + case GF_IOC_DISABLE_POWER:
  11490. + pr_debug("%s GF_IOC_DISABLE_POWER\n", __func__);
  11491. + if (gf_dev->device_available == 0)
  11492. + pr_debug("Sensor has already powered-off.\n");
  11493. + else
  11494. + gf_power_off(gf_dev);
  11495. + gf_dev->device_available = 0;
  11496. + break;
  11497. + case GF_IOC_ENTER_SLEEP_MODE:
  11498. + pr_debug("%s GF_IOC_ENTER_SLEEP_MODE\n", __func__);
  11499. + break;
  11500. + case GF_IOC_GET_FW_INFO:
  11501. + pr_debug("%s GF_IOC_GET_FW_INFO\n", __func__);
  11502. + break;
  11503. + case GF_IOC_REMOVE:
  11504. + pr_debug("%s GF_IOC_REMOVE\n", __func__);
  11505. + break;
  11506. + case GF_IOC_CHIP_INFO:
  11507. + pr_debug("%s GF_IOC_CHIP_INFO\n", __func__);
  11508. + if (copy_from_user(&info, (struct gf_ioc_chip_info *)arg, sizeof(struct gf_ioc_chip_info))) {
  11509. + retval = -EFAULT;
  11510. + break;
  11511. + }
  11512. + pr_debug("vendor_id : 0x%x\n", info.vendor_id);
  11513. + pr_debug("mode : 0x%x\n", info.mode);
  11514. + pr_debug("operation: 0x%x\n", info.operation);
  11515. + break;
  11516. + default:
  11517. + pr_warn("unsupport cmd:0x%x\n", cmd);
  11518. + break;
  11519. + }
  11520. +
  11521. + return retval;
  11522. +}
  11523. +
  11524. +#ifdef CONFIG_COMPAT
  11525. +static long gf_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  11526. +{
  11527. + return gf_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
  11528. +}
  11529. +#endif /*CONFIG_COMPAT*/
  11530. +
  11531. +static irqreturn_t gf_irq(int irq, void *handle)
  11532. +{
  11533. +#if defined(GF_NETLINK_ENABLE)
  11534. + char temp[4] = { 0x0 };
  11535. + temp[0] = GF_NET_EVENT_IRQ;
  11536. + wake_lock_timeout(&fp_wakelock, msecs_to_jiffies(2*1000));
  11537. + sendnlmsg(temp);
  11538. +#elif defined (GF_FASYNC)
  11539. + struct gf_dev *gf_dev = &gf;
  11540. +
  11541. + if (gf_dev->async)
  11542. + kill_fasync(&gf_dev->async, SIGIO, POLL_IN);
  11543. +#endif
  11544. +
  11545. + return IRQ_HANDLED;
  11546. +}
  11547. +
  11548. +static int gf_open(struct inode *inode, struct file *filp)
  11549. +{
  11550. + struct gf_dev *gf_dev;
  11551. + int status = -ENXIO;
  11552. + int rc = 0;
  11553. +
  11554. + mutex_lock(&device_list_lock);
  11555. +
  11556. + list_for_each_entry(gf_dev, &device_list, device_entry) {
  11557. + if (gf_dev->devt == inode->i_rdev) {
  11558. + pr_debug("Found\n");
  11559. + status = 0;
  11560. + break;
  11561. + }
  11562. + }
  11563. +
  11564. + if (status == 0) {
  11565. + if (status == 0) {
  11566. + rc = gpio_request(gf_dev->reset_gpio, "goodix_reset");
  11567. + if (rc) {
  11568. + dev_err(&gf_dev->spi->dev, "Failed to request RESET GPIO. rc = %d\n", rc);
  11569. + mutex_unlock(&device_list_lock);
  11570. + return -EPERM;
  11571. + }
  11572. +
  11573. + gpio_direction_output(gf_dev->reset_gpio, 1);
  11574. +
  11575. + rc = gpio_request(gf_dev->irq_gpio, "goodix_irq");
  11576. + if (rc) {
  11577. + dev_err(&gf_dev->spi->dev, "Failed to request IRQ GPIO. rc = %d\n", rc);
  11578. + mutex_unlock(&device_list_lock);
  11579. + return -EPERM;
  11580. + }
  11581. + gpio_direction_input(gf_dev->irq_gpio);
  11582. +
  11583. + rc = request_threaded_irq(gf_dev->irq, NULL, gf_irq,
  11584. + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  11585. + "gf", gf_dev);
  11586. +
  11587. + if (!rc) {
  11588. + enable_irq_wake(gf_dev->irq);
  11589. + gf_dev->irq_enabled = 1;
  11590. + gf_disable_irq(gf_dev);
  11591. + }
  11592. +
  11593. + gf_dev->users++;
  11594. + filp->private_data = gf_dev;
  11595. + nonseekable_open(inode, filp);
  11596. + pr_debug("Succeed to open device. irq = %d\n",
  11597. + gf_dev->irq);
  11598. + if (gf_dev->users == 1)
  11599. + gf_enable_irq(gf_dev);
  11600. + gf_hw_reset(gf_dev, 3);
  11601. + gf_dev->device_available = 1;
  11602. + }
  11603. + } else {
  11604. + pr_debug("No device for minor %d\n", iminor(inode));
  11605. + }
  11606. + mutex_unlock(&device_list_lock);
  11607. + return status;
  11608. +}
  11609. +
  11610. +#ifdef GF_FASYNC
  11611. +static int gf_fasync(int fd, struct file *filp, int mode)
  11612. +{
  11613. + struct gf_dev *gf_dev = filp->private_data;
  11614. + int ret;
  11615. +
  11616. + ret = fasync_helper(fd, filp, mode, &gf_dev->async);
  11617. + pr_debug("ret = %d\n", ret);
  11618. + return ret;
  11619. +}
  11620. +#endif
  11621. +
  11622. +static int gf_release(struct inode *inode, struct file *filp)
  11623. +{
  11624. + struct gf_dev *gf_dev;
  11625. + int status = 0;
  11626. +
  11627. + mutex_lock(&device_list_lock);
  11628. + gf_dev = filp->private_data;
  11629. + filp->private_data = NULL;
  11630. +
  11631. + /*last close?? */
  11632. + gf_dev->users--;
  11633. + if (!gf_dev->users) {
  11634. + pr_debug("disble_irq. irq = %d\n", gf_dev->irq);
  11635. + gf_disable_irq(gf_dev);
  11636. + /*power off the sensor*/
  11637. + gf_dev->device_available = 0;
  11638. + free_irq(gf_dev->irq, gf_dev);
  11639. + gpio_free(gf_dev->irq_gpio);
  11640. + gpio_free(gf_dev->reset_gpio);
  11641. + gf_power_off(gf_dev);
  11642. + }
  11643. + mutex_unlock(&device_list_lock);
  11644. + return status;
  11645. +}
  11646. +
  11647. +static const struct file_operations gf_fops = {
  11648. + .owner = THIS_MODULE,
  11649. + /* REVISIT switch to aio primitives, so that userspace
  11650. + * gets more complete API coverage. It'll simplify things
  11651. + * too, except for the locking.
  11652. + */
  11653. + .unlocked_ioctl = gf_ioctl,
  11654. +#ifdef CONFIG_COMPAT
  11655. + .compat_ioctl = gf_compat_ioctl,
  11656. +#endif /*CONFIG_COMPAT*/
  11657. + .open = gf_open,
  11658. + .release = gf_release,
  11659. +#ifdef GF_FASYNC
  11660. + .fasync = gf_fasync,
  11661. +#endif
  11662. +};
  11663. +
  11664. +static int goodix_fb_state_chg_callback(struct notifier_block *nb,
  11665. + unsigned long val, void *data)
  11666. +{
  11667. + struct gf_dev *gf_dev;
  11668. + struct fb_event *evdata = data;
  11669. + unsigned int blank;
  11670. + char temp[4] = { 0x0 };
  11671. +
  11672. + if (val != FB_EVENT_BLANK)
  11673. + return 0;
  11674. + pr_debug("[info] %s go to the goodix_fb_state_chg_callback value = %d\n",
  11675. + __func__, (int)val);
  11676. + gf_dev = container_of(nb, struct gf_dev, notifier);
  11677. + if (evdata && evdata->data && val == FB_EVENT_BLANK && gf_dev) {
  11678. + blank = *(int *)(evdata->data);
  11679. + switch (blank) {
  11680. + case FB_BLANK_POWERDOWN:
  11681. + if (gf_dev->device_available == 1) {
  11682. + gf_dev->fb_black = 1;
  11683. +#if defined(GF_NETLINK_ENABLE)
  11684. + temp[0] = GF_NET_EVENT_FB_BLACK;
  11685. + sendnlmsg(temp);
  11686. +#elif defined (GF_FASYNC)
  11687. + if (gf_dev->async) {
  11688. + kill_fasync(&gf_dev->async, SIGIO, POLL_IN);
  11689. + }
  11690. +#endif
  11691. + }
  11692. + break;
  11693. + case FB_BLANK_UNBLANK:
  11694. + if (gf_dev->device_available == 1) {
  11695. + gf_dev->fb_black = 0;
  11696. +#if defined(GF_NETLINK_ENABLE)
  11697. + temp[0] = GF_NET_EVENT_FB_UNBLACK;
  11698. + sendnlmsg(temp);
  11699. +#elif defined (GF_FASYNC)
  11700. + if (gf_dev->async) {
  11701. + kill_fasync(&gf_dev->async, SIGIO, POLL_IN);
  11702. + }
  11703. +#endif
  11704. + }
  11705. + break;
  11706. + default:
  11707. + pr_debug("%s defalut\n", __func__);
  11708. + break;
  11709. + }
  11710. + }
  11711. + return NOTIFY_OK;
  11712. +}
  11713. +
  11714. +static struct notifier_block goodix_noti_block = {
  11715. + .notifier_call = goodix_fb_state_chg_callback,
  11716. +};
  11717. +
  11718. +static struct class *gf_class;
  11719. +#if defined(USE_SPI_BUS)
  11720. +static int gf_probe(struct spi_device *spi)
  11721. +#elif defined(USE_PLATFORM_BUS)
  11722. +static int gf_probe(struct platform_device *pdev)
  11723. +#endif
  11724. +{
  11725. + struct gf_dev *gf_dev = &gf;
  11726. + int status = -EINVAL;
  11727. + unsigned long minor;
  11728. + int i;
  11729. +
  11730. + /* Initialize the driver data */
  11731. + INIT_LIST_HEAD(&gf_dev->device_entry);
  11732. +#if defined(USE_SPI_BUS)
  11733. + gf_dev->spi = spi;
  11734. +#elif defined(USE_PLATFORM_BUS)
  11735. + gf_dev->spi = pdev;
  11736. +#endif
  11737. + gf_dev->irq_gpio = -EINVAL;
  11738. + gf_dev->reset_gpio = -EINVAL;
  11739. + gf_dev->pwr_gpio = -EINVAL;
  11740. + gf_dev->device_available = 0;
  11741. + gf_dev->fb_black = 0;
  11742. +
  11743. + if (gf_parse_dts(gf_dev))
  11744. + goto error_hw;
  11745. +
  11746. + /* If we can allocate a minor number, hook up this device.
  11747. + * Reusing minors is fine so long as udev or mdev is working.
  11748. + */
  11749. + mutex_lock(&device_list_lock);
  11750. + minor = find_first_zero_bit(minors, N_SPI_MINORS);
  11751. + if (minor < N_SPI_MINORS) {
  11752. + struct device *dev;
  11753. +
  11754. + gf_dev->devt = MKDEV(SPIDEV_MAJOR, minor);
  11755. + dev = device_create(gf_class, &gf_dev->spi->dev, gf_dev->devt,
  11756. + gf_dev, GF_DEV_NAME);
  11757. + status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
  11758. + } else {
  11759. + dev_dbg(&gf_dev->spi->dev, "no minor number available!\n");
  11760. + status = -ENODEV;
  11761. + mutex_unlock(&device_list_lock);
  11762. + goto error_hw;
  11763. + }
  11764. +
  11765. + if (status == 0) {
  11766. + set_bit(minor, minors);
  11767. + list_add(&gf_dev->device_entry, &device_list);
  11768. + } else {
  11769. + gf_dev->devt = 0;
  11770. + }
  11771. + mutex_unlock(&device_list_lock);
  11772. +
  11773. + if (status == 0) {
  11774. + /*input device subsystem */
  11775. + gf_dev->input = input_allocate_device();
  11776. + if (gf_dev->input == NULL) {
  11777. + pr_err("%s, failed to allocate input device\n", __func__);
  11778. + status = -ENOMEM;
  11779. + goto error_dev;
  11780. + }
  11781. + for (i = 0; i < ARRAY_SIZE(maps); i++)
  11782. + input_set_capability(gf_dev->input, maps[i].type, maps[i].code);
  11783. +
  11784. + gf_dev->input->name = GF_INPUT_NAME;
  11785. + status = input_register_device(gf_dev->input);
  11786. + if (status) {
  11787. + pr_err("failed to register input device\n");
  11788. + goto error_input;
  11789. + }
  11790. + }
  11791. +#ifdef AP_CONTROL_CLK
  11792. + pr_debug("Get the clk resource.\n");
  11793. + /* Enable spi clock */
  11794. + if (gfspi_ioctl_clk_init(gf_dev))
  11795. + goto gfspi_probe_clk_init_failed;
  11796. +
  11797. + if (gfspi_ioctl_clk_enable(gf_dev))
  11798. + goto gfspi_probe_clk_enable_failed;
  11799. +
  11800. + spi_clock_set(gf_dev, 1000000);
  11801. +#endif
  11802. +
  11803. + gf_dev->notifier = goodix_noti_block;
  11804. + fb_register_client(&gf_dev->notifier);
  11805. +
  11806. + gf_dev->irq = gf_irq_num(gf_dev);
  11807. +
  11808. + wake_lock_init(&fp_wakelock, WAKE_LOCK_SUSPEND, "fp_wakelock");
  11809. + pr_debug("version V%d.%d.%02d\n", VER_MAJOR, VER_MINOR, PATCH_LEVEL);
  11810. +
  11811. + return status;
  11812. +
  11813. +#ifdef AP_CONTROL_CLK
  11814. +gfspi_probe_clk_enable_failed:
  11815. + gfspi_ioctl_clk_uninit(gf_dev);
  11816. +gfspi_probe_clk_init_failed:
  11817. +#endif
  11818. + input_unregister_device(gf_dev->input);
  11819. +error_input:
  11820. + if (gf_dev->input != NULL)
  11821. + input_free_device(gf_dev->input);
  11822. +error_dev:
  11823. + if (gf_dev->devt != 0) {
  11824. + pr_debug("Err: status = %d\n", status);
  11825. + mutex_lock(&device_list_lock);
  11826. + list_del(&gf_dev->device_entry);
  11827. + device_destroy(gf_class, gf_dev->devt);
  11828. + clear_bit(MINOR(gf_dev->devt), minors);
  11829. + mutex_unlock(&device_list_lock);
  11830. + }
  11831. +error_hw:
  11832. + gf_cleanup(gf_dev);
  11833. + gf_dev->device_available = 0;
  11834. +
  11835. + return status;
  11836. +}
  11837. +
  11838. +#if defined(USE_SPI_BUS)
  11839. +static int gf_remove(struct spi_device *spi)
  11840. +#elif defined(USE_PLATFORM_BUS)
  11841. +static int gf_remove(struct platform_device *pdev)
  11842. +#endif
  11843. +{
  11844. + struct gf_dev *gf_dev = &gf;
  11845. +
  11846. + wake_lock_destroy(&fp_wakelock);
  11847. + /* make sure ops on existing fds can abort cleanly */
  11848. + if (gf_dev->irq)
  11849. + free_irq(gf_dev->irq, gf_dev);
  11850. +
  11851. + if (gf_dev->input != NULL)
  11852. + input_unregister_device(gf_dev->input);
  11853. + input_free_device(gf_dev->input);
  11854. +
  11855. + /* prevent new opens */
  11856. + mutex_lock(&device_list_lock);
  11857. + list_del(&gf_dev->device_entry);
  11858. + device_destroy(gf_class, gf_dev->devt);
  11859. + clear_bit(MINOR(gf_dev->devt), minors);
  11860. + if (gf_dev->users == 0)
  11861. + gf_cleanup(gf_dev);
  11862. +
  11863. +
  11864. + fb_unregister_client(&gf_dev->notifier);
  11865. + mutex_unlock(&device_list_lock);
  11866. +
  11867. + return 0;
  11868. +}
  11869. +
  11870. +static struct of_device_id gx_match_table[] = {
  11871. + { .compatible = GF_SPIDEV_NAME },
  11872. + {},
  11873. +};
  11874. +
  11875. +#if defined(USE_SPI_BUS)
  11876. +static struct spi_driver gf_driver = {
  11877. +#elif defined(USE_PLATFORM_BUS)
  11878. +static struct platform_driver gf_driver = {
  11879. +#endif
  11880. + .driver = {
  11881. + .name = GF_DEV_NAME,
  11882. + .owner = THIS_MODULE,
  11883. + .of_match_table = gx_match_table,
  11884. + },
  11885. + .probe = gf_probe,
  11886. + .remove = gf_remove,
  11887. +};
  11888. +
  11889. +static int __init gf_init(void)
  11890. +{
  11891. + int status;
  11892. +
  11893. + /* Claim our 256 reserved device numbers. Then register a class
  11894. + * that will key udev/mdev to add/remove /dev nodes. Last, register
  11895. + * the driver which manages those device numbers.
  11896. + */
  11897. +
  11898. + BUILD_BUG_ON(N_SPI_MINORS > 256);
  11899. + status = register_chrdev(SPIDEV_MAJOR, CHRD_DRIVER_NAME, &gf_fops);
  11900. + if (status < 0) {
  11901. + pr_warn("Failed to register char device!\n");
  11902. + return status;
  11903. + }
  11904. + SPIDEV_MAJOR = status;
  11905. + gf_class = class_create(THIS_MODULE, CLASS_NAME);
  11906. + if (IS_ERR(gf_class)) {
  11907. + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name);
  11908. + pr_warn("Failed to create class.\n");
  11909. + return PTR_ERR(gf_class);
  11910. + }
  11911. +#if defined(USE_PLATFORM_BUS)
  11912. + status = platform_driver_register(&gf_driver);
  11913. +#elif defined(USE_SPI_BUS)
  11914. + status = spi_register_driver(&gf_driver);
  11915. +#endif
  11916. + if (status < 0) {
  11917. + class_destroy(gf_class);
  11918. + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name);
  11919. + pr_warn("Failed to register SPI driver.\n");
  11920. + }
  11921. +
  11922. +#ifdef GF_NETLINK_ENABLE
  11923. + netlink_init();
  11924. +#endif
  11925. + pr_debug("status = 0x%x\n", status);
  11926. + return 0;
  11927. +}
  11928. +module_init(gf_init);
  11929. +
  11930. +static void __exit gf_exit(void)
  11931. +{
  11932. +#ifdef GF_NETLINK_ENABLE
  11933. + netlink_exit();
  11934. +#endif
  11935. +#if defined(USE_PLATFORM_BUS)
  11936. + platform_driver_unregister(&gf_driver);
  11937. +#elif defined(USE_SPI_BUS)
  11938. + spi_unregister_driver(&gf_driver);
  11939. +#endif
  11940. + class_destroy(gf_class);
  11941. + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name);
  11942. +}
  11943. +module_exit(gf_exit);
  11944. +
  11945. +MODULE_AUTHOR("Jiangtao Yi, <yijiangtao@goodix.com>");
  11946. +MODULE_AUTHOR("Jandy Gou, <gouqingsong@goodix.com>");
  11947. +MODULE_DESCRIPTION("goodix fingerprint sensor device driver");
  11948. +MODULE_LICENSE("GPL");
  11949. diff --git a/drivers/input/fingerprint/goodix_ta/gf_spi.h b/drivers/input/fingerprint/goodix_ta/gf_spi.h
  11950. new file mode 100644
  11951. index 0000000..207e385
  11952. --- /dev/null
  11953. +++ b/drivers/input/fingerprint/goodix_ta/gf_spi.h
  11954. @@ -0,0 +1,155 @@
  11955. +/*
  11956. + * driver definition for sensor driver
  11957. + *
  11958. + * Coypright (c) 2017 Goodix
  11959. + * Copyright (C) 2017 XiaoMi, Inc.
  11960. + */
  11961. +#ifndef __GF_SPI_H
  11962. +#define __GF_SPI_H
  11963. +
  11964. +#include <linux/types.h>
  11965. +#include <linux/notifier.h>
  11966. +/**********************************************************/
  11967. +enum FP_MODE{
  11968. + GF_IMAGE_MODE = 0,
  11969. + GF_KEY_MODE,
  11970. + GF_SLEEP_MODE,
  11971. + GF_FF_MODE,
  11972. + GF_DEBUG_MODE = 0x56
  11973. +};
  11974. +
  11975. +#define SUPPORT_NAV_EVENT
  11976. +
  11977. +#if defined(SUPPORT_NAV_EVENT)
  11978. +#define GF_NAV_INPUT_UP KEY_UP
  11979. +#define GF_NAV_INPUT_DOWN KEY_DOWN
  11980. +#define GF_NAV_INPUT_LEFT KEY_LEFT
  11981. +#define GF_NAV_INPUT_RIGHT KEY_RIGHT
  11982. +#define GF_NAV_INPUT_CLICK KEY_VOLUMEDOWN
  11983. +#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP
  11984. +#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH
  11985. +#define GF_NAV_INPUT_HEAVY KEY_CHAT
  11986. +#endif
  11987. +
  11988. +#define GF_KEY_INPUT_HOME KEY_HOME
  11989. +#define GF_KEY_INPUT_MENU KEY_MENU
  11990. +#define GF_KEY_INPUT_BACK KEY_BACK
  11991. +#define GF_KEY_INPUT_POWER KEY_POWER
  11992. +#define GF_KEY_INPUT_CAMERA KEY_CAMERA
  11993. +
  11994. +#if defined(SUPPORT_NAV_EVENT)
  11995. +typedef enum gf_nav_event {
  11996. + GF_NAV_NONE = 0,
  11997. + GF_NAV_FINGER_UP,
  11998. + GF_NAV_FINGER_DOWN,
  11999. + GF_NAV_UP,
  12000. + GF_NAV_DOWN,
  12001. + GF_NAV_LEFT,
  12002. + GF_NAV_RIGHT,
  12003. + GF_NAV_CLICK,
  12004. + GF_NAV_HEAVY,
  12005. + GF_NAV_LONG_PRESS,
  12006. + GF_NAV_DOUBLE_CLICK,
  12007. +} gf_nav_event_t;
  12008. +#endif
  12009. +
  12010. +typedef enum gf_key_event {
  12011. + GF_KEY_NONE = 0,
  12012. + GF_KEY_HOME,
  12013. + GF_KEY_POWER,
  12014. + GF_KEY_MENU,
  12015. + GF_KEY_BACK,
  12016. + GF_KEY_CAMERA,
  12017. +} gf_key_event_t;
  12018. +
  12019. +struct gf_key {
  12020. + enum gf_key_event key;
  12021. + uint32_t value; /* key down = 1, key up = 0 */
  12022. +};
  12023. +
  12024. +struct gf_key_map {
  12025. + unsigned int type;
  12026. + unsigned int code;
  12027. +};
  12028. +
  12029. +struct gf_ioc_chip_info {
  12030. + unsigned char vendor_id;
  12031. + unsigned char mode;
  12032. + unsigned char operation;
  12033. + unsigned char reserved[5];
  12034. +};
  12035. +
  12036. +#define GF_IOC_MAGIC 'g' /*define magic number*/
  12037. +#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t)
  12038. +#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1)
  12039. +#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2)
  12040. +#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3)
  12041. +#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4)
  12042. +#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t)
  12043. +#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6)
  12044. +#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7)
  12045. +#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8)
  12046. +#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key)
  12047. +#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10)
  12048. +#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t)
  12049. +#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12)
  12050. +#define GF_IOC_CHIP_INFO _IOW(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info)
  12051. +
  12052. +#if defined(SUPPORT_NAV_EVENT)
  12053. +#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t)
  12054. +#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */
  12055. +#else
  12056. +#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */
  12057. +#endif
  12058. +
  12059. +/*#define AP_CONTROL_CLK 1*/
  12060. +#define USE_PLATFORM_BUS 1
  12061. +/*#define USE_SPI_BUS 1*/
  12062. +/*#define GF_FASYNC 1*//*If support fasync mechanism.*/
  12063. +#define GF_NETLINK_ENABLE 1
  12064. +#define GF_NET_EVENT_IRQ 1
  12065. +#define GF_NET_EVENT_FB_BLACK 2
  12066. +#define GF_NET_EVENT_FB_UNBLACK 3
  12067. +#define NETLINK_TEST 25
  12068. +
  12069. +struct gf_dev {
  12070. + dev_t devt;
  12071. + struct list_head device_entry;
  12072. +#if defined(USE_SPI_BUS)
  12073. + struct spi_device *spi;
  12074. +#elif defined(USE_PLATFORM_BUS)
  12075. + struct platform_device *spi;
  12076. +#endif
  12077. + struct clk *core_clk;
  12078. + struct clk *iface_clk;
  12079. +
  12080. + struct input_dev *input;
  12081. + /* buffer is NULL unless this device is open (users > 0) */
  12082. + unsigned users;
  12083. + signed irq_gpio;
  12084. + signed reset_gpio;
  12085. + signed pwr_gpio;
  12086. + int irq;
  12087. + int irq_enabled;
  12088. + int clk_enabled;
  12089. +#ifdef GF_FASYNC
  12090. + struct fasync_struct *async;
  12091. +#endif
  12092. + struct notifier_block notifier;
  12093. + char device_available;
  12094. + char fb_black;
  12095. +};
  12096. +
  12097. +int gf_parse_dts(struct gf_dev *gf_dev);
  12098. +void gf_cleanup(struct gf_dev *gf_dev);
  12099. +
  12100. +int gf_power_on(struct gf_dev *gf_dev);
  12101. +int gf_power_off(struct gf_dev *gf_dev);
  12102. +
  12103. +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms);
  12104. +int gf_irq_num(struct gf_dev *gf_dev);
  12105. +
  12106. +void sendnlmsg(char *message);
  12107. +int netlink_init(void);
  12108. +void netlink_exit(void);
  12109. +#endif /*__GF_SPI_H*/
  12110. diff --git a/drivers/input/fingerprint/goodix_ta/netlink.c b/drivers/input/fingerprint/goodix_ta/netlink.c
  12111. new file mode 100644
  12112. index 0000000..9e96fa8
  12113. --- /dev/null
  12114. +++ b/drivers/input/fingerprint/goodix_ta/netlink.c
  12115. @@ -0,0 +1,98 @@
  12116. +/*
  12117. + * netlink interface
  12118. + *
  12119. + * Copyright (c) 2017 Goodix
  12120. + * Copyright (C) 2017 XiaoMi, Inc.
  12121. + */
  12122. +#include <linux/init.h>
  12123. +#include <linux/module.h>
  12124. +#include <linux/timer.h>
  12125. +#include <linux/time.h>
  12126. +#include <linux/types.h>
  12127. +#include <net/sock.h>
  12128. +#include <net/netlink.h>
  12129. +
  12130. +#define NETLINK_TEST 25
  12131. +#define MAX_MSGSIZE 32
  12132. +int stringlength(char *s);
  12133. +void sendnlmsg(char *message);
  12134. +static int pid = -1;
  12135. +struct sock *nl_sk = NULL;
  12136. +
  12137. +void sendnlmsg(char *message)
  12138. +{
  12139. + struct sk_buff *skb_1;
  12140. + struct nlmsghdr *nlh;
  12141. + int len = NLMSG_SPACE(MAX_MSGSIZE);
  12142. + int slen = 0;
  12143. + int ret = 0;
  12144. + if (!message || !nl_sk || !pid) {
  12145. + return;
  12146. + }
  12147. + skb_1 = alloc_skb(len, GFP_KERNEL);
  12148. + if (!skb_1) {
  12149. + pr_err("alloc_skb error\n");
  12150. + return;
  12151. + }
  12152. + slen = strlen(message);
  12153. + nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0);
  12154. +
  12155. + NETLINK_CB(skb_1).portid = 0;
  12156. + NETLINK_CB(skb_1).dst_group = 0;
  12157. +
  12158. + message[slen] = '\0';
  12159. + memcpy(NLMSG_DATA(nlh), message, slen+1);
  12160. +
  12161. + ret = netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT);
  12162. + if (!ret) {
  12163. + /*kfree_skb(skb_1);*/
  12164. + pr_err("send msg from kernel to usespace failed ret 0x%x\n", ret);
  12165. + }
  12166. +
  12167. +}
  12168. +
  12169. +
  12170. +void nl_data_ready(struct sk_buff *__skb)
  12171. +{
  12172. + struct sk_buff *skb;
  12173. + struct nlmsghdr *nlh;
  12174. + char str[100];
  12175. + skb = skb_get (__skb);
  12176. + if (skb->len >= NLMSG_SPACE(0)) {
  12177. + nlh = nlmsg_hdr(skb);
  12178. + memcpy(str, NLMSG_DATA(nlh), sizeof(str));
  12179. + pid = nlh->nlmsg_pid;
  12180. + kfree_skb(skb);
  12181. + }
  12182. +}
  12183. +
  12184. +
  12185. +int netlink_init(void)
  12186. +{
  12187. + struct netlink_kernel_cfg netlink_cfg;
  12188. + memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg));
  12189. +
  12190. + netlink_cfg.groups = 0;
  12191. + netlink_cfg.flags = 0;
  12192. + netlink_cfg.input = nl_data_ready;
  12193. + netlink_cfg.cb_mutex = NULL;
  12194. +
  12195. + nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST,
  12196. + &netlink_cfg);
  12197. +
  12198. + if (!nl_sk) {
  12199. + pr_err("create netlink socket error\n");
  12200. + return 1;
  12201. + }
  12202. + return 0;
  12203. +}
  12204. +
  12205. +void netlink_exit(void)
  12206. +{
  12207. + if (nl_sk != NULL) {
  12208. + netlink_kernel_release(nl_sk);
  12209. + nl_sk = NULL;
  12210. + }
  12211. + pr_info("self module exited\n");
  12212. +}
  12213. +
  12214. diff --git a/drivers/input/fingerprint/goodix_ta/platform.c b/drivers/input/fingerprint/goodix_ta/platform.c
  12215. new file mode 100644
  12216. index 0000000..3ac2965
  12217. --- /dev/null
  12218. +++ b/drivers/input/fingerprint/goodix_ta/platform.c
  12219. @@ -0,0 +1,98 @@
  12220. +/*
  12221. + * platform indepent driver interface
  12222. + *
  12223. + * Coypritht (c) 2017 Goodix
  12224. + * Copyright (C) 2017 XiaoMi, Inc.
  12225. + */
  12226. +#include <linux/delay.h>
  12227. +#include <linux/workqueue.h>
  12228. +#include <linux/of_gpio.h>
  12229. +#include <linux/gpio.h>
  12230. +#include <linux/regulator/consumer.h>
  12231. +#include <linux/timer.h>
  12232. +#include <linux/err.h>
  12233. +
  12234. +#include "gf_spi.h"
  12235. +
  12236. +#if defined(USE_SPI_BUS)
  12237. +#include <linux/spi/spi.h>
  12238. +#include <linux/spi/spidev.h>
  12239. +#elif defined(USE_PLATFORM_BUS)
  12240. +#include <linux/platform_device.h>
  12241. +#endif
  12242. +
  12243. +int gf_parse_dts(struct gf_dev *gf_dev)
  12244. +{
  12245. + /*get reset resource*/
  12246. + gf_dev->reset_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node, "fp-gpio-reset", 0);
  12247. + if (!gpio_is_valid(gf_dev->reset_gpio)) {
  12248. + pr_info("RESET GPIO is invalid.\n");
  12249. + return -EPERM;
  12250. + }
  12251. +
  12252. + /*get irq resourece*/
  12253. + gf_dev->irq_gpio = of_get_named_gpio(gf_dev->spi->dev.of_node, "fp-gpio-irq", 0);
  12254. + pr_info("gf::irq_gpio:%d\n", gf_dev->irq_gpio);
  12255. + if (!gpio_is_valid(gf_dev->irq_gpio)) {
  12256. + pr_info("IRQ GPIO is invalid.\n");
  12257. + return -EPERM;
  12258. + }
  12259. +
  12260. + return 0;
  12261. +}
  12262. +
  12263. +void gf_cleanup(struct gf_dev *gf_dev)
  12264. +{
  12265. + pr_info("[info] %s\n", __func__);
  12266. + if (gpio_is_valid(gf_dev->irq_gpio)) {
  12267. + gpio_free(gf_dev->irq_gpio);
  12268. + pr_info("remove irq_gpio success\n");
  12269. + }
  12270. + if (gpio_is_valid(gf_dev->reset_gpio)) {
  12271. + gpio_free(gf_dev->reset_gpio);
  12272. + pr_info("remove reset_gpio success\n");
  12273. + }
  12274. +}
  12275. +
  12276. +int gf_power_on(struct gf_dev *gf_dev)
  12277. +{
  12278. + int rc = 0;
  12279. +
  12280. + msleep(10);
  12281. + pr_info("---- power on ok ----\n");
  12282. +
  12283. + return rc;
  12284. +}
  12285. +
  12286. +int gf_power_off(struct gf_dev *gf_dev)
  12287. +{
  12288. + int rc = 0;
  12289. +
  12290. + pr_info("---- power off ----\n");
  12291. + return rc;
  12292. +}
  12293. +
  12294. +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms)
  12295. +{
  12296. + if (gf_dev == NULL) {
  12297. + pr_info("Input buff is NULL.\n");
  12298. + return -EPERM;
  12299. + }
  12300. + gpio_direction_output(gf_dev->reset_gpio, 0);
  12301. + gpio_set_value(gf_dev->reset_gpio, 0);
  12302. + mdelay(3);
  12303. + gpio_set_value(gf_dev->reset_gpio, 1);
  12304. + mdelay(delay_ms);
  12305. + return 0;
  12306. +}
  12307. +
  12308. +int gf_irq_num(struct gf_dev *gf_dev)
  12309. +{
  12310. + if (gf_dev == NULL) {
  12311. + pr_info("Input buff is NULL.\n");
  12312. + return -EPERM;
  12313. + } else {
  12314. + return gpio_to_irq(gf_dev->irq_gpio);
  12315. + }
  12316. +}
  12317. +
  12318. diff --git a/drivers/input/input.c b/drivers/input/input.c
  12319. index baaddd1..b063ea1 100644
  12320. --- a/drivers/input/input.c
  12321. +++ b/drivers/input/input.c
  12322. @@ -2,6 +2,7 @@
  12323. * The input core
  12324. *
  12325. * Copyright (c) 1999-2002 Vojtech Pavlik
  12326. + * Copyright (C) 2017 XiaoMi, Inc.
  12327. */
  12328.  
  12329. /*
  12330. @@ -27,6 +28,9 @@
  12331. #include <linux/device.h>
  12332. #include <linux/mutex.h>
  12333. #include <linux/rcupdate.h>
  12334. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12335. +#include <linux/rtc.h>
  12336. +#endif
  12337. #include "input-compat.h"
  12338.  
  12339. MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
  12340. @@ -50,6 +54,50 @@ static DEFINE_MUTEX(input_mutex);
  12341.  
  12342. static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
  12343.  
  12344. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12345. +static int input_device_is_touch(struct input_dev *input_dev)
  12346. +{
  12347. + unsigned long mask = BIT_MASK(BTN_TOUCH);
  12348. + return ((input_dev->keybit[BIT_WORD(BTN_TOUCH)] & mask) == mask) ? true:false;
  12349. +}
  12350. +
  12351. +static inline void touch_press_release_events_collect(struct input_dev *dev,
  12352. + unsigned int type, unsigned int code, int value)
  12353. +{
  12354. + if (dev->touch_events) {
  12355. + pr_debug("type %d, code %d, value %d\n", type, code, value);
  12356. + if (code == ABS_MT_TRACKING_ID) {
  12357. + if (value != -1 && !dev->touch_is_pressed) { /* Pressed */
  12358. + getnstimeofday(&dev->latest_touch_event.press_time_stamp);
  12359. + dev->touch_is_pressed = true;
  12360. + }
  12361. + } else if (code == BTN_TOUCH) {
  12362. + if (value == 0 && dev->touch_is_pressed) { /* Released */
  12363. + getnstimeofday(&dev->latest_touch_event.release_time_stamp);
  12364. + dev->touch_events->touch_event_buf[dev->touch_events->touch_event_num] =
  12365. + dev->latest_touch_event;
  12366. + dev->touch_events->touch_event_num++;
  12367. + if (dev->touch_events->touch_event_num >= TOUCH_EVENT_MAX)
  12368. + dev->touch_events->touch_event_num = 0;
  12369. + dev->latest_touch_event.press_pos_x = 0;
  12370. + dev->latest_touch_event.press_pos_y = 0;
  12371. + dev->touch_is_pressed = false;
  12372. + }
  12373. + } else if (code == ABS_MT_POSITION_X) {
  12374. + if (!dev->latest_touch_event.press_pos_x && dev->touch_is_pressed) {
  12375. + dev->latest_touch_event.press_pos_x = value;
  12376. + }
  12377. + dev->latest_touch_event.release_pos_x = value;
  12378. + } else if (code == ABS_MT_POSITION_Y) {
  12379. + if (!dev->latest_touch_event.press_pos_y && dev->touch_is_pressed) {
  12380. + dev->latest_touch_event.press_pos_y = value;
  12381. + }
  12382. + dev->latest_touch_event.release_pos_y = value;
  12383. + }
  12384. + }
  12385. +}
  12386. +#endif
  12387. +
  12388. static inline int is_event_supported(unsigned int code,
  12389. unsigned long *bm, unsigned int max)
  12390. {
  12391. @@ -436,6 +484,9 @@ void input_event(struct input_dev *dev,
  12392. spin_lock_irqsave(&dev->event_lock, flags);
  12393. input_handle_event(dev, type, code, value);
  12394. spin_unlock_irqrestore(&dev->event_lock, flags);
  12395. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12396. + touch_press_release_events_collect(dev, type, code, value);
  12397. +#endif
  12398. }
  12399. }
  12400. EXPORT_SYMBOL(input_event);
  12401. @@ -1261,6 +1312,59 @@ static const struct file_operations input_handlers_fileops = {
  12402. .release = seq_release,
  12403. };
  12404.  
  12405. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12406. +static int last_touch_events_show(struct seq_file *seq, void *v)
  12407. +{
  12408. + struct input_dev *dev = container_of(v, struct input_dev, node);
  12409. + int i = 0;
  12410. + struct rtc_time tm;
  12411. +
  12412. + if (!input_device_is_touch(dev) || !dev->touch_events)
  12413. + return 0;
  12414. +
  12415. + seq_printf(seq, "Name=\"%s\"\n", dev->name ? dev->name : "");
  12416. +
  12417. + for (i = 0; i < TOUCH_EVENT_MAX; i++) {
  12418. + if (dev->touch_events->touch_event_buf[i].release_pos_x == 0 &&
  12419. + dev->touch_events->touch_event_buf[i].release_pos_y == 0)
  12420. + continue;
  12421. +
  12422. + rtc_time_to_tm(dev->touch_events->touch_event_buf[i].press_time_stamp.tv_sec, &tm);
  12423. + seq_printf(seq, "%d-%02d-%02d %02d:%02d:%02d.%09lu UTC Postion (%d, %d) pressed\n",
  12424. + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  12425. + tm.tm_hour, tm.tm_min, tm.tm_sec, dev->touch_events->touch_event_buf[i].press_time_stamp.tv_nsec,
  12426. + dev->touch_events->touch_event_buf[i].press_pos_x, dev->touch_events->touch_event_buf[i].press_pos_y);
  12427. +
  12428. + rtc_time_to_tm(dev->touch_events->touch_event_buf[i].release_time_stamp.tv_sec, &tm);
  12429. + seq_printf(seq, "%d-%02d-%02d %02d:%02d:%02d.%09lu UTC Postion (%d, %d) released\n",
  12430. + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  12431. + tm.tm_hour, tm.tm_min, tm.tm_sec, dev->touch_events->touch_event_buf[i].release_time_stamp.tv_nsec,
  12432. + dev->touch_events->touch_event_buf[i].release_pos_x, dev->touch_events->touch_event_buf[i].release_pos_y);
  12433. + }
  12434. + return 0;
  12435. +}
  12436. +
  12437. +static const struct seq_operations input_last_touch_events_seq_ops = {
  12438. + .start = input_devices_seq_start,
  12439. + .next = input_devices_seq_next,
  12440. + .stop = input_seq_stop,
  12441. + .show = last_touch_events_show,
  12442. +};
  12443. +
  12444. +static int input_last_touch_events_open(struct inode *inode, struct file *file)
  12445. +{
  12446. + return seq_open(file, &input_last_touch_events_seq_ops);
  12447. +}
  12448. +
  12449. +
  12450. +static const struct file_operations input_last_touch_events_fileops = {
  12451. + .open = input_last_touch_events_open,
  12452. + .read = seq_read,
  12453. + .llseek = seq_lseek,
  12454. + .release = seq_release,
  12455. +};
  12456. +#endif
  12457. +
  12458. static int __init input_proc_init(void)
  12459. {
  12460. struct proc_dir_entry *entry;
  12461. @@ -1278,8 +1382,17 @@ static int __init input_proc_init(void)
  12462. &input_handlers_fileops);
  12463. if (!entry)
  12464. goto fail2;
  12465. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12466. + entry = proc_create("last_touch_events", 0, proc_bus_input_dir,
  12467. + &input_last_touch_events_fileops);
  12468. + if (!entry)
  12469. + goto fail3;
  12470. +#endif
  12471.  
  12472. return 0;
  12473. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12474. + fail3: remove_proc_entry("handlers", proc_bus_input_dir);
  12475. +#endif
  12476.  
  12477. fail2: remove_proc_entry("devices", proc_bus_input_dir);
  12478. fail1: remove_proc_entry("bus/input", NULL);
  12479. @@ -1288,6 +1401,9 @@ static int __init input_proc_init(void)
  12480.  
  12481. static void input_proc_exit(void)
  12482. {
  12483. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12484. + remove_proc_entry("last_touch_events", proc_bus_input_dir);
  12485. +#endif
  12486. remove_proc_entry("devices", proc_bus_input_dir);
  12487. remove_proc_entry("handlers", proc_bus_input_dir);
  12488. remove_proc_entry("bus/input", NULL);
  12489. @@ -2168,6 +2284,19 @@ int input_register_device(struct input_dev *dev)
  12490. __func__, dev_name(&dev->dev));
  12491. devres_add(dev->dev.parent, devres);
  12492. }
  12493. +
  12494. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12495. + if (input_device_is_touch(dev)) {
  12496. + dev->touch_events = kzalloc(sizeof(struct touch_event_info), GFP_KERNEL);
  12497. + if (dev->touch_events == NULL) {
  12498. + pr_err("Touch event: alloc memory failed\n");
  12499. + }
  12500. +
  12501. + dev->touch_is_pressed = false;
  12502. + dev->latest_touch_event.press_pos_x = 0;
  12503. + dev->latest_touch_event.press_pos_y = 0;
  12504. + }
  12505. +#endif
  12506. return 0;
  12507.  
  12508. err_device_del:
  12509. @@ -2190,6 +2319,12 @@ EXPORT_SYMBOL(input_register_device);
  12510. */
  12511. void input_unregister_device(struct input_dev *dev)
  12512. {
  12513. +#ifdef CONFIG_LAST_TOUCH_EVENTS
  12514. + if (dev->touch_events) {
  12515. + kfree(dev->touch_events);
  12516. + dev->touch_events = NULL;
  12517. + }
  12518. +#endif
  12519. if (dev->devres_managed) {
  12520. WARN_ON(devres_destroy(dev->dev.parent,
  12521. devm_input_device_unregister,
  12522. diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
  12523. index 339f94c..d9fdb9a 100644
  12524. --- a/drivers/input/misc/qpnp-power-on.c
  12525. +++ b/drivers/input/misc/qpnp-power-on.c
  12526. @@ -1,4 +1,5 @@
  12527. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
  12528. + * Copyright (C) 2017 XiaoMi, Inc.
  12529. *
  12530. * This program is free software; you can redistribute it and/or modify
  12531. * it under the terms of the GNU General Public License version 2 and
  12532. @@ -32,6 +33,7 @@
  12533. #include <linux/regulator/of_regulator.h>
  12534. #include <linux/input/qpnp-power-on.h>
  12535. #include <linux/power_supply.h>
  12536. +#include <linux/wakelock.h>
  12537.  
  12538. #define PMIC_VER_8941 0x01
  12539. #define PMIC_VERSION_REG 0x0105
  12540. @@ -66,6 +68,7 @@
  12541. ((pon)->base + PON_OFFSET((pon)->subtype, 0xA, 0xC2))
  12542. #define QPNP_POFF_REASON1(pon) \
  12543. ((pon)->base + PON_OFFSET((pon)->subtype, 0xC, 0xC5))
  12544. +#define QPNP_POFF_REASON2(pon) ((pon)->base + 0xD)
  12545. #define QPNP_PON_WARM_RESET_REASON2(pon) ((pon)->base + 0xB)
  12546. #define QPNP_PON_OFF_REASON(pon) ((pon)->base + 0xC7)
  12547. #define QPNP_FAULT_REASON1(pon) ((pon)->base + 0xC8)
  12548. @@ -228,6 +231,8 @@ module_param_named(
  12549. ship_mode_en, pon_ship_mode_en, int, 0600
  12550. );
  12551.  
  12552. +static struct wake_lock volume_down_wl;
  12553. +static const char *wake_lock_name = "volume_down_locker";
  12554. static struct qpnp_pon *sys_reset_dev;
  12555. static DEFINE_SPINLOCK(spon_list_slock);
  12556. static LIST_HEAD(spon_dev_list);
  12557. @@ -631,6 +636,103 @@ int qpnp_pon_is_warm_reset(void)
  12558. }
  12559. EXPORT_SYMBOL(qpnp_pon_is_warm_reset);
  12560.  
  12561. +int qpnp_pon_is_ps_hold_reset(void)
  12562. +{
  12563. + struct qpnp_pon *pon = sys_reset_dev;
  12564. + int rc;
  12565. + int reg = 0;
  12566. +
  12567. + if (!pon)
  12568. + return 0;
  12569. +
  12570. + rc = regmap_read(pon->regmap, QPNP_POFF_REASON1(pon), &reg);
  12571. + if (rc) {
  12572. + dev_err(&pon->pdev->dev,
  12573. + "Unable to read addr=%x, rc(%d)\n",
  12574. + QPNP_POFF_REASON1(pon), rc);
  12575. + return 0;
  12576. + }
  12577. +
  12578. + /* The bit 1 is 1, means by PS_HOLD/MSM controlled shutdown */
  12579. + if (reg & 0x2)
  12580. + return 1;
  12581. +
  12582. + dev_info(&pon->pdev->dev,
  12583. + "hw_reset reason1 is 0x%x\n",
  12584. + reg);
  12585. +
  12586. + rc = regmap_read(pon->regmap, QPNP_POFF_REASON2(pon), &reg);
  12587. +
  12588. + dev_info(&pon->pdev->dev,
  12589. + "hw_reset reason2 is 0x%x\n",
  12590. + reg);
  12591. + return 0;
  12592. +}
  12593. +EXPORT_SYMBOL(qpnp_pon_is_ps_hold_reset);
  12594. +
  12595. +int qpnp_pon_is_lck(void)
  12596. +{
  12597. + struct qpnp_pon *pon = sys_reset_dev;
  12598. + int rc;
  12599. + int reg = 0;
  12600. +
  12601. + if (!pon)
  12602. + return 0;
  12603. +
  12604. + rc = regmap_read(pon->regmap, QPNP_PON_WARM_RESET_REASON1(pon),
  12605. + &reg);
  12606. + if (rc) {
  12607. + dev_err(&pon->pdev->dev, "Unable to read addr=%x, rc(%d)\n",
  12608. + QPNP_PON_WARM_RESET_REASON1(pon), rc);
  12609. + return 0;
  12610. + }
  12611. +
  12612. + /* The bit 5 is 1, means the power on reason is KPDPWR_AND_RESIN */
  12613. + if (reg & 0x20)
  12614. + return 1;
  12615. +
  12616. + dev_info(&pon->pdev->dev,
  12617. + "warm_reset reason1 is 0x%x\n",
  12618. + reg);
  12619. +
  12620. + return 0;
  12621. +}
  12622. +EXPORT_SYMBOL(qpnp_pon_is_lck);
  12623. +
  12624. +int qpnp_pon_is_lpk(void)
  12625. +{
  12626. + struct qpnp_pon *pon = sys_reset_dev;
  12627. + int rc;
  12628. + int reg = 0;
  12629. +
  12630. + if (!pon)
  12631. + return 0;
  12632. +
  12633. + rc = regmap_read(pon->regmap, QPNP_POFF_REASON1(pon), &reg);
  12634. + if (rc) {
  12635. + dev_err(&pon->pdev->dev,
  12636. + "Unable to read addr=%x, rc(%d)\n",
  12637. + QPNP_POFF_REASON1(pon), rc);
  12638. + return 0;
  12639. + }
  12640. +
  12641. + /* The bit 7 is 1, means the off reason is powerkey */
  12642. + if (reg & 0x80)
  12643. + return 1;
  12644. +
  12645. + dev_info(&pon->pdev->dev,
  12646. + "hw_reset reason1 is 0x%x\n",
  12647. + reg);
  12648. +
  12649. + rc = regmap_read(pon->regmap, QPNP_POFF_REASON2(pon), &reg);
  12650. +
  12651. + dev_info(&pon->pdev->dev,
  12652. + "hw_reset reason2 is 0x%x\n",
  12653. + reg);
  12654. + return 0;
  12655. +}
  12656. +EXPORT_SYMBOL(qpnp_pon_is_lpk);
  12657. +
  12658. /**
  12659. * qpnp_pon_wd_config - Disable the wd in a warm reset.
  12660. * @enable: to enable or disable the PON watch dog
  12661. @@ -892,6 +994,7 @@ static irqreturn_t qpnp_resin_irq(int irq, void *_pon)
  12662. int rc;
  12663. struct qpnp_pon *pon = _pon;
  12664.  
  12665. + wake_lock_timeout(&volume_down_wl, 3*HZ);
  12666. rc = qpnp_pon_input_dispatch(pon, PON_RESIN);
  12667. if (rc)
  12668. dev_err(&pon->pdev->dev, "Unable to send input event\n");
  12669. @@ -2360,6 +2463,9 @@ static int qpnp_pon_probe(struct platform_device *pdev)
  12670. "qcom,store-hard-reset-reason");
  12671.  
  12672. qpnp_pon_debugfs_init(pdev);
  12673. + /* if wake_lock not be initied, init it */
  12674. + if (volume_down_wl.ws.name != wake_lock_name)
  12675. + wake_lock_init(&volume_down_wl, WAKE_LOCK_SUSPEND, wake_lock_name);
  12676. return 0;
  12677. }
  12678.  
  12679. @@ -2380,6 +2486,7 @@ static int qpnp_pon_remove(struct platform_device *pdev)
  12680. list_del(&pon->list);
  12681. spin_unlock_irqrestore(&spon_list_slock, flags);
  12682. }
  12683. + wake_lock_destroy(&volume_down_wl);
  12684. return 0;
  12685. }
  12686.  
  12687. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
  12688. index 2d564aa..bdb4c6f 100644
  12689. --- a/drivers/input/touchscreen/Kconfig
  12690. +++ b/drivers/input/touchscreen/Kconfig
  12691. @@ -12,6 +12,8 @@ menuconfig INPUT_TOUCHSCREEN
  12692. if INPUT_TOUCHSCREEN
  12693.  
  12694. source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
  12695. +source "drivers/input/touchscreen/synaptics_dsx_force/Kconfig"
  12696. +source "drivers/input/touchscreen/ft5x46/Kconfig"
  12697.  
  12698. config OF_TOUCHSCREEN
  12699. def_tristate INPUT
  12700. diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
  12701. index f5be6fc..aee53c9 100644
  12702. --- a/drivers/input/touchscreen/Makefile
  12703. +++ b/drivers/input/touchscreen/Makefile
  12704. @@ -70,6 +70,7 @@ obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
  12705. obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
  12706. obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
  12707. obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v21) += synaptics_dsx/
  12708. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FORCE) += synaptics_dsx_force/
  12709. obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
  12710. obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
  12711. obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
  12712. @@ -97,4 +98,6 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
  12713. obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
  12714. obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
  12715. obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
  12716. +obj-$(CONFIG_TOUCHSCREEN_ST_FTS) += fts/
  12717. +obj-$(CONFIG_TOUCHSCREEN_FT5X46) += ft5x46/
  12718. obj-$(CONFIG_TOUCHSCREEN_ST) += st/
  12719. diff --git a/drivers/input/touchscreen/ft5x46/Kconfig b/drivers/input/touchscreen/ft5x46/Kconfig
  12720. new file mode 100644
  12721. index 0000000..8bac8f9
  12722. --- /dev/null
  12723. +++ b/drivers/input/touchscreen/ft5x46/Kconfig
  12724. @@ -0,0 +1,52 @@
  12725. +config TOUCHSCREEN_FT5X46
  12726. + tristate "FocalTech touchscreens"
  12727. + depends on I2C
  12728. + help
  12729. + Say Y here if you have a FT5X46 touchscreen.
  12730. + Ft5x06 controllers are multi touch controllers which can
  12731. + report 5 touches at a time.
  12732. +
  12733. + If unsure, say N.
  12734. +
  12735. + To compile this driver as a module, choose M here: the
  12736. + module will be called ft5x46_ts.
  12737. +
  12738. +config TOUCHSCREEN_FT5X46_CALIBRATE
  12739. + bool "calibrate after flash firmware"
  12740. + depends on TOUCHSCREEN_FT5X46
  12741. + default y
  12742. + help
  12743. + must turn off after all pre-production device get upgrade.
  12744. +
  12745. +config TOUCHSCREEN_FT5X46_TYPEB
  12746. + bool "use type B for touch report"
  12747. + depends on TOUCHSCREEN_FT5X46
  12748. + default y
  12749. + help
  12750. + enable typeB for multi-touch report.
  12751. +
  12752. +config TOUCHSCREEN_FT5X46_I2C
  12753. + tristate "Focaltech FT5X0X I2C touchscreens"
  12754. + depends on I2C
  12755. + select TOUCHSCREEN_FT5X46
  12756. + help
  12757. + Say Y here if you have a Focaltech FT5X46 I2C touchscreen connected
  12758. + to your system.
  12759. +
  12760. + If unsure, say N.
  12761. +
  12762. + To compile this driver as a set of modules, choose M here: the
  12763. + modules will be called ft5x46_ts_i2c.
  12764. +
  12765. +config TOUCHSCREEN_FT5X46_SPI
  12766. + tristate "Focaltech FT5X0X SPI touchscreens"
  12767. + depends on SPI
  12768. + select TOUCHSCREEN_FT5X46
  12769. + help
  12770. + Say Y here if you have a Focaltech FT5X46 SPI touchscreen connected
  12771. + to your system.
  12772. +
  12773. + If unsure, say N.
  12774. +
  12775. + To compile this driver as a set of modules, choose M here: the
  12776. + modules will be called ft5x46_ts_spi.
  12777. diff --git a/drivers/input/touchscreen/ft5x46/Makefile b/drivers/input/touchscreen/ft5x46/Makefile
  12778. new file mode 100644
  12779. index 0000000..21a0bc1
  12780. --- /dev/null
  12781. +++ b/drivers/input/touchscreen/ft5x46/Makefile
  12782. @@ -0,0 +1,8 @@
  12783. +#
  12784. +# Makefile for the FT5X46 touchscreen driver.
  12785. +#
  12786. +
  12787. +#obj-$(CONFIG_TOUCHSCREEN_FT5X46) += ft5x46_ts.o focaltech_test.o focaltech_test_ft5x46.o
  12788. +#obj-$(CONFIG_TOUCHSCREEN_FT5X46_I2C) += ft5x46_ts_i2c.o
  12789. +#obj-$(CONFIG_TOUCHSCREEN_FT5X46_SPI) += ft5x46_ts_spi.o
  12790. +obj-y += ft5x46_ts.o focaltech_test.o focaltech_test_ft5x46.o ft5x46_ts_i2c.o
  12791. diff --git a/drivers/input/touchscreen/ft5x46/focaltech_test.c b/drivers/input/touchscreen/ft5x46/focaltech_test.c
  12792. new file mode 100644
  12793. index 0000000..dabd8c0
  12794. --- /dev/null
  12795. +++ b/drivers/input/touchscreen/ft5x46/focaltech_test.c
  12796. @@ -0,0 +1,313 @@
  12797. +
  12798. +/*
  12799. + * FocalTech TouchScreen driver.
  12800. + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved.
  12801. + * Copyright (C) 2017 XiaoMi, Inc.
  12802. + * This software is licensed under the terms of the GNU General Public
  12803. + * License version 2, as published by the Free Software Foundation, and
  12804. + * may be copied, distributed, and modified under those terms.
  12805. + * This program is distributed in the hope that it will be useful,
  12806. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12807. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12808. + * GNU General Public License for more details.
  12809. + */
  12810. +
  12811. + /************************************************************************
  12812. +* File Name: focaltech_test.c
  12813. +* Author: Software Department, FocalTech
  12814. +* Created: 2016-03-24
  12815. +* Modify:
  12816. +* Abstract: create char device and proc node for the comm between APK and TP
  12817. +************************************************************************/
  12818. +
  12819. +/*******************************************************************************
  12820. +* Included header files
  12821. +*******************************************************************************/
  12822. +#include <linux/kernel.h>
  12823. +#include <linux/module.h>
  12824. +#include <linux/slab.h>
  12825. +#include <linux/vmalloc.h>
  12826. +#include <linux/debugfs.h>
  12827. +#include <linux/interrupt.h>
  12828. +#include <linux/uaccess.h>
  12829. +#include <linux/i2c.h>
  12830. +#include <linux/delay.h>
  12831. +#include <linux/proc_fs.h>
  12832. +#include "focaltech_test.h"
  12833. +#include "focaltech_test_ft5x46.h"
  12834. +
  12835. +/*******************************************************************************
  12836. +* Private constant and macro definitions using #define
  12837. +*******************************************************************************/
  12838. +#define FOCALTECH_TEST_INFO "focaltech_test.c:V1.1.0 2016-05-19"
  12839. +#define DEVIDE_MODE_ADDR 0x00
  12840. +#define FTS_MALLOC_TYPE 1
  12841. +static struct proc_dir_entry *fts_selftest_proc;
  12842. +/*******************************************************************************
  12843. +* functions body
  12844. +*******************************************************************************/
  12845. +int fts_test_result = RESULT_INVALID;
  12846. +
  12847. +static int fts_i2c_read_test(unsigned char *writebuf, int writelen,
  12848. + unsigned char *readbuf, int readlen)
  12849. +{
  12850. + int iret = -1;
  12851. +
  12852. + iret = fts_i2c_read(fts_i2c_client, writebuf,
  12853. + writelen, readbuf, readlen);
  12854. + return iret;
  12855. +
  12856. +}
  12857. +
  12858. +static int fts_i2c_write_test(unsigned char *writebuf, int writelen)
  12859. +{
  12860. + int iret = -1;
  12861. +
  12862. + iret = fts_i2c_write(fts_i2c_client, writebuf, writelen);
  12863. + return iret;
  12864. +}
  12865. +
  12866. +void focal_msleep(int ms)
  12867. +{
  12868. + msleep(ms);
  12869. +}
  12870. +void SysDelay(int ms)
  12871. +{
  12872. + msleep(ms);
  12873. +}
  12874. +int focal_abs(int value)
  12875. +{
  12876. + if (value < 0)
  12877. + value = 0 - value;
  12878. + return value;
  12879. +}
  12880. +void *fts_malloc(size_t size)
  12881. +{
  12882. + if (FTS_MALLOC_TYPE == kmalloc_mode)
  12883. + return kmalloc(size, GFP_ATOMIC);
  12884. + if (FTS_MALLOC_TYPE == vmalloc_mode)
  12885. + return vmalloc(size);
  12886. + return NULL;
  12887. +}
  12888. +void fts_free(void *p)
  12889. +{
  12890. + if (FTS_MALLOC_TYPE == kmalloc_mode)
  12891. + kfree(p);
  12892. + if (FTS_MALLOC_TYPE == vmalloc_mode)
  12893. + vfree(p);
  12894. +}
  12895. +
  12896. +/************************************************************************
  12897. +* Name: ReadReg(Same function name as FT_MultipleTest)
  12898. +* Brief: Read Register
  12899. +* Input: RegAddr
  12900. +* Output: RegData
  12901. +* Return: Comm Code. Code = 0x00 is OK, else fail.
  12902. +***********************************************************************/
  12903. +int ReadReg(unsigned char RegAddr, unsigned char *RegData)
  12904. +{
  12905. + int iRet;
  12906. +
  12907. + iRet = fts_i2c_read_test(&RegAddr, 1, RegData, 1);
  12908. +
  12909. + if (iRet >= 0)
  12910. + return ERROR_CODE_OK;
  12911. + else
  12912. + return ERROR_CODE_COMM_ERROR;
  12913. +}
  12914. +/************************************************************************
  12915. +* Name: WriteReg(Same function name as FT_MultipleTest)
  12916. +* Brief: Write Register
  12917. +* Input: RegAddr, RegData
  12918. +* Output: null
  12919. +* Return: Comm Code. Code = 0x00 is OK, else fail.
  12920. +***********************************************************************/
  12921. +int WriteReg(unsigned char RegAddr, unsigned char RegData)
  12922. +{
  12923. + int iRet;
  12924. + unsigned char cmd[2] = {0};
  12925. +
  12926. + cmd[0] = RegAddr;
  12927. + cmd[1] = RegData;
  12928. + iRet = fts_i2c_write_test(cmd, 2);
  12929. +
  12930. + if (iRet >= 0)
  12931. + return ERROR_CODE_OK;
  12932. + else
  12933. + return ERROR_CODE_COMM_ERROR;
  12934. +}
  12935. +/************************************************************************
  12936. +* Name: Comm_Base_IIC_IO(Same function name as FT_MultipleTest)
  12937. +* Brief: Write/Read Data by IIC
  12938. +* Input: pWriteBuffer, iBytesToWrite, iBytesToRead
  12939. +* Output: pReadBuffer
  12940. +* Return: Comm Code. Code = 0x00 is OK, else fail.
  12941. +***********************************************************************/
  12942. +unsigned char Comm_Base_IIC_IO(unsigned char *pWriteBuffer, int iBytesToWrite,
  12943. + unsigned char *pReadBuffer, int iBytesToRead)
  12944. +{
  12945. + int iRet;
  12946. +
  12947. + iRet = fts_i2c_read_test(pWriteBuffer, iBytesToWrite,
  12948. + pReadBuffer, iBytesToRead);
  12949. +
  12950. + if (iRet >= 0)
  12951. + return ERROR_CODE_OK;
  12952. + else
  12953. + return ERROR_CODE_COMM_ERROR;
  12954. +}
  12955. +/************************************************************************
  12956. +* Name: EnterWork(Same function name as FT_MultipleTest)
  12957. +* Brief: Enter Work Mode
  12958. +* Input: null
  12959. +* Output: null
  12960. +* Return: Comm Code. Code = 0x00 is OK, else fail.
  12961. +***********************************************************************/
  12962. +unsigned char EnterWork(void)
  12963. +{
  12964. + unsigned char RunState = 0;
  12965. + unsigned char ReCode = ERROR_CODE_COMM_ERROR;
  12966. +
  12967. + FTS_TEST_DBG("");
  12968. + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState);
  12969. + if (ReCode == ERROR_CODE_OK) {
  12970. + if (((RunState>>4)&0x07) == 0x00)
  12971. + ReCode = ERROR_CODE_OK;
  12972. + else {
  12973. + ReCode = WriteReg(DEVIDE_MODE_ADDR, 0);
  12974. + if (ReCode == ERROR_CODE_OK) {
  12975. + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState);
  12976. + if (ReCode == ERROR_CODE_OK) {
  12977. + if (((RunState>>4)&0x07) == 0x00)
  12978. + ReCode = ERROR_CODE_OK;
  12979. + else
  12980. + ReCode = ERROR_CODE_COMM_ERROR;
  12981. + }
  12982. + } else
  12983. + pr_err("%s,error\n", __func__);
  12984. + }
  12985. + }
  12986. +
  12987. + return ReCode;
  12988. +}
  12989. +/************************************************************************
  12990. +* Name: EnterFactory
  12991. +* Brief: enter Fcatory Mode
  12992. +* Input: null
  12993. +* Output: null
  12994. +* Return: Comm Code. Code = 0 is OK, else fail.
  12995. +***********************************************************************/
  12996. +unsigned char EnterFactory(void)
  12997. +{
  12998. + unsigned char RunState = 0;
  12999. + unsigned char ReCode = ERROR_CODE_COMM_ERROR;
  13000. +
  13001. + FTS_TEST_DBG("");
  13002. + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState);
  13003. + if (ReCode == ERROR_CODE_OK) {
  13004. + if (((RunState>>4)&0x07) == 0x04)
  13005. + ReCode = ERROR_CODE_OK;
  13006. + else {
  13007. + ReCode = WriteReg(DEVIDE_MODE_ADDR, 0x40);
  13008. + if (ReCode == ERROR_CODE_OK) {
  13009. + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState);
  13010. + if (ReCode == ERROR_CODE_OK) {
  13011. + if (((RunState>>4)&0x07) == 0x04)
  13012. + ReCode = ERROR_CODE_OK;
  13013. + else
  13014. + ReCode = ERROR_CODE_COMM_ERROR;
  13015. + }
  13016. + }
  13017. + }
  13018. + } else
  13019. + FTS_TEST_ERR("EnterFactory read DEVIDE_MODE_ADDR error 1.");
  13020. +
  13021. + FTS_TEST_DBG(" END");
  13022. + return ReCode;
  13023. +}
  13024. +int fts_i2c_test(struct i2c_client *client)
  13025. +{
  13026. + int retry = 5;
  13027. + int ReCode = ERROR_CODE_OK;
  13028. + unsigned char chip_id = 0;
  13029. +
  13030. + if (client == NULL)
  13031. + return RESULT_INVALID;
  13032. + fts_test_result = RESULT_INVALID;
  13033. + while (retry--) {
  13034. + ReCode = ReadReg(REG_CHIP_ID, &chip_id);
  13035. + if (ReCode == ERROR_CODE_OK)
  13036. + return RESULT_PASS;
  13037. + dev_err(&client->dev, "GTP i2c test failed time %d.\n", retry);
  13038. + msleep(20);
  13039. + }
  13040. + if (ReCode != ERROR_CODE_OK)
  13041. + return RESULT_NG;
  13042. + return RESULT_INVALID;
  13043. +}
  13044. +
  13045. +
  13046. +int fts_tp_selftest_open(struct inode *inode, struct file *file)
  13047. +{
  13048. + return 0;
  13049. +}
  13050. +
  13051. +ssize_t fts_tp_selftest_read(struct file *file, char __user *buf,
  13052. + size_t count, loff_t *pos)
  13053. +{
  13054. + if (*pos != 0)
  13055. + return 0;
  13056. + snprintf(buf, sizeof(fts_test_result), "%d", fts_test_result);
  13057. + *pos += strlen(buf);
  13058. + return strlen(buf);
  13059. +}
  13060. +
  13061. +ssize_t fts_tp_selftest_write(struct file *file, const char __user *buf,
  13062. + size_t count, loff_t *pos)
  13063. +{
  13064. + int retval;
  13065. +
  13066. + if (!fts_i2c_client) {
  13067. + retval = -EINVAL;
  13068. + fts_test_result = RESULT_INVALID;
  13069. + goto out;
  13070. + }
  13071. + disable_irq(fts_i2c_client->irq);
  13072. + if (!strncmp(buf, "short", 5))
  13073. + fts_test_result = FT5X46_TestItem_WeakShortTest(fts_i2c_client);
  13074. + else if (!strncmp(buf, "open", 4))
  13075. + fts_test_result = FT5X46_TestItem_RawDataTest(fts_i2c_client);
  13076. + else if (!strncmp(buf, "i2c", 3))
  13077. + fts_test_result = fts_i2c_test(fts_i2c_client);
  13078. + EnterWork();
  13079. + enable_irq(fts_i2c_client->irq);
  13080. +out:
  13081. + return RESULT_NG;
  13082. +}
  13083. +
  13084. +int fts_tp_selftest_release(struct inode *inode, struct file *file)
  13085. +{
  13086. + return 0;
  13087. +}
  13088. +static const struct file_operations tp_selftest_ops = {
  13089. + .open = fts_tp_selftest_open,
  13090. + .read = fts_tp_selftest_read,
  13091. + .write = fts_tp_selftest_write,
  13092. + .release = fts_tp_selftest_release,
  13093. +};
  13094. +
  13095. +int fts_test_module_init(struct i2c_client *client)
  13096. +{
  13097. +
  13098. + FTS_TEST_DBG("[focal] %s ", FOCALTECH_TEST_INFO);
  13099. + fts_selftest_proc = proc_create("tp_selftest", 0,
  13100. + NULL, &tp_selftest_ops);
  13101. + return 0;
  13102. +}
  13103. +int fts_test_module_exit(struct i2c_client *client)
  13104. +{
  13105. + FTS_TEST_DBG("");
  13106. + if (fts_selftest_proc)
  13107. + remove_proc_entry("tp_selftest", NULL);
  13108. + return 0;
  13109. +}
  13110. diff --git a/drivers/input/touchscreen/ft5x46/focaltech_test.h b/drivers/input/touchscreen/ft5x46/focaltech_test.h
  13111. new file mode 100644
  13112. index 0000000..70f819a
  13113. --- /dev/null
  13114. +++ b/drivers/input/touchscreen/ft5x46/focaltech_test.h
  13115. @@ -0,0 +1,119 @@
  13116. +
  13117. +/************************************************************************
  13118. +* Copyright (C) 2012-2015, Focaltech Systems (R),All Rights Reserved.
  13119. +* Copyright (C) 2017 XiaoMi, Inc.
  13120. +*
  13121. +* File Name: focaltech_test_main.h
  13122. +*
  13123. +* Author: Software Development Team, AE
  13124. +*
  13125. +* Created: 2015-07-14
  13126. +*
  13127. +* Abstract: test entry for all IC
  13128. +*
  13129. +************************************************************************/
  13130. +#ifndef _TEST_LIB_H
  13131. +#define _TEST_LIB_H
  13132. +#include <linux/kernel.h>
  13133. +#define boolean unsigned char
  13134. +#define bool unsigned char
  13135. +#define BYTE unsigned char
  13136. +#define false 0
  13137. +#define true 1
  13138. +
  13139. +
  13140. +#define MIN_HOLE_LEVEL (-1)
  13141. +#define MAX_HOLE_LEVEL 0x7F
  13142. +#define ERROR_CODE_OK 0x00
  13143. +#define ERROR_CODE_CHECKSUM_ERROR 0x01
  13144. +#define ERROR_CODE_INVALID_COMMAND 0x02
  13145. +#define ERROR_CODE_INVALID_PARAM 0x03
  13146. +#define ERROR_CODE_IIC_WRITE_ERROR 0x04
  13147. +#define ERROR_CODE_IIC_READ_ERROR 0x05
  13148. +#define ERROR_CODE_WRITE_USB_ERROR 0x06
  13149. +#define ERROR_CODE_WAIT_RESPONSE_TIMEOUT 0x07
  13150. +#define ERROR_CODE_PACKET_RE_ERROR 0x08
  13151. +#define ERROR_CODE_NO_DEVICE 0x09
  13152. +#define ERROR_CODE_WAIT_WRITE_TIMEOUT 0x0a
  13153. +#define ERROR_CODE_READ_USB_ERROR 0x0b
  13154. +#define ERROR_CODE_COMM_ERROR 0x0c
  13155. +#define ERROR_CODE_ALLOCATE_BUFFER_ERROR 0x0d
  13156. +#define ERROR_CODE_DEVICE_OPENED 0x0e
  13157. +#define ERROR_CODE_DEVICE_CLOSED 0x0f
  13158. +
  13159. +/*-----------------------------------------------------------
  13160. +Test Status
  13161. +-----------------------------------------------------------*/
  13162. +#define RESULT_INVALID 0
  13163. +#define RESULT_PASS 2
  13164. +#define RESULT_NG 1
  13165. +
  13166. +/*-----------------------------------------------------------
  13167. +read write max bytes per time
  13168. +-----------------------------------------------------------*/
  13169. +#define BYTES_PER_TIME 128
  13170. +#define DEVIDE_MODE_ADDR 0x00
  13171. +#define REG_CHIP_ID 0xA3
  13172. +#define FTS_MALLOC_TYPE 1
  13173. +#define TX_NUM_MAX 60
  13174. +#define RX_NUM_MAX 60
  13175. +enum NodeType {
  13176. + NODE_INVALID_TYPE = 0,
  13177. + NODE_VALID_TYPE = 1,
  13178. + NODE_KEY_TYPE = 2,
  13179. + NODE_AST_TYPE = 3,
  13180. +};
  13181. +
  13182. +
  13183. +enum enum_malloc_mode {
  13184. + kmalloc_mode = 0,
  13185. + vmalloc_mode = 1,
  13186. +};
  13187. +
  13188. +
  13189. +enum NORMALIZE_Type {
  13190. + Overall_Normalize = 0,
  13191. + Auto_Normalize = 1,
  13192. +};
  13193. +
  13194. +enum PROOF_TYPE {
  13195. + Proof_Normal,
  13196. + Proof_Level0,
  13197. + Proof_NoWaterProof,
  13198. +};
  13199. +
  13200. +int fts_test_module_init(struct i2c_client *client);
  13201. +int fts_test_module_exit(struct i2c_client *client);
  13202. +extern struct i2c_client *fts_i2c_client;
  13203. +extern int fts_i2c_write(struct i2c_client *client,
  13204. + char *writebuf, int writelen);
  13205. +extern int fts_i2c_read(struct i2c_client *client,
  13206. + char *writebuf, int writelen, char *readbuf, int readlen);
  13207. +void focal_msleep(int ms);
  13208. +void SysDelay(int ms);
  13209. +int focal_abs(int value);
  13210. +int ReadReg(unsigned char RegAddr, unsigned char *RegData);
  13211. +int WriteReg(unsigned char RegAddr, unsigned char RegData);
  13212. +unsigned char Comm_Base_IIC_IO(unsigned char *pWriteBuffer, int iBytesToWrite,
  13213. + unsigned char *pReadBuffer, int iBytesToRead);
  13214. +unsigned char EnterWork(void);
  13215. +unsigned char EnterFactory(void);
  13216. +void *fts_malloc(size_t size);
  13217. +void fts_free(void *p);
  13218. +#define FOCAL_TEST_DEBUG_EN 1
  13219. +
  13220. +#if (FOCAL_TEST_DEBUG_EN)
  13221. +#define FTS_TEST_DBG(fmt, args...) \
  13222. + pr_debug("[FOCAL] %s. line: %d. "fmt"\n",\
  13223. + __func__, __LINE__, ##args)
  13224. +#define FTS_TEST_PRINT(fmt, args...) pr_err(""fmt, ## args)
  13225. +#define FTS_TEST_ERR(fmt, args...) \
  13226. + pr_err("[FOCAL] %s. line: %d. "fmt"\n", \
  13227. + __func__, __LINE__, ##args)
  13228. +#else
  13229. +#define FTS_TEST_DBG(fmt, args...) do {} while (0)
  13230. +#define FTS_TEST_PRINT(fmt, args...) do {} while (0)
  13231. +#endif
  13232. +
  13233. +
  13234. +#endif
  13235. diff --git a/drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.c b/drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.c
  13236. new file mode 100644
  13237. index 0000000..3563822
  13238. --- /dev/null
  13239. +++ b/drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.c
  13240. @@ -0,0 +1,806 @@
  13241. +/************************************************************************
  13242. +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved.
  13243. +* Copyright (C) 2017 XiaoMi, Inc.
  13244. +*
  13245. +* File Name: Test_FT5X46.c
  13246. +*
  13247. +* Author: Software Development Team, AE
  13248. +*
  13249. +* Created: 2015-07-14
  13250. +*
  13251. +*
  13252. +************************************************************************/
  13253. +
  13254. +#include <linux/kernel.h>
  13255. +#include <linux/string.h>
  13256. +#include <linux/slab.h>
  13257. +#include <linux/i2c.h>
  13258. +#include <linux/input/ft5x46_ts.h>
  13259. +#include "focaltech_test.h"
  13260. +
  13261. +#define DEVIDE_MODE_ADDR 0x00
  13262. +#define REG_LINE_NUM 0x01
  13263. +#define REG_TX_NUM 0x02
  13264. +#define REG_RX_NUM 0x03
  13265. +#define REG_MAPPING_SWITCH 0x54
  13266. +#define REG_TX_NOMAPPING_NUM 0x55
  13267. +#define REG_RX_NOMAPPING_NUM 0x56
  13268. +#define REG_NORMALIZE_TYPE 0x16
  13269. +#define REG_RawBuf0 0x36
  13270. +static int m_RawData[TX_NUM_MAX][RX_NUM_MAX] = {{0} };
  13271. +static int m_iTempRawData[TX_NUM_MAX * RX_NUM_MAX] = {0};
  13272. +static unsigned char m_ucTempData[TX_NUM_MAX * RX_NUM_MAX*2] = {0};
  13273. +static bool m_bV3TP;
  13274. +struct StruScreenSeting {
  13275. + int iTxNum;
  13276. + int iRxNum;
  13277. + int isNormalize;
  13278. + int iUsedMaxTxNum;
  13279. + int iUsedMaxRxNum;
  13280. + unsigned char iChannelsNum;
  13281. + unsigned char iKeyNum;
  13282. +} g_ScreenSetParam;
  13283. +
  13284. +static int StartScan(void);
  13285. +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum,
  13286. + int ByteNum, int *pRevBuffer);
  13287. +static unsigned char GetPanelRows(unsigned char *pPanelRows);
  13288. +static unsigned char GetPanelCols(unsigned char *pPanelCols);
  13289. +static unsigned char GetRawData(void);
  13290. +static unsigned char GetChannelNum(void);
  13291. +static void ShowRawData(void);
  13292. +static unsigned char GetChannelNumNoMapping(void);
  13293. +static unsigned char WeakShort_GetAdcData(int AllAdcDataLen, int *pRevBuffer);
  13294. +
  13295. +void set_max_channel_num(void)
  13296. +{
  13297. + g_ScreenSetParam.iUsedMaxTxNum = TX_NUM_MAX;
  13298. + g_ScreenSetParam.iUsedMaxRxNum = RX_NUM_MAX;
  13299. +
  13300. +}
  13301. +
  13302. +static int InitTest(void)
  13303. +{
  13304. + set_max_channel_num();
  13305. + return 0;
  13306. +}
  13307. +
  13308. +unsigned char FT5X46_TestItem_RawDataTest(struct i2c_client *client)
  13309. +{
  13310. +
  13311. + unsigned char ReCode = 0;
  13312. + bool btmpresult = true;
  13313. + int RawDataMin;
  13314. + unsigned char strSwitch = 0;
  13315. + unsigned char OriginValue = 0xff;
  13316. + int index = 0;
  13317. + int iRow, iCol;
  13318. + int iValue = 0;
  13319. + struct ft5x46_data *ft5x46 = i2c_get_clientdata(client);
  13320. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  13321. +
  13322. + m_bV3TP = false;
  13323. + FTS_TEST_DBG("\n\nTest Item:Raw Data Test\n");
  13324. + InitTest();
  13325. +
  13326. + ReCode = EnterFactory();
  13327. + if (ReCode != ERROR_CODE_OK) {
  13328. + FTS_TEST_ERR("\nFailed to Enter factory.%d",
  13329. + ReCode);
  13330. + goto TEST_ERR;
  13331. + }
  13332. +
  13333. + if (m_bV3TP) {
  13334. + ReCode = ReadReg(REG_MAPPING_SWITCH, &strSwitch);
  13335. + if (ReCode != ERROR_CODE_OK) {
  13336. + FTS_TEST_ERR("\n Read REG_MAPPING_SWITCH error%d", ReCode);
  13337. + goto TEST_ERR;
  13338. + }
  13339. + if (strSwitch != 0) {
  13340. + ReCode = WriteReg(REG_MAPPING_SWITCH, 0);
  13341. + if (ReCode != ERROR_CODE_OK) {
  13342. + FTS_TEST_ERR("\n Write REG_MAPPING_SWITCH error%d", ReCode);
  13343. + goto TEST_ERR;
  13344. + }
  13345. + ReCode = GetChannelNum();
  13346. + if (ReCode != ERROR_CODE_OK) {
  13347. + FTS_TEST_ERR("\n GetChannelNum error%d", ReCode);
  13348. + goto TEST_ERR;
  13349. + }
  13350. + }
  13351. + } else {
  13352. + ReCode = GetChannelNum();
  13353. + if (ReCode != ERROR_CODE_OK) {
  13354. + FTS_TEST_ERR("\n GetChannelNum error%d", ReCode);
  13355. + goto TEST_ERR;
  13356. + }
  13357. + }
  13358. +
  13359. + ReCode = ReadReg(REG_NORMALIZE_TYPE, &OriginValue);
  13360. + if (ReCode != ERROR_CODE_OK) {
  13361. + FTS_TEST_ERR("\n Read REG_NORMALIZE_TYPE error. %d", ReCode);
  13362. + goto TEST_ERR;
  13363. + }
  13364. +
  13365. + if (OriginValue != 1) {
  13366. + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x01);
  13367. + if (ReCode != ERROR_CODE_OK) {
  13368. + FTS_TEST_ERR("\n write REG_NORMALIZE_TYPE error.%d", ReCode);
  13369. + goto TEST_ERR;
  13370. + }
  13371. + }
  13372. +
  13373. + FTS_TEST_DBG("\nSet Frequecy High\n");
  13374. + ReCode = WriteReg(0x0A, 0x81);
  13375. + if (ReCode != ERROR_CODE_OK) {
  13376. + FTS_TEST_ERR("\n Set Frequecy High error. %d", ReCode);
  13377. + goto TEST_ERR;
  13378. + }
  13379. +
  13380. + FTS_TEST_DBG("\nFIR State: OFF");
  13381. + ReCode = WriteReg(0xFB, 0);
  13382. + if (ReCode != ERROR_CODE_OK) {
  13383. + FTS_TEST_ERR("\n FIR on error:%d", ReCode);
  13384. + goto TEST_ERR;
  13385. + }
  13386. +
  13387. + for (index = 0; index < 3; ++index)
  13388. + ReCode = GetRawData();
  13389. +
  13390. + if (ReCode != ERROR_CODE_OK) {
  13391. + FTS_TEST_ERR("\n Get Rawdata failed,Error Code: 0x%x", ReCode);
  13392. + goto TEST_ERR;
  13393. + }
  13394. +
  13395. + ShowRawData();
  13396. + RawDataMin = pdata->open_min;
  13397. + if (pdata->has_key) {
  13398. + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) {
  13399. + for (iCol = 0; iCol < (g_ScreenSetParam.iRxNum - 1); iCol++) {
  13400. + iValue = m_RawData[iRow][iCol];
  13401. + if (iValue < RawDataMin) {
  13402. + btmpresult = false;
  13403. + FTS_TEST_PRINT("rawdata failure.Node=(%d,%d),value=%d",
  13404. + iRow+1, iCol+1, iValue);
  13405. + }
  13406. + }
  13407. + }
  13408. + iValue = m_RawData[pdata->key_rx1 - 1][iCol];
  13409. + if (iValue < RawDataMin) {
  13410. + btmpresult = false;
  13411. + FTS_TEST_PRINT("rawdata failure.Node=(%d,%d),Get_value=%d",
  13412. + 4, iCol+1, iValue);
  13413. + }
  13414. + iValue = m_RawData[pdata->key_rx2 - 1][iCol];
  13415. + if (iValue < RawDataMin) {
  13416. + btmpresult = false;
  13417. + FTS_TEST_PRINT("rawdata failure.Node=(%d,%d),Get_value=%d",
  13418. + 8, iCol+1, iValue);
  13419. + }
  13420. + iValue = m_RawData[pdata->key_rx3 - 1][iCol];
  13421. + if (iValue < RawDataMin) {
  13422. + btmpresult = false;
  13423. + FTS_TEST_PRINT("rawdata test failure.Node=(%d,%d),Get_value=%d",
  13424. + 12, iCol+1, iValue);
  13425. + }
  13426. + } else {
  13427. + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) {
  13428. + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) {
  13429. + iValue = m_RawData[iRow][iCol];
  13430. + if (iValue < RawDataMin) {
  13431. + btmpresult = false;
  13432. + FTS_TEST_PRINT("rawdata failure.Node=(%d,%d),value=%d",
  13433. + iRow+1, iCol+1, iValue);
  13434. + }
  13435. + }
  13436. + }
  13437. + }
  13438. + ReCode = WriteReg(REG_NORMALIZE_TYPE, OriginValue);
  13439. + if (ReCode != ERROR_CODE_OK) {
  13440. + FTS_TEST_ERR("\n Write REG_NORMALIZE_TYPE error:%d", ReCode);
  13441. + goto TEST_ERR;
  13442. + }
  13443. +
  13444. + if (m_bV3TP) {
  13445. + ReCode = WriteReg(REG_MAPPING_SWITCH, strSwitch);
  13446. + if (ReCode != ERROR_CODE_OK) {
  13447. + FTS_TEST_ERR("\n Write REG_MAPPING_SWITCH errore: %d", ReCode);
  13448. + goto TEST_ERR;
  13449. + }
  13450. + }
  13451. +
  13452. + if (btmpresult) {
  13453. + FTS_TEST_ERR("\n\n//RawData Test is OK!");
  13454. + return RESULT_PASS;
  13455. + }
  13456. + if (!btmpresult) {
  13457. + FTS_TEST_ERR("\n\n//RawData Test is NG!");
  13458. + return RESULT_NG;
  13459. + }
  13460. + return RESULT_INVALID;
  13461. +
  13462. +TEST_ERR:
  13463. + FTS_TEST_DBG("\n\n//RawData Test is NG!");
  13464. + return RESULT_INVALID;
  13465. +}
  13466. +
  13467. +static unsigned char GetPanelRows(unsigned char *pPanelRows)
  13468. +{
  13469. + return ReadReg(REG_TX_NUM, pPanelRows);
  13470. +}
  13471. +
  13472. +static unsigned char GetPanelCols(unsigned char *pPanelCols)
  13473. +{
  13474. + return ReadReg(REG_RX_NUM, pPanelCols);
  13475. +}
  13476. +
  13477. +static int StartScan(void)
  13478. +{
  13479. + unsigned char RegVal = 0;
  13480. + unsigned char times = 0;
  13481. + const unsigned char MaxTimes = 20;
  13482. + unsigned char ReCode = ERROR_CODE_COMM_ERROR;
  13483. +
  13484. + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal);
  13485. + if (ReCode == ERROR_CODE_OK) {
  13486. + RegVal |= 0x80;
  13487. + ReCode = WriteReg(DEVIDE_MODE_ADDR, RegVal);
  13488. + if (ReCode == ERROR_CODE_OK) {
  13489. + while (times++ < MaxTimes) {
  13490. + SysDelay(8);
  13491. + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal);
  13492. + if (ReCode == ERROR_CODE_OK) {
  13493. + if ((RegVal>>7) == 0)
  13494. + break;
  13495. + } else {
  13496. + FTS_TEST_DBG("StartScan read DEVIDE_MODE_ADDR error.");
  13497. + break;
  13498. + }
  13499. + }
  13500. + if (times < MaxTimes)
  13501. + ReCode = ERROR_CODE_OK;
  13502. + else {
  13503. + ReCode = ERROR_CODE_COMM_ERROR;
  13504. + FTS_TEST_DBG("times NOT < MaxTimes. error.");
  13505. + }
  13506. + } else
  13507. + FTS_TEST_DBG("StartScan write DEVIDE_MODE_ADDR error.");
  13508. + } else
  13509. + FTS_TEST_DBG("StartScan read DEVIDE_MODE_ADDR error.");
  13510. + return ReCode;
  13511. +}
  13512. +
  13513. +unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer)
  13514. +{
  13515. + unsigned char ReCode = ERROR_CODE_COMM_ERROR;
  13516. + unsigned char I2C_wBuffer[3];
  13517. + int i, iReadNum;
  13518. + unsigned short BytesNumInTestMode1 = 0;
  13519. +
  13520. + iReadNum = ByteNum/BYTES_PER_TIME;
  13521. + if (0 != (ByteNum%BYTES_PER_TIME))
  13522. + iReadNum++;
  13523. +
  13524. + if (ByteNum <= BYTES_PER_TIME)
  13525. + BytesNumInTestMode1 = ByteNum;
  13526. + else
  13527. + BytesNumInTestMode1 = BYTES_PER_TIME;
  13528. + ReCode = WriteReg(REG_LINE_NUM, LineNum);
  13529. +
  13530. + if (ReCode != ERROR_CODE_OK) {
  13531. + FTS_TEST_DBG("Failed to write REG_LINE_NUM! ");
  13532. + goto READ_ERR;
  13533. + }
  13534. +
  13535. + I2C_wBuffer[0] = REG_RawBuf0;
  13536. + if (ReCode == ERROR_CODE_OK) {
  13537. + focal_msleep(10);
  13538. + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1,
  13539. + m_ucTempData, BytesNumInTestMode1);
  13540. + if (ReCode != ERROR_CODE_OK) {
  13541. + FTS_TEST_DBG("read rawdata Comm_Base_IIC_IO Failed!1 ");
  13542. + goto READ_ERR;
  13543. + }
  13544. + }
  13545. +
  13546. + for (i = 1; i < iReadNum; i++) {
  13547. + if (ReCode != ERROR_CODE_OK)
  13548. + break;
  13549. +
  13550. + if (i == iReadNum-1) {
  13551. + focal_msleep(10);
  13552. + ReCode = Comm_Base_IIC_IO(NULL, 0,
  13553. + m_ucTempData+BYTES_PER_TIME*i, ByteNum-BYTES_PER_TIME*i);
  13554. + if (ReCode != ERROR_CODE_OK) {
  13555. + FTS_TEST_DBG("read rawdata Comm_Base_IIC_IO Failed!2 ");
  13556. + goto READ_ERR;
  13557. + }
  13558. + } else {
  13559. + focal_msleep(10);
  13560. + ReCode = Comm_Base_IIC_IO(NULL, 0,
  13561. + m_ucTempData+BYTES_PER_TIME*i, BYTES_PER_TIME);
  13562. +
  13563. + if (ReCode != ERROR_CODE_OK) {
  13564. + FTS_TEST_DBG("read rawdata Comm_Base_IIC_IO Failed!3 ");
  13565. + goto READ_ERR;
  13566. + }
  13567. + }
  13568. +
  13569. + }
  13570. +
  13571. + if (ReCode == ERROR_CODE_OK)
  13572. + for (i = 0; i < (ByteNum>>1); i++)
  13573. + pRevBuffer[i] = (m_ucTempData[i<<1]<<8)+m_ucTempData[(i<<1)+1];
  13574. +
  13575. +READ_ERR:
  13576. + return ReCode;
  13577. +
  13578. +}
  13579. +
  13580. +static unsigned char GetChannelNum(void)
  13581. +{
  13582. + unsigned char ReCode;
  13583. + unsigned char rBuffer[1];
  13584. +
  13585. + ReCode = GetPanelRows(rBuffer);
  13586. + if (ReCode == ERROR_CODE_OK) {
  13587. + g_ScreenSetParam.iTxNum = rBuffer[0];
  13588. + if (g_ScreenSetParam.iTxNum > g_ScreenSetParam.iUsedMaxTxNum) {
  13589. + FTS_TEST_DBG("Failed to get Tx number, Get num = %d, UsedMaxNum = %d",
  13590. + g_ScreenSetParam.iTxNum, g_ScreenSetParam.iUsedMaxTxNum);
  13591. + g_ScreenSetParam.iTxNum = 0;
  13592. + return ERROR_CODE_INVALID_PARAM;
  13593. + }
  13594. + } else
  13595. + FTS_TEST_DBG("Failed to get Tx number");
  13596. +
  13597. + ReCode = GetPanelCols(rBuffer);
  13598. + if (ReCode == ERROR_CODE_OK) {
  13599. + g_ScreenSetParam.iRxNum = rBuffer[0];
  13600. + if (g_ScreenSetParam.iRxNum > g_ScreenSetParam.iUsedMaxRxNum) {
  13601. + FTS_TEST_DBG("Failed to get Rx number, Get num = %d, UsedMaxNum = %d",
  13602. + g_ScreenSetParam.iRxNum, g_ScreenSetParam.iUsedMaxRxNum);
  13603. + g_ScreenSetParam.iRxNum = 0;
  13604. + return ERROR_CODE_INVALID_PARAM;
  13605. + }
  13606. + } else
  13607. + FTS_TEST_DBG("Failed to get Rx number");
  13608. +
  13609. + return ReCode;
  13610. +
  13611. +}
  13612. +static unsigned char GetRawData(void)
  13613. +{
  13614. + unsigned char ReCode = ERROR_CODE_OK;
  13615. + int iRow = 0;
  13616. + int iCol = 0;
  13617. +
  13618. + ReCode = EnterFactory();
  13619. + if (ERROR_CODE_OK != ReCode) {
  13620. + FTS_TEST_DBG("Failed to Enter Factory Mode...");
  13621. + return ReCode;
  13622. + }
  13623. + if (0 == (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)) {
  13624. + ReCode = GetChannelNum();
  13625. + if (ERROR_CODE_OK != ReCode) {
  13626. + FTS_TEST_DBG("Error Channel Num...");
  13627. + return ERROR_CODE_INVALID_PARAM;
  13628. + }
  13629. + }
  13630. +
  13631. + FTS_TEST_DBG("Start Scan ...");
  13632. + ReCode = StartScan();
  13633. + if (ERROR_CODE_OK != ReCode) {
  13634. + FTS_TEST_DBG("Failed to Scan ...");
  13635. + return ReCode;
  13636. + }
  13637. +
  13638. + memset(m_RawData, 0, sizeof(m_RawData));
  13639. + ReCode = ReadRawData(1, 0xAA,
  13640. + (g_ScreenSetParam.iTxNum * g_ScreenSetParam.iRxNum)*2, m_iTempRawData);
  13641. + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++)
  13642. + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++)
  13643. + m_RawData[iRow][iCol] = m_iTempRawData[iRow*g_ScreenSetParam.iRxNum + iCol];
  13644. + return ReCode;
  13645. +}
  13646. +
  13647. +static void ShowRawData(void)
  13648. +{
  13649. + int iRow, iCol;
  13650. +
  13651. + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) {
  13652. + FTS_TEST_PRINT("Tx%2d: ", iRow+1);
  13653. + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++)
  13654. + FTS_TEST_PRINT("%5d ", m_RawData[iRow][iCol]);
  13655. + FTS_TEST_PRINT("\n ");
  13656. + }
  13657. +}
  13658. +
  13659. +static unsigned char GetChannelNumNoMapping(void)
  13660. +{
  13661. + unsigned char ReCode;
  13662. + unsigned char rBuffer[1];
  13663. +
  13664. + FTS_TEST_DBG("Get Tx Num...");
  13665. + ReCode = ReadReg(REG_TX_NOMAPPING_NUM, rBuffer);
  13666. + if (ReCode == ERROR_CODE_OK)
  13667. + g_ScreenSetParam.iTxNum = rBuffer[0];
  13668. + else
  13669. + FTS_TEST_DBG("Failed to get Tx number");
  13670. +
  13671. + FTS_TEST_DBG("Get Rx Num...");
  13672. + ReCode = ReadReg(REG_RX_NOMAPPING_NUM, rBuffer);
  13673. + if (ReCode == ERROR_CODE_OK)
  13674. + g_ScreenSetParam.iRxNum = rBuffer[0];
  13675. + else
  13676. + FTS_TEST_DBG("Failed to get Rx number");
  13677. +
  13678. + return ReCode;
  13679. +}
  13680. +unsigned char FT5X46_TestItem_WeakShortTest(struct i2c_client *client)
  13681. +{
  13682. + unsigned char ReCode = ERROR_CODE_COMM_ERROR;
  13683. + int i = 0;
  13684. + int iAllAdcDataNum = 63;
  13685. + int iMaxTx = 35;
  13686. + unsigned char iTxNum, iRxNum, iChannelNum;
  13687. + int iClbData_Ground, iClbData_Mutual, iOffset;
  13688. + unsigned char IcValue = 0;
  13689. + unsigned char strSwitch = 1;
  13690. + bool bCapShortTest = false;
  13691. + int *iAdcData = NULL;
  13692. + bool btmpresult = true;
  13693. + int fKcal = 0;
  13694. + int *fMShortResistance = NULL, *fGShortResistance = NULL;
  13695. + int iDoffset = 0, iDsen = 0, iDrefn = 0;
  13696. + int iMin_CG = 0;
  13697. + int iCount = 0;
  13698. + int iMin_CC = 0;
  13699. + int iDCal = 0;
  13700. + int iMa = 0;
  13701. + int iRsen = 57;
  13702. + int iCCRsen = 57;
  13703. + struct ft5x46_data *ft5x46 = i2c_get_clientdata(client);
  13704. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  13705. +
  13706. + FTS_TEST_DBG("\nTest Item:Weak Short-Circuit Test\n");
  13707. + InitTest();
  13708. + ReCode = EnterWork();
  13709. + if (ReCode != ERROR_CODE_OK) {
  13710. + FTS_TEST_ERR(" EnterWork failed.. Error Code: %d", ReCode);
  13711. + goto TEST_ERR;
  13712. + }
  13713. + SysDelay(200);
  13714. + ReCode = ReadReg(0xB1, &IcValue);
  13715. + if (ReCode != ERROR_CODE_OK) {
  13716. + FTS_TEST_ERR("\n Read 0xB1 IcValue error. Error Code: %d\n", ReCode);
  13717. + goto TEST_ERR;
  13718. + } else
  13719. + FTS_TEST_DBG(" IcValue:0x%02x\n", IcValue);
  13720. + ReCode = EnterFactory();
  13721. + SysDelay(100);
  13722. + if (ReCode != ERROR_CODE_OK) {
  13723. + FTS_TEST_ERR(" EnterFactory failed.. Error Code: %d", ReCode);
  13724. + goto TEST_ERR;
  13725. + }
  13726. +
  13727. + if (m_bV3TP) {
  13728. + ReCode = ReadReg(REG_MAPPING_SWITCH, &strSwitch);
  13729. + if (strSwitch != 1) {
  13730. + ReCode = WriteReg(REG_MAPPING_SWITCH, 1);
  13731. + SysDelay(20);
  13732. + if (ReCode != ERROR_CODE_OK)
  13733. + FTS_TEST_ERR("\r\nFailed to restore mapping type!\r\n ");
  13734. + GetChannelNumNoMapping();
  13735. + iTxNum = g_ScreenSetParam.iTxNum;
  13736. + iRxNum = g_ScreenSetParam.iRxNum;
  13737. + }
  13738. + } else {
  13739. + ReCode = ReadReg(0x02, &iTxNum);
  13740. + ReCode = ReadReg(0x03, &iRxNum);
  13741. + FTS_TEST_DBG("Newly acquired TxNum:%d, RxNum:%d", iTxNum, iRxNum);
  13742. + }
  13743. +
  13744. + if (ReCode != ERROR_CODE_OK) {
  13745. + FTS_TEST_ERR("ReCode error. Error Code: %d\n", ReCode);
  13746. + goto TEST_ERR;
  13747. + }
  13748. +
  13749. + iChannelNum = iTxNum + iRxNum;
  13750. + iMaxTx = iTxNum;
  13751. + iAllAdcDataNum = 1 + (1 + iTxNum + iRxNum)*2;
  13752. + for (i = 0; i < 5; i++) {
  13753. + ReCode = StartScan();
  13754. + if (ReCode != ERROR_CODE_OK) {
  13755. + FTS_TEST_ERR("StartScan Failed!\n");
  13756. + SysDelay(100);
  13757. + } else {
  13758. + FTS_TEST_DBG("StartScan OK!\n");
  13759. + break;
  13760. + }
  13761. + }
  13762. + if (i >= 5) {
  13763. + FTS_TEST_ERR("StartScan Failed for several times.!\n");
  13764. + goto TEST_ERR;
  13765. + }
  13766. + iAdcData = fts_malloc(iAllAdcDataNum*sizeof(int));
  13767. + memset(iAdcData, 0, iAllAdcDataNum);
  13768. + for (i = 0; i < 5; i++) {
  13769. + memset(iAdcData, 0, iAllAdcDataNum);
  13770. +
  13771. + FTS_TEST_DBG("WeakShort_GetAdcData times: %d", i);
  13772. +
  13773. + ReCode = WeakShort_GetAdcData(iAllAdcDataNum*2, iAdcData);
  13774. + SysDelay(50);
  13775. + if (ReCode != ERROR_CODE_OK)
  13776. + continue;
  13777. + else {
  13778. + if (0 == iAdcData[0] && 0 == iAdcData[1])
  13779. + continue;
  13780. + else
  13781. + break;
  13782. + }
  13783. + }
  13784. + if (i >= 5) {
  13785. + FTS_TEST_ERR("WeakShort_GetAdcData or ADC data error. tried times: %d", i);
  13786. + goto TEST_ERR;
  13787. + }
  13788. +
  13789. + FTS_TEST_DBG("");
  13790. +
  13791. + iOffset = iAdcData[0];
  13792. + iClbData_Ground = iAdcData[1];
  13793. + iClbData_Mutual = iAdcData[2 + iChannelNum];
  13794. +
  13795. + for (i = 0; i < iAllAdcDataNum; i++) {
  13796. + if (i <= (iChannelNum + 1)) {
  13797. + if (i == 0)
  13798. + FTS_TEST_PRINT("\n\n\nOffset %02d: %4d,\n", i, iAdcData[i]);
  13799. + else if (i == 1)
  13800. + FTS_TEST_PRINT("Ground %02d: %4d,\n", i, iAdcData[i]);
  13801. + else if (i <= (iMaxTx + 1))
  13802. + FTS_TEST_PRINT("Tx%02d: %4d, ", i-1, iAdcData[i]);
  13803. + else if (i <= (iChannelNum + 1))
  13804. + FTS_TEST_PRINT("Rx%02d: %4d, ", i - iMaxTx-1, iAdcData[i]);
  13805. + if (i % 10 == 0)
  13806. + FTS_TEST_PRINT("\n");
  13807. + } else {
  13808. + if (i == (iChannelNum + 2))
  13809. + FTS_TEST_PRINT("\n\n\nMultual %02d: %4d,\n", i, iAdcData[i]);
  13810. + else if (i <= (iMaxTx)+(iChannelNum + 2))
  13811. + FTS_TEST_PRINT("Tx%02d: %4d, ", i - (iChannelNum + 2), iAdcData[i]);
  13812. + else if (i < iAllAdcDataNum)
  13813. + FTS_TEST_PRINT("Rx%02d: %4d, ", i - iMaxTx - (iChannelNum + 2), iAdcData[i]);
  13814. + if (i % 10 == 0)
  13815. + FTS_TEST_PRINT("\n");
  13816. + }
  13817. + }
  13818. + FTS_TEST_PRINT("\r\n");
  13819. + FTS_TEST_DBG("");
  13820. +
  13821. + fMShortResistance = fts_malloc(iChannelNum*sizeof(int));
  13822. + memset(fMShortResistance, 0, iChannelNum);
  13823. + fGShortResistance = fts_malloc(iChannelNum*sizeof(int));
  13824. + memset(fGShortResistance, 0, iChannelNum);
  13825. +
  13826. + iMin_CG = pdata->imin_cg;
  13827. + iDoffset = iOffset - 1024;
  13828. + iDrefn = iClbData_Ground;
  13829. +
  13830. + FTS_TEST_DBG("Drefp:%5d \r\n", iDrefn);
  13831. + FTS_TEST_DBG("Doffset:%5d\r\n", iDoffset);
  13832. + FTS_TEST_DBG("Rshort(Ground):\n\n\n");
  13833. + fKcal = 1;
  13834. + FTS_TEST_DBG("Short Circuit (Channel and Ground):\r\n");
  13835. + for (i = 0; i < iChannelNum; i++) {
  13836. + iDsen = iAdcData[i+2];
  13837. + FTS_TEST_PRINT("%5d ", iDsen);
  13838. + if (i+1 == iMaxTx)
  13839. + FTS_TEST_PRINT("\n");
  13840. + if ((2047+iDoffset) - iDsen <= 0)
  13841. + continue;
  13842. + if (i == iMaxTx)
  13843. + FTS_TEST_PRINT("\n");
  13844. + if (IcValue <= 0x05 || IcValue == 0xff)
  13845. + fGShortResistance[i] = (iDsen - iDoffset + 410) * 25 * fKcal / (2047 + iDoffset - iDsen) - 3;
  13846. + else {
  13847. + if (iDrefn - iDsen <= 0) {
  13848. + fGShortResistance[i] = iMin_CG;
  13849. + FTS_TEST_PRINT("%02d ", fGShortResistance[i]);
  13850. + continue;
  13851. + }
  13852. + fGShortResistance[i] = (((iDsen - iDoffset + 384) / (iDrefn - iDsen) * 57) - 1);
  13853. + }
  13854. + if (fGShortResistance[i] < 0)
  13855. + fGShortResistance[i] = 0;
  13856. + FTS_TEST_PRINT("%02d ", fGShortResistance[i]);
  13857. + if ((iMin_CG > fGShortResistance[i]) || (iDsen - iDoffset < 0)) {
  13858. + iCount++;
  13859. + if (i+1 <= iMaxTx)
  13860. + FTS_TEST_PRINT("Tx%02d: %02d (k¦¸), ", i+1, fGShortResistance[i]);
  13861. + else
  13862. + FTS_TEST_PRINT("Rx%02d: %02d (k¦¸), ", i+1 - iMaxTx, fGShortResistance[i]);
  13863. + if (iCount % 10 == 0)
  13864. + FTS_TEST_PRINT("\n");
  13865. + }
  13866. + }
  13867. + FTS_TEST_PRINT("\n");
  13868. +
  13869. + if (iCount > 0)
  13870. + btmpresult = false;
  13871. + iMin_CC = pdata->imin_cc;
  13872. + if ((IcValue == 0x06 || IcValue < 0xff) && iRsen != iCCRsen)
  13873. + iRsen = iCCRsen;
  13874. + iDoffset = iOffset - 1024;
  13875. + iDrefn = iClbData_Mutual;
  13876. + fKcal = 1.0;
  13877. +
  13878. + FTS_TEST_DBG("\n\nShort Circuit (Channel and Channel):\n");
  13879. + iCount = 0;
  13880. +
  13881. +
  13882. + FTS_TEST_DBG("Drefp: %5d \r\n", iDrefn);
  13883. + FTS_TEST_DBG("Doffset: %5d \r\n", iDoffset);
  13884. + FTS_TEST_DBG("Rshort(Channel):");
  13885. + iDCal = max(iDrefn, 116 + iDoffset);
  13886. +
  13887. + for (i = 0; i < iChannelNum; i++) {
  13888. + iDsen = iAdcData[i+iChannelNum + 3];
  13889. +
  13890. + FTS_TEST_PRINT("%5d ", iDsen);
  13891. + if (i+1 == iMaxTx)
  13892. + FTS_TEST_PRINT("\n");
  13893. + if (IcValue <= 0x05 || IcValue == 0xff)
  13894. + if (iDsen - iDrefn < 0)
  13895. + continue;
  13896. +
  13897. + if (i == iMaxTx)
  13898. + FTS_TEST_PRINT("\n");
  13899. +
  13900. + if (IcValue <= 0x05 || IcValue == 0xff) {
  13901. + iMa = iDsen - iDCal;
  13902. + iMa = iMa ? iMa : 1;
  13903. + fMShortResistance[i] = ((2047 + iDoffset - iDCal) * 24 / iMa - 27) * fKcal - 6;
  13904. + } else {
  13905. + if (iDrefn - iDsen <= 0) {
  13906. + fMShortResistance[i] = iMin_CC;
  13907. + FTS_TEST_PRINT("%02d ", fMShortResistance[i]);
  13908. + continue;
  13909. + }
  13910. +
  13911. + fMShortResistance[i] = (iDsen - iDoffset - 123) * iRsen * fKcal / (iDrefn - iDsen) - 2;
  13912. + }
  13913. +
  13914. +
  13915. + FTS_TEST_PRINT("%02d ", fMShortResistance[i]);
  13916. +
  13917. + if (fMShortResistance[i] < 0 && fMShortResistance[i] >= -240)
  13918. + fMShortResistance[i] = 0;
  13919. + else if (fMShortResistance[i] < -240)
  13920. + continue;
  13921. +
  13922. + if (fMShortResistance[i] <= 0 || fMShortResistance[i] < iMin_CC) {
  13923. + iCount++;
  13924. + if (i+1 <= iMaxTx)
  13925. + FTS_TEST_PRINT("Tx%02d: %02d(k¦¸), ", i+1, fMShortResistance[i]);
  13926. + else
  13927. + FTS_TEST_PRINT("Rx%02d: %02d(k¦¸), ", i+1 - iMaxTx, fMShortResistance[i]);
  13928. + if (iCount % 10 == 0)
  13929. + FTS_TEST_PRINT("\n");
  13930. + }
  13931. + }
  13932. + FTS_TEST_PRINT("\n");
  13933. +
  13934. + if (iCount > 0 && !bCapShortTest)
  13935. + btmpresult = false;
  13936. +
  13937. + if (bCapShortTest && iCount)
  13938. + FTS_TEST_DBG(" bCapShortTest && iCount. need to add ......");
  13939. +
  13940. + if (m_bV3TP) {
  13941. + ReCode = WriteReg(REG_MAPPING_SWITCH, strSwitch);
  13942. + SysDelay(50);
  13943. + if (ReCode != ERROR_CODE_OK) {
  13944. + FTS_TEST_ERR("Failed to restore mapping type!\r\n");
  13945. + goto TEST_ERR;
  13946. + }
  13947. + ReCode = GetChannelNum();
  13948. + if (ReCode != ERROR_CODE_OK) {
  13949. + FTS_TEST_ERR("\nGetChannelNum error.Code: %d", ReCode);
  13950. + goto TEST_ERR;
  13951. + }
  13952. + ReCode = GetRawData();
  13953. + }
  13954. + if (NULL != iAdcData) {
  13955. + fts_free(iAdcData);
  13956. + iAdcData = NULL;
  13957. + }
  13958. +
  13959. + if (NULL != fMShortResistance) {
  13960. + fts_free(fMShortResistance);
  13961. + fMShortResistance = NULL;
  13962. + }
  13963. +
  13964. + if (NULL != fGShortResistance) {
  13965. + fts_free(fGShortResistance);
  13966. + fGShortResistance = NULL;
  13967. + }
  13968. + if (btmpresult) {
  13969. + FTS_TEST_DBG("\r\n\r\n//Weak Short Test is OK.");
  13970. + return RESULT_PASS;
  13971. + }
  13972. +
  13973. + FTS_TEST_DBG("\r\n\r\n//Weak Short Test is NG.");
  13974. + return RESULT_NG;
  13975. +
  13976. +TEST_ERR:
  13977. + if (NULL != iAdcData) {
  13978. + fts_free(iAdcData);
  13979. + iAdcData = NULL;
  13980. + }
  13981. + if (NULL != fMShortResistance) {
  13982. + fts_free(fMShortResistance);
  13983. + fMShortResistance = NULL;
  13984. + }
  13985. + if (NULL != fGShortResistance) {
  13986. + fts_free(fGShortResistance);
  13987. + fGShortResistance = NULL;
  13988. + }
  13989. + FTS_TEST_DBG("%s invalid\n\n\n\n", __func__);
  13990. + return RESULT_INVALID;
  13991. +}
  13992. +
  13993. +static unsigned char WeakShort_GetAdcData(int AllAdcDataLen, int *pRevBuffer)
  13994. +{
  13995. + unsigned char ReCode = ERROR_CODE_COMM_ERROR;
  13996. + int iReadDataLen = AllAdcDataLen;
  13997. + unsigned char *pDataSend = NULL;
  13998. + unsigned char Data = 0xff;
  13999. + int i = 0;
  14000. + bool bAdcOK = false;
  14001. +
  14002. + FTS_TEST_DBG("\n");
  14003. + pDataSend = fts_malloc(iReadDataLen + 1);
  14004. + if (pDataSend == NULL)
  14005. + return ERROR_CODE_ALLOCATE_BUFFER_ERROR;
  14006. + memset(pDataSend, 0, iReadDataLen + 1);
  14007. + ReCode = WriteReg(0x07, 0x01);
  14008. + if (ReCode != ERROR_CODE_OK) {
  14009. + FTS_TEST_DBG("WriteReg error.\n");
  14010. + return ReCode;
  14011. + }
  14012. + SysDelay(100);
  14013. + for (i = 0; i < 100*5; i++) {
  14014. + SysDelay(10);
  14015. + ReCode = ReadReg(0x07, &Data);
  14016. + if (ReCode == ERROR_CODE_OK)
  14017. + if (Data == 0) {
  14018. + bAdcOK = true;
  14019. + break;
  14020. + }
  14021. + }
  14022. + if (!bAdcOK) {
  14023. + FTS_TEST_ERR("ADC data NOT ready. error.\n");
  14024. + ReCode = ERROR_CODE_COMM_ERROR;
  14025. + goto EndGetAdc;
  14026. + }
  14027. + SysDelay(300);
  14028. + pDataSend[0] = 0xF4;
  14029. + ReCode = Comm_Base_IIC_IO(pDataSend, 1, pDataSend + 1, iReadDataLen);
  14030. + if (ReCode == ERROR_CODE_OK) {
  14031. + FTS_TEST_PRINT("\n Adc Data:\n");
  14032. + for (i = 0; i < iReadDataLen/2; i++) {
  14033. + pRevBuffer[i] = (pDataSend[1 + 2*i]<<8) + pDataSend[1 + 2*i + 1];
  14034. + FTS_TEST_PRINT("%d, ", pRevBuffer[i]);
  14035. + }
  14036. + FTS_TEST_PRINT("\n");
  14037. + } else
  14038. + FTS_TEST_DBG("Comm_Base_IIC_IO error. error:%d.\n", ReCode);
  14039. +EndGetAdc:
  14040. + if (pDataSend != NULL) {
  14041. + fts_free(pDataSend);
  14042. + pDataSend = NULL;
  14043. + }
  14044. + FTS_TEST_DBG(" END.\n");
  14045. + return ReCode;
  14046. +}
  14047. diff --git a/drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.h b/drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.h
  14048. new file mode 100644
  14049. index 0000000..245c4e6
  14050. --- /dev/null
  14051. +++ b/drivers/input/touchscreen/ft5x46/focaltech_test_ft5x46.h
  14052. @@ -0,0 +1,22 @@
  14053. +
  14054. +/************************************************************************
  14055. +* Copyright (C) 2012-2015, Focaltech Systems (R),All Rights Reserved.
  14056. +*
  14057. +* File Name: Test_FT8716.c
  14058. +*
  14059. +* Author: Software Development Team, AE
  14060. +*
  14061. +* Created: 2015-07-14
  14062. +*
  14063. +* Abstract: test item for FT8716
  14064. +*
  14065. +************************************************************************/
  14066. +#ifndef _TEST_FT8716_H
  14067. +#define _TEST_FT8716_H
  14068. +
  14069. +
  14070. +unsigned char FT5X46_TestItem_RawDataTest(struct i2c_client *client);
  14071. +unsigned char FT5X46_TestItem_WeakShortTest(struct i2c_client *client);
  14072. +
  14073. +
  14074. +#endif
  14075. diff --git a/drivers/input/touchscreen/ft5x46/ft5x46_ts.c b/drivers/input/touchscreen/ft5x46/ft5x46_ts.c
  14076. new file mode 100644
  14077. index 0000000..079d1a4
  14078. --- /dev/null
  14079. +++ b/drivers/input/touchscreen/ft5x46/ft5x46_ts.c
  14080. @@ -0,0 +1,3051 @@
  14081. +
  14082. +/* Copyright (C) 2017 XiaoMi, Inc.
  14083. + *
  14084. + * This software is licensed under the terms of the GNU General Public
  14085. + * License version 2, as published by the Free Software Foundation, and
  14086. + * may be copied, distributed, and modified under those terms.
  14087. + *
  14088. + * This program is distributed in the hope that it will be useful,
  14089. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14090. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14091. + * GNU General Public License for more details.
  14092. + *
  14093. + */
  14094. +
  14095. +#include <linux/input/ft5x46_ts.h>
  14096. +
  14097. +#define FT5X46_DEBUG_PERMISSION
  14098. +#define FT5X46_APK_DEBUG_CHANNEL
  14099. +
  14100. +#define FT5X0X_REG_DEVIDE_MODE 0x00
  14101. +#define FT5X0X_REG_ROW_ADDR 0x01
  14102. +#define FT5X0X_REG_TD_STATUS 0x02
  14103. +#define FT5X0X_REG_START_SCAN 0x02
  14104. +#define FT5X0X_REG_TOUCH_START 0x03
  14105. +#define FT5X0X_REG_VOLTAGE 0x05
  14106. +#define FT5X0X_REG_CHIP_ID 0xA3
  14107. +#define FT5X0X_ID_G_PMODE 0xA5
  14108. +#define FT5X0X_REG_FW_VER 0xA6
  14109. +#define FT5X0X_ID_G_FT5201ID 0xA8
  14110. +#define FT5X0X_NOISE_FILTER 0x8B
  14111. +#define FT5X0X_REG_POINT_RATE 0x88
  14112. +#define FT5X0X_REG_THGROUP 0x80
  14113. +#define FT5X0X_REG_RESET 0xFC
  14114. +
  14115. +#define FT5X0X_DEVICE_MODE_NORMAL 0x00
  14116. +#define FT5X0X_DEVICE_MODE_TEST 0x40
  14117. +#define FT5X0X_DEVICE_START_CALIB 0x04
  14118. +#define FT5X0X_DEVICE_SAVE_RESULT 0x05
  14119. +
  14120. +#define FT5X0X_POWER_ACTIVE 0x00
  14121. +#define FT5X0X_POWER_MONITOR 0x01
  14122. +#define FT5X0X_POWER_HIBERNATE 0x03
  14123. +
  14124. +#define FT5X0X_REG_CONFIG_INFO 0x92
  14125. +
  14126. +#define FT5X0X_TOUCH_LENGTH 6
  14127. +
  14128. +#define FT5X0X_TOUCH_XH 0x00
  14129. +#define FT5X0X_TOUCH_XL 0x01
  14130. +#define FT5X0X_TOUCH_YH 0x02
  14131. +#define FT5X0X_TOUCH_YL 0x03
  14132. +#define FT5X0X_TOUCH_PRESSURE 0x04
  14133. +#define FT5X0X_TOUCH_SIZE 0x05
  14134. +
  14135. +#define FT5X46_MAX_ID 0x0F
  14136. +#define FT5X46_TOUCH_LENGTH 6
  14137. +#define FT5X46_XH_POS 3
  14138. +#define FT5X46_XL_POS 4
  14139. +#define FT5X46_YH_POS 5
  14140. +#define FT5X46_YL_POS 6
  14141. +#define FT5X46_XY_POS 7
  14142. +#define FT5X46_EVENT_POS 3
  14143. +#define FT5X46_ID_POS 5
  14144. +
  14145. +#define FT5X46_DEF_PRESSURE 8
  14146. +
  14147. +#define FT5X0X_MODE_NORMAL 0x00
  14148. +#define FT5X0X_MODE_SYSINFO 0x10
  14149. +#define FT5X0X_MODE_TEST 0x40
  14150. +#define FT5X0X_MODE_MASK 0x70
  14151. +
  14152. +#define FT5X0X_EVENT_DOWN 0x00
  14153. +#define FT5X0X_EVENT_UP 0x40
  14154. +#define FT5X0X_EVENT_CONTACT 0x80
  14155. +#define FT5X0X_EVENT_MASK 0xc0
  14156. +
  14157. +
  14158. +#define FT5X0X_FIRMWARE_TAIL (-8)
  14159. +#define FT5X0X_FIRMWARE_VERION (-2)
  14160. +#define FT5X46_RD_FLASH_PACKET_SIZE 4
  14161. +#define FT5X0X_PACKET_HEADER 6
  14162. +#define FT5X0X_PACKET_LENGTH 128
  14163. +
  14164. +#define FT5X0X_MAX_PRESSURE 0xff
  14165. +#define FT5X46_PRESSURE 8
  14166. +
  14167. +#define FT5X46_POINT_READ_BUF (3 + FT5X46_TOUCH_LENGTH * FT5X0X_MAX_FINGER)
  14168. +
  14169. +#define NOISE_FILTER_DELAY HZ
  14170. +
  14171. +#define FT_VTG_MIN_UV 2600000
  14172. +#define FT_VTG_MAX_UV 3300000
  14173. +#define FT_I2C_VTG_MIN_UV 1800000
  14174. +#define FT_I2C_VTG_MAX_UV 1800000
  14175. +
  14176. +#define FT5316_UPGRADE_AA_DELAY 50
  14177. +#define FT5316_UPGRADE_55_DELAY 40
  14178. +#define FT5316_UPGRADE_ID_1 0x79
  14179. +#define FT5316_UPGRADE_ID_2 0x07
  14180. +#define FT5316_UPGRADE_READID_DELAY 1
  14181. +
  14182. +#define FT5X36_UPGRADE_AA_DELAY 30
  14183. +#define FT5X36_UPGRADE_55_DELAY 30
  14184. +#define FT5X36_UPGRADE_ID_1 0x79
  14185. +#define FT5X36_UPGRADE_ID_2 0x11
  14186. +#define FT5X36_UPGRADE_READID_DELAY 10
  14187. +
  14188. +#define FT5X46_UPGRADE_AA_DELAY 2
  14189. +#define FT5X46_UPGRADE_55_DELAY 2
  14190. +#define FT5X46_UPGRADE_ID_1 0x54
  14191. +#define FT5X46_UPGRADE_ID_2 0x2C
  14192. +#define FT5X46_UPGRADE_READID_DELAY 20
  14193. +
  14194. +
  14195. +#define FT5316_CHIP_ID 0x0A
  14196. +#define FT5X36_CHIP_ID 0x14
  14197. +#define FT5X46_CHIP_ID 0x54
  14198. +
  14199. +#define FT5316_PROJ_ID "FTS0000x000"
  14200. +#define FT5X36_PROJ_ID "FTS0000P000"
  14201. +
  14202. +#define FT5X0X_UPGRADE_LOOP 3
  14203. +
  14204. +#define BL_VERSION_LZ4 0
  14205. +#define BL_VERSION_Z7 1
  14206. +#define BL_VERSION_GZF 2
  14207. +
  14208. +
  14209. +#ifdef FT5X46_APK_DEBUG_CHANNEL
  14210. +#define FT5X46_PROC_NAME "ftxxxx-debug"
  14211. +
  14212. +#define FT5X46_PROC_UPGRADE 0
  14213. +#define FT5X46_PROC_READ_REGISTER 1
  14214. +#define FT5X46_PROC_WRITE_REGISTER 2
  14215. +#define FT5X46_PROC_AUTOCLB 4
  14216. +#define FT5X46_PROC_UPGRADE_INFO 5
  14217. +#define FT5X46_PROC_WRITE_DATA 6
  14218. +#define FT5X46_PROC_READ_DATA 7
  14219. +
  14220. +#define FT5X46_GESTURE_POINTS_HEADER 8
  14221. +#define FT5X46_GESTURE_UP 0x22
  14222. +#define FT5X46_GESTURE_DBLCLICK 0x24
  14223. +
  14224. +#define FT5X46_INPUT_EVENT_START 0
  14225. +#define FT5X46_INPUT_EVENT_SENSITIVE_MODE_OFF 0
  14226. +#define FT5X46_INPUT_EVENT_SENSITIVE_MODE_ON 1
  14227. +#define FT5X46_INPUT_EVENT_STYLUS_MODE_OFF 2
  14228. +#define FT5X46_INPUT_EVENT_STYLUS_MODE_ON 3
  14229. +#define FT5X46_INPUT_EVENT_WAKUP_MODE_OFF 4
  14230. +#define FT5X46_INPUT_EVENT_WAKUP_MODE_ON 5
  14231. +#define FT5X46_INPUT_EVENT_COVER_MODE_OFF 6
  14232. +#define FT5X46_INPUT_EVENT_COVER_MODE_ON 7
  14233. +#define FT5X46_INPUT_EVENT_END 7
  14234. +
  14235. +#define FT5X46_COVER_REG 0xc1
  14236. +
  14237. +static unsigned char proc_operate_mode = FT5X46_PROC_UPGRADE;
  14238. +static struct proc_dir_entry *ft5x46_proc_entry;
  14239. +#endif
  14240. +
  14241. +struct ft5x46_packet {
  14242. + u8 magic1;
  14243. + u8 magic2;
  14244. + u16 offset;
  14245. + u16 length;
  14246. + u8 payload[FT5X0X_PACKET_LENGTH];
  14247. +};
  14248. +
  14249. +struct ft5x46_rd_flash_packet {
  14250. + u8 magic;
  14251. + u8 addr_h;
  14252. + u8 addr_m;
  14253. + u8 addr_l;
  14254. +};
  14255. +
  14256. +struct ft5x46_finger {
  14257. + int x, y;
  14258. + int size;
  14259. + int pressure;
  14260. + bool detect;
  14261. +};
  14262. +struct ft5x46_mode_switch {
  14263. + struct ft5x46_data *data;
  14264. + u8 mode;
  14265. + struct work_struct switch_mode_work;
  14266. +};
  14267. +
  14268. +static void ft5x46_cover_mode(struct ft5x46_data *ft5x46, bool enable);
  14269. +
  14270. +struct ft5x46_data *ft_data;
  14271. +
  14272. +static int ft5x46_recv_byte(struct ft5x46_data *ft5x46, u8 len, ...)
  14273. +{
  14274. + int error;
  14275. + va_list varg;
  14276. + u8 i, buf[len];
  14277. +
  14278. + error = ft5x46->bops->recv(ft5x46->dev, buf, len);
  14279. + if (error)
  14280. + return error;
  14281. +
  14282. + va_start(varg, len);
  14283. + for (i = 0; i < len; i++)
  14284. + *va_arg(varg, u8 *) = buf[i];
  14285. + va_end(varg);
  14286. +
  14287. + return 0;
  14288. +}
  14289. +
  14290. +static int ft5x46_send_block(struct ft5x46_data *ft5x46,
  14291. + const void *buf, int len)
  14292. +{
  14293. + return ft5x46->bops->send(ft5x46->dev, buf, len);
  14294. +}
  14295. +
  14296. +static int ft5x46_recv_block(struct ft5x46_data *ft5x46,
  14297. + void *buf, int len)
  14298. +{
  14299. + return ft5x46->bops->recv(ft5x46->dev, buf, len);
  14300. +}
  14301. +
  14302. +static int ft5x46_send_byte(struct ft5x46_data *ft5x46, u8 len, ...)
  14303. +{
  14304. + va_list varg;
  14305. + u8 i, buf[len];
  14306. +
  14307. + va_start(varg, len);
  14308. + for (i = 0; i < len; i++)
  14309. + buf[i] = va_arg(varg, int);
  14310. + va_end(varg);
  14311. +
  14312. + return ft5x46_send_block(ft5x46, buf, len);
  14313. +}
  14314. +
  14315. +static int ft5x46_read_block(struct ft5x46_data *ft5x46,
  14316. + u8 addr, void *buf, u8 len)
  14317. +{
  14318. + return ft5x46->bops->read(ft5x46->dev, addr, buf, len);
  14319. +}
  14320. +
  14321. +static int ft5x46_read_byte(struct ft5x46_data *ft5x46, u8 addr, u8 *data)
  14322. +{
  14323. + return ft5x46_read_block(ft5x46, addr, data, sizeof(*data));
  14324. +}
  14325. +
  14326. +static int ft5x46_write_byte(struct ft5x46_data *ft5x46, u8 addr, u8 data)
  14327. +{
  14328. + return ft5x46->bops->write(ft5x46->dev, addr, &data, sizeof(data));
  14329. +}
  14330. +
  14331. +static void ft5x46_charger_state_changed(struct ft5x46_data *ft5x46, bool force_update)
  14332. +{
  14333. + u8 is_usb_exist;
  14334. +
  14335. + is_usb_exist = power_supply_is_system_supplied();
  14336. + if ((is_usb_exist != ft5x46->is_usb_plug_in) || (force_update)) {
  14337. + ft5x46->is_usb_plug_in = is_usb_exist;
  14338. + dev_info(ft5x46->dev, "Power state changed, set noise filter to 0x%x\n", is_usb_exist);
  14339. + mutex_lock(&ft5x46->mutex);
  14340. + ft5x46_write_byte(ft5x46, FT5X0X_NOISE_FILTER, is_usb_exist);
  14341. + mutex_unlock(&ft5x46->mutex);
  14342. + }
  14343. +}
  14344. +
  14345. +static void ft5x46_noise_filter_delayed_work(struct work_struct *work)
  14346. +{
  14347. + struct delayed_work *delayed_work = to_delayed_work(work);
  14348. + struct ft5x46_data *ft5x46 = container_of(delayed_work, struct ft5x46_data, noise_filter_delayed_work);
  14349. +
  14350. + dev_info(ft5x46->dev, "ft5x46_noise_filter_delayed_work called\n");
  14351. + ft5x46_charger_state_changed(ft5x46, true);
  14352. +}
  14353. +
  14354. +static void ft5x46_disable_irq(struct ft5x46_data *ft5x46)
  14355. +{
  14356. + if (likely(ft5x46->irq_enabled)) {
  14357. + disable_irq(ft5x46->irq);
  14358. + ft5x46->irq_enabled = false;
  14359. + }
  14360. +}
  14361. +
  14362. +static void ft5x46_enable_irq(struct ft5x46_data *ft5x46)
  14363. +{
  14364. + if (likely(!ft5x46->irq_enabled)) {
  14365. + enable_irq(ft5x46->irq);
  14366. + ft5x46->irq_enabled = true;
  14367. + }
  14368. +}
  14369. +
  14370. +#ifdef CONFIG_TOUCHSCREEN_FT5X46_CALIBRATE
  14371. +static int ft5x46_auto_calib(struct ft5x46_data *ft5x46)
  14372. +{
  14373. + int error;
  14374. + u8 val1;
  14375. + int i;
  14376. + msleep(200);
  14377. + error = ft5x46_write_byte(ft5x46,
  14378. + FT5X0X_REG_DEVIDE_MODE, FT5X0X_DEVICE_MODE_TEST);
  14379. + if (error)
  14380. + return error;
  14381. + msleep(100);
  14382. +
  14383. + error = ft5x46_write_byte(ft5x46,
  14384. + FT5X0X_REG_START_SCAN, FT5X0X_DEVICE_START_CALIB);
  14385. + if (error)
  14386. + return error;
  14387. + msleep(300);
  14388. +
  14389. + for (i = 0; i < 100; i++) {
  14390. + error = ft5x46_read_byte(ft5x46, FT5X0X_REG_DEVIDE_MODE, &val1);
  14391. + if (error)
  14392. + return error;
  14393. + if (((val1 & 0x70) >> 4) == 0)
  14394. + break;
  14395. + msleep(200);
  14396. + }
  14397. + dev_info(ft5x46->dev, "[FTS] calibration OK.\n");
  14398. +
  14399. + msleep(300);
  14400. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_DEVIDE_MODE, FT5X0X_DEVICE_MODE_TEST);
  14401. + if (error)
  14402. + return error;
  14403. + msleep(100);
  14404. +
  14405. + error = ft5x46_write_byte(ft5x46,
  14406. + FT5X0X_REG_START_SCAN, FT5X0X_DEVICE_SAVE_RESULT);
  14407. + if (error)
  14408. + return error;
  14409. + msleep(300);
  14410. +
  14411. + error = ft5x46_write_byte(ft5x46,
  14412. + FT5X0X_REG_DEVIDE_MODE, FT5X0X_DEVICE_MODE_NORMAL);
  14413. + if (error)
  14414. + return error;
  14415. + msleep(300);
  14416. + dev_info(ft5x46->dev, "[FTS] Save calib result OK.\n");
  14417. +
  14418. + return 0;
  14419. +}
  14420. +#endif
  14421. +
  14422. +static u8 reset_delay[] = {
  14423. + 30, 33, 36, 39, 42, 45, 27, 24, 11, 18, 15
  14424. +};
  14425. +
  14426. +static int ft5x46_hid_to_std_i2c(struct ft5x46_data *ft5x46)
  14427. +{
  14428. + int error;
  14429. + u8 val1, val2, val3;
  14430. +
  14431. + error = ft5x46_send_byte(ft5x46, 3, 0xEB, 0xAA, 0x09);
  14432. + if (error) {
  14433. + dev_err(ft5x46->dev, "Failed to send EB AA 09\n");
  14434. + return error;
  14435. + }
  14436. +
  14437. + msleep(10);
  14438. + error = ft5x46_recv_byte(ft5x46, 3, &val1, &val2, &val3);
  14439. + if (error) {
  14440. + dev_err(ft5x46->dev, "Failed to receive device id\n");
  14441. + return error;
  14442. + }
  14443. +
  14444. + dev_dbg(ft5x46->dev, "Changed to STDI2C Value: REG1 = 0x%02x, REG2 = 0x%02x, REG3 = 0x%02x\n",
  14445. + val1, val2, val3);
  14446. +
  14447. + if (val1 == 0xEB && val2 == 0xAA && val3 == 0x08) {
  14448. + dev_info(ft5x46->dev, "HidI2c To StdI2c succeed\n");
  14449. + return 0;
  14450. + } else {
  14451. + dev_err(ft5x46->dev, "HidI2c To StdI2c failed\n");
  14452. + return -ENODEV;
  14453. + }
  14454. +}
  14455. +
  14456. +static u8 ft5x46_get_factory_id(struct ft5x46_data *ft5x46)
  14457. +{
  14458. + int error = 0;
  14459. + int i, j;
  14460. + u8 val1, val2;
  14461. + struct ft5x46_rd_flash_packet packet;
  14462. + u8 vid;
  14463. +
  14464. + for (i = 0, error = -1; i < sizeof(reset_delay) && error; i++) {
  14465. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0xaa);
  14466. + if (error)
  14467. + continue;
  14468. + msleep(50);
  14469. +
  14470. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0x55);
  14471. + if (error)
  14472. + continue;
  14473. + msleep(200);
  14474. + dev_info(ft5x46->dev, "[FTS] step1: Reset device.\n");
  14475. +
  14476. + if (ft5x46->chip_id != FT5316_CHIP_ID) {
  14477. + error = ft5x46_hid_to_std_i2c(ft5x46);
  14478. + if (error) {
  14479. + dev_err(ft5x46->dev, "HidI2c change to StdI2c fail!\n");
  14480. + }
  14481. + }
  14482. + for (j = 0; j < 10; j++) {
  14483. + error = ft5x46_send_byte(ft5x46, 2, 0x55, 0xaa);
  14484. + msleep(5);
  14485. + if (!error)
  14486. + break;
  14487. + }
  14488. + if (error)
  14489. + continue;
  14490. +
  14491. + dev_info(ft5x46->dev, "[FTS] step2: Enter upgrade mode.\n");
  14492. +
  14493. + error = ft5x46_send_byte(ft5x46, 4, 0x90, 0x00, 0x00, 0x00);
  14494. + if (error) {
  14495. + dev_err(ft5x46->dev, "Failed to send 90 00 00 00\n");
  14496. + continue;
  14497. + }
  14498. +
  14499. + error = ft5x46_recv_byte(ft5x46, 2, &val1, &val2);
  14500. + if (error) {
  14501. + dev_err(ft5x46->dev, "Failed to receive device id\n");
  14502. + continue;
  14503. + }
  14504. +
  14505. + dev_info(ft5x46->dev, "read id = 0x%x, 0x%x\n", val1, val2);
  14506. +
  14507. + dev_info(ft5x46->dev, "[FTS] step3: Check device id.\n");
  14508. +
  14509. + if (val1 == FT5316_UPGRADE_ID_1 && val2 == FT5316_UPGRADE_ID_2) {
  14510. + ft5x46->chip_id = FT5316_CHIP_ID;
  14511. + break;
  14512. + } else if (val1 == FT5X36_UPGRADE_ID_1 && val2 == FT5X36_UPGRADE_ID_2) {
  14513. + ft5x46->chip_id = FT5X36_CHIP_ID;
  14514. + break;
  14515. + } else if (val1 == FT5X46_UPGRADE_ID_1 && val2 == FT5X46_UPGRADE_ID_2) {
  14516. + ft5x46->chip_id = FT5X46_CHIP_ID;
  14517. + break;
  14518. + }
  14519. + }
  14520. +
  14521. + if (error)
  14522. + return error;
  14523. +
  14524. + packet.magic = 0x03;
  14525. + packet.addr_h = 0x00;
  14526. + packet.addr_m = 0xD7;
  14527. + packet.addr_l = 0x84;
  14528. +
  14529. + error = ft5x46_send_block(ft5x46, &packet, FT5X46_RD_FLASH_PACKET_SIZE);
  14530. + if (error)
  14531. + return error;
  14532. + msleep(5);
  14533. +
  14534. + error = ft5x46_recv_byte(ft5x46, 1, &vid);
  14535. + if (error)
  14536. + return error;
  14537. +
  14538. + error = ft5x46_send_byte(ft5x46, 1, 0x07);
  14539. + if (error)
  14540. + return error;
  14541. + msleep(200);
  14542. +
  14543. + return vid;
  14544. +}
  14545. +
  14546. +static void ft5x46_wait_for_ready(struct ft5x46_data *ft5x46,
  14547. + u8 val1, u8 val2, int try_times, int delay_ms)
  14548. +{
  14549. + int i;
  14550. + int error;
  14551. + u8 recv1, recv2;
  14552. + for (i = 0; i < try_times; i++) {
  14553. + error = ft5x46_send_byte(ft5x46, 1, 0x6A);
  14554. + if (error) {
  14555. + dev_err(ft5x46->dev, "write failed\n");
  14556. + return;
  14557. + }
  14558. +
  14559. + error = ft5x46_recv_byte(ft5x46, 2, &recv1, &recv2);
  14560. + if (!error && recv1 == val1 && recv2 == val2) {
  14561. + dev_dbg(ft5x46->dev, "Ready: 0x%02x 0x%02x\n", val1, val2);
  14562. + break;
  14563. + }
  14564. + msleep(delay_ms);
  14565. + }
  14566. +
  14567. + if (i == try_times) {
  14568. + dev_err(ft5x46->dev, "Wait timeout and recv error 0x%02x 0x%02x(0x%02x 0x%02x)\n",
  14569. + recv1, recv2, val1, val2);
  14570. + }
  14571. +}
  14572. +
  14573. +int ft5x06_load_firmware(struct ft5x46_data *ft5x46,
  14574. + struct ft5x46_firmware_data *firmware, bool *upgraded)
  14575. +{
  14576. + int i, j, error = 0;
  14577. + u8 val1, val2, vid, bt_ecc, id;
  14578. + u32 temp;
  14579. + u32 lenght;
  14580. + const struct firmware *fw;
  14581. + int packet_number;
  14582. + u32 dw_lenth;
  14583. + u8 packet_buf[FT5X0X_PACKET_LENGTH + 6];
  14584. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  14585. + struct ft5x46_upgrade_info *ui = &pdata->ui;
  14586. +
  14587. + if (upgraded)
  14588. + *upgraded = false;
  14589. +
  14590. + if (firmware == NULL)
  14591. + return 0;
  14592. + error = ft5x46_read_byte(ft5x46, FT5X0X_ID_G_FT5201ID, &vid);
  14593. + if (error)
  14594. + return error;
  14595. +
  14596. + dev_info(ft5x46->dev, "firmware vendor is %02x\n", vid);
  14597. +
  14598. + id = vid;
  14599. + if (vid == FT5X0X_ID_G_FT5201ID ||
  14600. + vid == 0 || ft5x46->chip_id == 0) {
  14601. + vid = ft5x46_get_factory_id(ft5x46);
  14602. + dev_err(ft5x46->dev, "firmware corruption, read real factory id = 0x%x!\n", vid);
  14603. + }
  14604. +
  14605. + for (i = 0; i < pdata->cfg_size; i++, firmware++) {
  14606. + if (vid == firmware->vendor) {
  14607. + if (ft5x46->dev->of_node)
  14608. + if (ft5x46->chip_id == firmware->chip) {
  14609. + dev_info(ft5x46->dev, "chip id = 0x%x, found it!\n",
  14610. + ft5x46->chip_id);
  14611. + ft5x46->current_index = i;
  14612. + break;
  14613. + } else
  14614. + continue;
  14615. + else
  14616. + break;
  14617. + }
  14618. + }
  14619. +
  14620. + if (!ft5x46->dev->of_node && firmware->size == 0) {
  14621. + dev_err(ft5x46->dev, "unknown touch screen vendor, failed!\n");
  14622. + return -ENOENT;
  14623. + } else if (ft5x46->dev->of_node && (i == pdata->cfg_size)) {
  14624. + dev_err(ft5x46->dev, "Failed to find matched config!\n");
  14625. + ft5x46->current_index = 0;
  14626. + firmware->fwname = "ft5216_biel.fw";
  14627. + }
  14628. +
  14629. + if (firmware->size == 0 && ft5x46->dev->of_node) {
  14630. + dev_info(ft5x46->dev, "firmware name = %s\n", firmware->fwname);
  14631. + error = request_firmware(&fw, firmware->fwname, ft5x46->dev);
  14632. + if (!error) {
  14633. + firmware->data = kmalloc((int)fw->size, GFP_KERNEL);
  14634. + if (!firmware->data) {
  14635. + dev_err(ft5x46->dev, "Failed to allocate firmware!\n");
  14636. + return -ENOMEM;
  14637. + } else {
  14638. + memcpy(firmware->data, fw->data, (int)fw->size);
  14639. + firmware->size = (int)fw->size;
  14640. + }
  14641. + release_firmware(fw);
  14642. + } else {
  14643. + dev_err(ft5x46->dev, "Cannot find firmware %s\n", firmware->fwname);
  14644. + return -ENODEV;
  14645. + }
  14646. + }
  14647. +
  14648. +
  14649. + error = ft5x46_read_byte(ft5x46, FT5X0X_REG_FW_VER, &id);
  14650. + if (error)
  14651. + return error;
  14652. + dev_info(ft5x46->dev, "firmware version is %02x\n", id);
  14653. +
  14654. + if (id == firmware->data[firmware->size + FT5X0X_FIRMWARE_VERION])
  14655. + return 0;
  14656. + dev_info(ft5x46->dev, "upgrade firmware to %02x\n",
  14657. + firmware->data[firmware->size + FT5X0X_FIRMWARE_VERION]);
  14658. + dev_info(ft5x46->dev, "[FTS] step1: check fw id\n");
  14659. +
  14660. + for (i = 0, error = -1; i < sizeof(reset_delay) && error; i++) {
  14661. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0xaa);
  14662. + if (error)
  14663. + continue;
  14664. + msleep(ui->delay_aa);
  14665. +
  14666. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0x55);
  14667. + msleep(ui->delay_55);
  14668. + if (error)
  14669. + continue;
  14670. + msleep(reset_delay[i]);
  14671. + dev_info(ft5x46->dev, "[FTS] step2: Reset device.\n");
  14672. + msleep(10);
  14673. +
  14674. + for (j = 0; j < 10; j++) {
  14675. + error = ft5x46_send_byte(ft5x46, 2, 0x55, 0xaa);
  14676. + msleep(5);
  14677. + if (!error)
  14678. + break;
  14679. + }
  14680. + if (error)
  14681. + continue;
  14682. +
  14683. + dev_info(ft5x46->dev, "[FTS] step3: Enter upgrade mode.\n");
  14684. +
  14685. + error = ft5x46_send_byte(ft5x46, 4, 0x90, 0x00, 0x00, 0x00);
  14686. + if (error) {
  14687. + dev_err(ft5x46->dev, "Failed to send 90 00 00 00\n");
  14688. + continue;
  14689. + }
  14690. +
  14691. + error = ft5x46_recv_byte(ft5x46, 2, &val1, &val2);
  14692. + if (error) {
  14693. + dev_err(ft5x46->dev, "Failed to receive device id\n");
  14694. + continue;
  14695. + }
  14696. +
  14697. + dev_info(ft5x46->dev, "read id = 0x%x, 0x%x, id = 0x%x, 0x%x\n", val1, val2,
  14698. + ui->upgrade_id_1, ui->upgrade_id_2);
  14699. + if (val1 != ui->upgrade_id_1 || val2 != ui->upgrade_id_2)
  14700. + error = -ENODEV;
  14701. +
  14702. + dev_info(ft5x46->dev, "[FTS] step4: Check device id.\n");
  14703. + }
  14704. +
  14705. + if (error)
  14706. + return error;
  14707. +
  14708. + error = ft5x46_send_byte(ft5x46, 1, 0xcd);
  14709. + if (error)
  14710. + return error;
  14711. + error = ft5x46_recv_byte(ft5x46, 1, &val1);
  14712. + if (error)
  14713. + return error;
  14714. + dev_info(ft5x46->dev, "[FTS] bootloader version is 0x%x\n", val1);
  14715. +
  14716. + dev_info(ft5x46->dev, "[FTS] step5: Erase device.\n");
  14717. + error = ft5x46_send_byte(ft5x46, 1, 0x61);
  14718. + if (error)
  14719. + return error;
  14720. + msleep(ui->delay_erase);
  14721. + error = ft5x46_send_byte(ft5x46, 1, 0x63);
  14722. + if (error)
  14723. + return error;
  14724. + msleep(100);
  14725. +
  14726. + /*********Step 5:write firmware(FW) to ctpm flash*********/
  14727. + bt_ecc = 0;
  14728. +
  14729. + dw_lenth = firmware->size - 8;
  14730. + packet_number = (dw_lenth) / FT5X0X_PACKET_LENGTH;
  14731. + packet_buf[0] = 0xBF;
  14732. + packet_buf[1] = 0x00;
  14733. + for (j = 0; j < packet_number; j++) {
  14734. + temp = j * FT5X0X_PACKET_LENGTH;
  14735. + packet_buf[2] = (u8) (temp >> 8);
  14736. + packet_buf[3] = (u8) temp;
  14737. + lenght = FT5X0X_PACKET_LENGTH;
  14738. + packet_buf[4] = (u8) (lenght >> 8);
  14739. + packet_buf[5] = (u8) lenght;
  14740. + for (i = 0; i < FT5X0X_PACKET_LENGTH; i++) {
  14741. + packet_buf[6 + i] = firmware->data[j * FT5X0X_PACKET_LENGTH + i];
  14742. + bt_ecc ^= packet_buf[6 + i];
  14743. + }
  14744. + ft5x46_send_block(ft5x46, packet_buf, FT5X0X_PACKET_LENGTH + 6);
  14745. + msleep(FT5X0X_PACKET_LENGTH / 6 + 1);
  14746. + }
  14747. + if ((dw_lenth) % FT5X0X_PACKET_LENGTH > 0) {
  14748. + temp = packet_number * FT5X0X_PACKET_LENGTH;
  14749. + packet_buf[2] = (u8) (temp >> 8);
  14750. + packet_buf[3] = (u8) temp;
  14751. + temp = (dw_lenth) % FT5X0X_PACKET_LENGTH;
  14752. + packet_buf[4] = (u8) (temp >> 8);
  14753. + packet_buf[5] = (u8) temp;
  14754. + for (i = 0; i < temp; i++) {
  14755. + packet_buf[6 + i] = firmware->data[packet_number * FT5X0X_PACKET_LENGTH + i];
  14756. + bt_ecc ^= packet_buf[6 + i];
  14757. + }
  14758. +
  14759. + ft5x46_send_block(ft5x46, packet_buf, temp + 6);
  14760. + msleep(20);
  14761. + }
  14762. + /*send the last six byte */
  14763. + for (i = 0; i < 6; i++) {
  14764. + temp = 0x6ffa + i;
  14765. + packet_buf[2] = (u8) (temp >> 8);
  14766. + packet_buf[3] = (u8) temp;
  14767. + temp = 1;
  14768. + packet_buf[4] = (u8) (temp >> 8);
  14769. + packet_buf[5] = (u8) temp;
  14770. + packet_buf[6] = firmware->data[dw_lenth + i];
  14771. + bt_ecc ^= packet_buf[6];
  14772. + ft5x46_send_block(ft5x46, packet_buf, 7);
  14773. + msleep(20);
  14774. + }
  14775. +
  14776. + /*********Step 6: read out checksum***********************/
  14777. + /*send the opration head */
  14778. + dev_info(ft5x46->dev, "Step 6: read out checksum\n");
  14779. + error = ft5x46_read_byte(ft5x46, 0xcc, &val1);
  14780. + if (val1 != bt_ecc) {
  14781. + dev_err(ft5x46->dev, "--ecc error! FW=%02x bt_ecc=%02x\n",
  14782. + val1, bt_ecc);
  14783. + return -EIO;
  14784. + }
  14785. + /*********Step 7: reset the new FW***********************/
  14786. + dev_info(ft5x46->dev, "Step 7: reset the new FW\n");
  14787. + error = ft5x46_send_byte(ft5x46, 1, 0x07);
  14788. + msleep(300);
  14789. + if (upgraded)
  14790. + *upgraded = true;
  14791. +
  14792. + return 0;
  14793. +}
  14794. +
  14795. +static int ft5x46_load_firmware(struct ft5x46_data *ft5x46,
  14796. + struct ft5x46_firmware_data *firmware, bool *upgraded)
  14797. +{
  14798. + struct ft5x46_packet packet;
  14799. + int i, j, length, error = 0;
  14800. + u8 val1, val2, vid, ecc = 0, id;
  14801. +#ifdef CONFIG_TOUCHSCREEN_FT5X46_CALIBRATE
  14802. + const int max_calib_time = 3;
  14803. + bool calib_ok = false;
  14804. +#endif
  14805. + bool is_5336_fwsize_30 = false;
  14806. + const struct firmware *fw;
  14807. + int packet_num;
  14808. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  14809. + struct ft5x46_upgrade_info *ui = &pdata->ui;
  14810. +
  14811. + /* step 0a: check and init argument */
  14812. + if (upgraded)
  14813. + *upgraded = false;
  14814. +
  14815. + if (firmware == NULL)
  14816. + return 0;
  14817. +
  14818. + error = ft5x46_hid_to_std_i2c(ft5x46);
  14819. + if (error) {
  14820. + dev_err(ft5x46->dev, "HidI2c change to StdI2c fail!\n");
  14821. + }
  14822. +
  14823. + /* step 0b: find the right firmware for touch screen */
  14824. + error = ft5x46_read_byte(ft5x46, FT5X0X_ID_G_FT5201ID, &vid);
  14825. + if (error)
  14826. + return error;
  14827. +
  14828. + dev_info(ft5x46->dev, "firmware vendor is %02x\n", vid);
  14829. +
  14830. + id = vid;
  14831. + if (vid == FT5X0X_ID_G_FT5201ID ||
  14832. + vid == 0 || ft5x46->chip_id == 0) {
  14833. + vid = ft5x46_get_factory_id(ft5x46);
  14834. + dev_err(ft5x46->dev, "firmware corruption, read real factory id = 0x%x!\n", vid);
  14835. + }
  14836. +
  14837. + for (i = 0; i < pdata->cfg_size; i++, firmware++) {
  14838. + if (vid == firmware->vendor) {
  14839. + if (ft5x46->dev->of_node)
  14840. + if (ft5x46->chip_id == firmware->chip) {
  14841. + dev_info(ft5x46->dev, "chip id = 0x%x, found it!\n",
  14842. + ft5x46->chip_id);
  14843. + ft5x46->current_index = i;
  14844. + break;
  14845. + } else
  14846. + continue;
  14847. + else
  14848. + break;
  14849. + }
  14850. + }
  14851. +
  14852. + if (!ft5x46->dev->of_node && firmware->size == 0) {
  14853. + dev_err(ft5x46->dev, "unknown touch screen vendor, failed!\n");
  14854. + return -ENOENT;
  14855. + } else if (ft5x46->dev->of_node && (i == pdata->cfg_size)) {
  14856. + dev_err(ft5x46->dev, "Failed to find matched config!\n");
  14857. + return -ENOENT;
  14858. + }
  14859. +
  14860. + if (firmware->size == 0 && ft5x46->dev->of_node) {
  14861. + dev_info(ft5x46->dev, "firmware name = %s\n", firmware->fwname);
  14862. + error = request_firmware(&fw, firmware->fwname, ft5x46->dev);
  14863. + if (!error) {
  14864. + firmware->data = kmalloc((int)fw->size, GFP_KERNEL);
  14865. + if (!firmware->data) {
  14866. + dev_err(ft5x46->dev, "Failed to allocate firmware!\n");
  14867. + return -ENOMEM;
  14868. + } else {
  14869. + memcpy(firmware->data, fw->data, (int)fw->size);
  14870. + firmware->size = (int)fw->size;
  14871. + }
  14872. + release_firmware(fw);
  14873. + } else {
  14874. + dev_err(ft5x46->dev, "Cannot find firmware %s\n", firmware->fwname);
  14875. + return -ENODEV;
  14876. + }
  14877. + }
  14878. +
  14879. + if (firmware->data[firmware->size - 12] == 30)
  14880. + is_5336_fwsize_30 = true;
  14881. + else
  14882. + is_5336_fwsize_30 = false;
  14883. +
  14884. + /* step 1: check firmware id is different */
  14885. + error = ft5x46_read_byte(ft5x46, FT5X0X_REG_FW_VER, &id);
  14886. + if (error)
  14887. + return error;
  14888. + dev_info(ft5x46->dev, "firmware version is %02x\n", id);
  14889. +
  14890. + if (id == firmware->data[firmware->size + FT5X0X_FIRMWARE_VERION])
  14891. + return 0;
  14892. + dev_info(ft5x46->dev, "upgrade firmware to %02x\n",
  14893. + firmware->data[firmware->size + FT5X0X_FIRMWARE_VERION]);
  14894. + dev_info(ft5x46->dev, "[FTS] step1: check fw id\n");
  14895. +
  14896. + for (i = 0, error = -1; i < sizeof(reset_delay) && error; i++) {
  14897. + /* step 2: reset device */
  14898. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0xaa);
  14899. + if (error)
  14900. + continue;
  14901. + msleep(ui->delay_aa);
  14902. +
  14903. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0x55);
  14904. + if (error)
  14905. + continue;
  14906. + msleep(reset_delay[i]);
  14907. + dev_info(ft5x46->dev, "[FTS] step2: Reset device.\n");
  14908. +
  14909. + error = ft5x46_hid_to_std_i2c(ft5x46);
  14910. + if (error) {
  14911. + dev_err(ft5x46->dev, "HidI2c change to StdI2c fail!\n");
  14912. + }
  14913. + msleep(10);
  14914. +
  14915. + for (j = 0; j < 10; j++) {
  14916. + error = ft5x46_send_byte(ft5x46, 2, 0x55, 0xaa);
  14917. + msleep(5);
  14918. + if (!error)
  14919. + break;
  14920. + }
  14921. + if (error)
  14922. + continue;
  14923. +
  14924. + dev_info(ft5x46->dev, "[FTS] step3: Enter upgrade mode.\n");
  14925. +
  14926. + /* step 4: check device id */
  14927. + error = ft5x46_send_byte(ft5x46, 4, 0x90, 0x00, 0x00, 0x00);
  14928. + if (error) {
  14929. + dev_err(ft5x46->dev, "Failed to send 90 00 00 00\n");
  14930. + continue;
  14931. + }
  14932. +
  14933. + error = ft5x46_recv_byte(ft5x46, 2, &val1, &val2);
  14934. + if (error) {
  14935. + dev_err(ft5x46->dev, "Failed to receive device id\n");
  14936. + continue;
  14937. + }
  14938. +
  14939. + dev_info(ft5x46->dev, "read id = 0x%x, 0x%x, id = 0x%x, 0x%x\n", val1, val2,
  14940. + ui->upgrade_id_1, ui->upgrade_id_2);
  14941. + if (val1 != ui->upgrade_id_1 || val2 != ui->upgrade_id_2)
  14942. + error = -ENODEV;
  14943. +
  14944. + dev_info(ft5x46->dev, "[FTS] step4: Check device id.\n");
  14945. + }
  14946. +
  14947. + if (error) /* check the final result */
  14948. + return error;
  14949. +
  14950. + error = ft5x46_send_byte(ft5x46, 1, 0xcd);
  14951. + if (error)
  14952. + return error;
  14953. + error = ft5x46_recv_byte(ft5x46, 1, &val1);
  14954. + if (error)
  14955. + return error;
  14956. + dev_info(ft5x46->dev, "[FTS] bootloader version is 0x%x\n", val1);
  14957. +
  14958. + /* step 5: erase device */
  14959. + error = ft5x46_send_byte(ft5x46, 1, 0x61);
  14960. + if (error)
  14961. + return error;
  14962. + msleep(1500);
  14963. + if (0) {
  14964. + if (is_5336_fwsize_30) {
  14965. + error = ft5x46_send_byte(ft5x46, 1, 0x63);
  14966. + if (error)
  14967. + return error;
  14968. + msleep(50);
  14969. + }
  14970. + }
  14971. + ft5x46_wait_for_ready(ft5x46, 0xF0, 0xAA, 15, 50);
  14972. +
  14973. + /* Write firmware file length to bootloader */
  14974. + error = ft5x46_send_byte(ft5x46, 4, 0xB0,
  14975. + (u8)((firmware->size >> 16) & 0xFF),
  14976. + (u8)((firmware->size >> 8) & 0xFF),
  14977. + (u8)(firmware->size & 0xFF));
  14978. +
  14979. + dev_info(ft5x46->dev, "[FTS] step5: Erase device.\n");
  14980. +
  14981. + /* step 6: flash firmware to device */
  14982. +
  14983. + /* step 6a: send data in 128 bytes chunk each time */
  14984. + packet.magic1 = 0xbf;
  14985. + packet.magic2 = 0x00;
  14986. + packet_num = firmware->size / FT5X0X_PACKET_LENGTH;
  14987. +
  14988. + for (i = 0; i < packet_num ; i++) {
  14989. + length = FT5X0X_PACKET_LENGTH;
  14990. + packet.offset = cpu_to_be16(i * FT5X0X_PACKET_LENGTH);
  14991. + packet.length = cpu_to_be16(length);
  14992. +
  14993. + for (j = 0; j < length; j++) {
  14994. + packet.payload[j] = firmware->data[i * FT5X0X_PACKET_LENGTH + j];
  14995. + ecc ^= firmware->data[i * FT5X0X_PACKET_LENGTH + j];
  14996. + }
  14997. +
  14998. + error = ft5x46_send_block(ft5x46, &packet,
  14999. + FT5X0X_PACKET_HEADER + length);
  15000. + if (error)
  15001. + return error;
  15002. +
  15003. + ft5x46_wait_for_ready(ft5x46, (u8)((0x1000 + i) >> 8), (u8)((0x1000 + i) & 0xFF), 30, 1);
  15004. + }
  15005. + dev_info(ft5x46->dev, "[FTS] step6a: Send data in 128 bytes chunk each time.\n");
  15006. +
  15007. + /* step 6b: send the last bytes */
  15008. + if (firmware->size % FT5X0X_PACKET_LENGTH > 0) {
  15009. + length = firmware->size % FT5X0X_PACKET_LENGTH;
  15010. +
  15011. + packet.offset = cpu_to_be16(packet_num * FT5X0X_PACKET_LENGTH);
  15012. + packet.length = cpu_to_be16(length);
  15013. +
  15014. + for (j = 0; j < length; j++) {
  15015. + packet.payload[j] = firmware->data[packet_num * FT5X0X_PACKET_LENGTH + j];
  15016. + ecc ^= firmware->data[packet_num * FT5X0X_PACKET_LENGTH + j];
  15017. + }
  15018. +
  15019. + error = ft5x46_send_block(ft5x46, &packet,
  15020. + FT5X0X_PACKET_HEADER + length);
  15021. + if (error)
  15022. + return error;
  15023. + ft5x46_wait_for_ready(ft5x46, (u8)((0x1000 + i) >> 8), (u8)((0x1000 + i) & 0xFF), 30, 1);
  15024. + }
  15025. + dev_info(ft5x46->dev, "[FTS] step6b: Send the last bytes.\n");
  15026. +
  15027. + msleep(100);
  15028. +
  15029. + /* step 7: verify checksum */
  15030. + error = ft5x46_send_byte(ft5x46, 1, 0x64);
  15031. + if (error)
  15032. + return error;
  15033. + msleep(300);
  15034. +
  15035. + error = ft5x46_send_byte(ft5x46, 6, 0x65, 0, 0, 0,
  15036. + (u8)((firmware->size >> 8) & 0xFF),
  15037. + (u8)(firmware->size & 0xFF));
  15038. + if (error)
  15039. + return error;
  15040. + msleep(300);
  15041. +
  15042. + ft5x46_wait_for_ready(ft5x46, 0xF0, 0x55, 10, 10);
  15043. +
  15044. + error = ft5x46_send_byte(ft5x46, 1, 0x66);
  15045. + if (error)
  15046. + return error;
  15047. +
  15048. + error = ft5x46_recv_byte(ft5x46, 1, &val1);
  15049. + if (error)
  15050. + return error;
  15051. +
  15052. + if (val1 != ecc) {
  15053. + dev_err(ft5x46->dev, "ECC error! CHIP=%02x, FW=%02x",
  15054. + val1, ecc);
  15055. + return -ERANGE;
  15056. + }
  15057. + dev_info(ft5x46->dev, "[FTS] step7: Verify checksum.\n");
  15058. +
  15059. + /* step 8: reset to new firmware */
  15060. + error = ft5x46_send_byte(ft5x46, 1, 0x07);
  15061. + if (error)
  15062. + return error;
  15063. + msleep(300);
  15064. + dev_info(ft5x46->dev, "[FTS] step8: Reset to new firmware.\n");
  15065. +
  15066. + error = ft5x46_hid_to_std_i2c(ft5x46);
  15067. + if (error) {
  15068. + dev_err(ft5x46->dev, "[FTS] Change to StdI2C failed\n");
  15069. + }
  15070. +
  15071. +#ifdef CONFIG_TOUCHSCREEN_FT5X46_CALIBRATE
  15072. + /* step 9: calibrate the reference value */
  15073. + for (i = 0; i < max_calib_time; i++) {
  15074. + error = ft5x46_auto_calib(ft5x46);
  15075. + if (!error) {
  15076. + calib_ok = true;
  15077. + dev_info(ft5x46->dev, "[FTS] step9: Calibrate the ref value successfully.\n");
  15078. + break;
  15079. + }
  15080. + }
  15081. + if (!calib_ok) {
  15082. + dev_info(ft5x46->dev, "[FTS] step9: Calibrate the ref value failed.\n");
  15083. + return error;
  15084. + }
  15085. +#endif
  15086. +
  15087. + if (upgraded)
  15088. + *upgraded = true;
  15089. +
  15090. + return 0;
  15091. +}
  15092. +
  15093. +static int ft5x46_read_touchdata(struct ft5x46_data *ft5x46)
  15094. +{
  15095. + struct ft5x46_ts_event *event = &ft5x46->event;
  15096. + u8 buf[FT5X46_POINT_READ_BUF] = {0};
  15097. + int i, ret;
  15098. + u8 point_id;
  15099. + u16 xh, xl, yh, yl;
  15100. +
  15101. + ret = ft5x46_read_block(ft5x46, 0,
  15102. + buf, FT5X46_POINT_READ_BUF);
  15103. + if (ret < 0) {
  15104. + dev_err(ft5x46->dev, "read touchdata failed\n");
  15105. + return ret;
  15106. + }
  15107. +
  15108. + memset(event, 0, sizeof(struct ft5x46_ts_event));
  15109. +
  15110. + for (i = 0; i < FT5X0X_MAX_FINGER; i++) {
  15111. + point_id = (buf[FT5X46_TOUCH_LENGTH * i + FT5X46_ID_POS]) >> 4;
  15112. + if (point_id >= FT5X46_MAX_ID)
  15113. + break;
  15114. + else
  15115. + event->touch_point++;
  15116. +
  15117. + xh = (u16)(buf[FT5X46_TOUCH_LENGTH * i + FT5X46_XH_POS] & 0x0F);
  15118. + xl = (u16)(buf[FT5X46_TOUCH_LENGTH * i + FT5X46_XL_POS] & 0xFF);
  15119. +
  15120. + yh = (u16)(buf[FT5X46_TOUCH_LENGTH * i + FT5X46_YH_POS] & 0x0F);
  15121. + yl = (u16)(buf[FT5X46_TOUCH_LENGTH * i + FT5X46_YL_POS] & 0xFF);
  15122. +
  15123. + event->x[i] = (xh << 8) | xl;
  15124. + event->y[i] = (yh << 8) | yl;
  15125. + event->touch_event[i] = buf[FT5X46_TOUCH_LENGTH * i + FT5X46_EVENT_POS] >> 6;
  15126. + event->finger_id[i] = buf[FT5X46_TOUCH_LENGTH * i + FT5X46_ID_POS] >> 4;
  15127. +
  15128. + pr_debug("[FINGER %d]: id = %d, event = %d, x = %d, y = %d\n",
  15129. + i, event->finger_id[i], event->touch_event[i],
  15130. + event->x[i], event->y[i]);
  15131. + }
  15132. +
  15133. + event->pressure = FT5X46_DEF_PRESSURE;
  15134. +
  15135. + return 0;
  15136. +}
  15137. +
  15138. +static void ft5x46_clear_touch_event(struct ft5x46_data *ft5x46)
  15139. +{
  15140. + struct ft5x46_ts_event *event = &ft5x46->event;
  15141. + int i;
  15142. +
  15143. + for (i = 0; i < FT5X0X_MAX_FINGER; i++) {
  15144. + input_mt_slot(ft5x46->input, i);
  15145. + input_mt_report_slot_state(ft5x46->input, MT_TOOL_FINGER, false);
  15146. + }
  15147. +
  15148. + memset(event, 0, sizeof(struct ft5x46_ts_event));
  15149. + ft5x46->touchs = 0;
  15150. +
  15151. + input_report_key(ft5x46->input, BTN_TOUCH, 0);
  15152. + input_sync(ft5x46->input);
  15153. +}
  15154. +
  15155. +static void ft5x46_report_key(struct ft5x46_data *ft5x46, int x_pos, bool down)
  15156. +{
  15157. + switch (x_pos) {
  15158. + case 200:
  15159. + input_report_key(ft5x46->input, KEY_MENU, (int)down);
  15160. + down ? ft5x46->keys |= 0x01 : ft5x46->keys & 0xfe;
  15161. + break;
  15162. + case 500:
  15163. + input_report_key(ft5x46->input, KEY_HOME, (int)down);
  15164. + down ? ft5x46->keys |= 0x02 : ft5x46->keys & 0xfd;
  15165. + break;
  15166. + case 800:
  15167. + input_report_key(ft5x46->input, KEY_BACK, (int)down);
  15168. + down ? ft5x46->keys |= 0x04 : ft5x46->keys & 0xfb;
  15169. + break;
  15170. + default:
  15171. + break;
  15172. + }
  15173. +}
  15174. +
  15175. +static void ft5x46_report_value(struct ft5x46_data *ft5x46)
  15176. +{
  15177. + struct ft5x46_ts_event *event = &ft5x46->event;
  15178. + int i;
  15179. + int up_point = 0;
  15180. + int touchs = 0;
  15181. + int finger_num = 0;
  15182. +
  15183. + for (i = 0; i < event->touch_point; i++) {
  15184. + if (event->y[i] == 2000) {
  15185. + finger_num++;
  15186. +
  15187. + if (event->touch_event[i] == 0 || event->touch_event[i] == 2)
  15188. + ft5x46_report_key(ft5x46, event->x[i], true);
  15189. + else
  15190. + ft5x46_report_key(ft5x46, event->x[i], false);
  15191. + } else {
  15192. + input_mt_slot(ft5x46->input, event->finger_id[i]);
  15193. +
  15194. + if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
  15195. + input_mt_report_slot_state(ft5x46->input, MT_TOOL_FINGER, true);
  15196. + input_report_abs(ft5x46->input, ABS_MT_PRESSURE, event->pressure);
  15197. + input_report_abs(ft5x46->input, ABS_MT_TOUCH_MAJOR, event->pressure);
  15198. + input_report_abs(ft5x46->input, ABS_MT_POSITION_X, event->x[i]);
  15199. + input_report_abs(ft5x46->input, ABS_MT_POSITION_Y, event->y[i]);
  15200. +
  15201. + touchs |= BIT(event->finger_id[i]);
  15202. + ft5x46->touchs |= BIT(event->finger_id[i]);
  15203. + } else {
  15204. + up_point++;
  15205. + input_mt_report_slot_state(ft5x46->input, MT_TOOL_FINGER, false);
  15206. +
  15207. + ft5x46->touchs &= ~BIT(event->finger_id[i]);
  15208. + }
  15209. + }
  15210. + }
  15211. +
  15212. +
  15213. + for (i = 0; i < FT5X0X_MAX_FINGER; i++) {
  15214. + if (BIT(i) & (ft5x46->touchs ^ touchs)) {
  15215. + ft5x46->touchs &= ~BIT(i);
  15216. + input_mt_slot(ft5x46->input, i);
  15217. + input_mt_report_slot_state(ft5x46->input, MT_TOOL_FINGER, false);
  15218. + }
  15219. + }
  15220. +
  15221. + event->touch_point -= finger_num;
  15222. +
  15223. + if (event->touch_point == up_point) {
  15224. + ft5x46->touchs = 0;
  15225. + input_report_key(ft5x46->input, BTN_TOUCH, 0);
  15226. + } else {
  15227. + if (ft5x46->keys & 0x01)
  15228. + input_report_key(ft5x46->input, KEY_MENU, 0);
  15229. + if (ft5x46->keys & 0x02)
  15230. + input_report_key(ft5x46->input, KEY_HOME, 0);
  15231. + if (ft5x46->keys & 0x04)
  15232. + input_report_key(ft5x46->input, KEY_BACK, 0);
  15233. +
  15234. + ft5x46->keys = 0;
  15235. +
  15236. + input_report_key(ft5x46->input, BTN_TOUCH, (event->touch_point > 0));
  15237. + }
  15238. +
  15239. + input_sync(ft5x46->input);
  15240. +}
  15241. +
  15242. +static int ft5x46_read_gesture(struct ft5x46_data *ft5x46)
  15243. +{
  15244. + unsigned char buf[FT5X46_GESTURE_POINTS_HEADER] = { 0 };
  15245. + int error;
  15246. +
  15247. + error = ft5x46_read_block(ft5x46, 0xD3, buf,
  15248. + FT5X46_GESTURE_POINTS_HEADER);
  15249. + if (error) {
  15250. + dev_err(ft5x46->dev, "Error reading GESTURE_COOR\n");
  15251. + return error;
  15252. + }
  15253. +
  15254. + dev_info(ft5x46->dev, "Gesture ID = %d, Point num = %d\n", buf[0],
  15255. + buf[1]);
  15256. +
  15257. + if (buf[0] == FT5X46_GESTURE_UP || buf[0] == FT5X46_GESTURE_DBLCLICK) {
  15258. + dev_info(ft5x46->dev, "input report key wakeup\n");
  15259. + input_event(ft5x46->input, EV_KEY, KEY_WAKEUP, 1);
  15260. + input_sync(ft5x46->input);
  15261. + input_event(ft5x46->input, EV_KEY, KEY_WAKEUP, 0);
  15262. + input_sync(ft5x46->input);
  15263. + }
  15264. +
  15265. + return 0;
  15266. +}
  15267. +
  15268. +static int ft5x46_wakeup_reconfigure(struct ft5x46_data *ft5x46, bool enable)
  15269. +{
  15270. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  15271. + int error = 0;
  15272. +
  15273. + mutex_lock(&ft5x46->mutex);
  15274. +
  15275. + gpio_set_value(pdata->reset_gpio, 0);
  15276. + mdelay(5);
  15277. + gpio_set_value(pdata->reset_gpio, 1);
  15278. + mdelay(200);
  15279. +
  15280. + if (enable) {
  15281. + error = ft5x46_write_byte(ft5x46, 0xD0, 0x01);
  15282. + error |= ft5x46_write_byte(ft5x46, 0xD1, 0x14);
  15283. + } else {
  15284. + error = ft5x46_write_byte(ft5x46,
  15285. + FT5X0X_ID_G_PMODE, FT5X0X_POWER_HIBERNATE);
  15286. + }
  15287. +
  15288. + mutex_unlock(&ft5x46->mutex);
  15289. +
  15290. + if (enable)
  15291. + ft5x46_enable_irq(ft5x46);
  15292. + else
  15293. + ft5x46_disable_irq(ft5x46);
  15294. +
  15295. + return error;
  15296. +}
  15297. +
  15298. +static irqreturn_t ft5x46_interrupt(int irq, void *dev_id)
  15299. +{
  15300. + struct ft5x46_data *ft5x46 = dev_id;
  15301. + int error = 0;
  15302. + u8 val = 0;
  15303. +
  15304. + mutex_lock(&ft5x46->mutex);
  15305. +
  15306. + if (ft5x46->wakeup_mode && ft5x46->in_suspend) {
  15307. + error = ft5x46_read_byte(ft5x46, 0xD0, &val);
  15308. + if (error)
  15309. + dev_err(ft5x46->dev, "Error reading register 0xD0\n");
  15310. + else
  15311. + if (val == 1) {
  15312. + error = ft5x46_read_gesture(ft5x46);
  15313. + if (error)
  15314. + dev_err(ft5x46->dev, "Failed to read wakeup gesture\n");
  15315. + } else
  15316. + dev_err(ft5x46->dev, "Chip is in suspend, but wakeup gesture is not enabled.\n");
  15317. +
  15318. + goto out;
  15319. + }
  15320. +
  15321. + error = ft5x46_read_touchdata(ft5x46);
  15322. + if (!error) {
  15323. + ft5x46_report_value(ft5x46);
  15324. + }
  15325. +
  15326. +out:
  15327. + mutex_unlock(&ft5x46->mutex);
  15328. + return IRQ_HANDLED;
  15329. +}
  15330. +
  15331. +int ft5x46_suspend(struct ft5x46_data *ft5x46)
  15332. +{
  15333. + int error = 0;
  15334. +
  15335. + if (!ft5x46->wakeup_mode)
  15336. + ft5x46_disable_irq(ft5x46);
  15337. +
  15338. + mutex_lock(&ft5x46->mutex);
  15339. +
  15340. + if (ft5x46->in_suspend)
  15341. + goto out;
  15342. +
  15343. + ft5x46_clear_touch_event(ft5x46);
  15344. + mutex_unlock(&ft5x46->mutex);
  15345. +
  15346. + cancel_delayed_work_sync(&ft5x46->noise_filter_delayed_work);
  15347. +
  15348. + mutex_lock(&ft5x46->mutex);
  15349. + if (ft5x46->wakeup_mode) {
  15350. + dev_info(ft5x46->dev, "enter wakeup gesture mode\n");
  15351. + error = ft5x46_write_byte(ft5x46, 0xD0, 0x01);
  15352. + error |= ft5x46_write_byte(ft5x46, 0xD1, 0x14);
  15353. + } else {
  15354. + error = ft5x46_write_byte(ft5x46,
  15355. + FT5X0X_ID_G_PMODE, FT5X0X_POWER_HIBERNATE);
  15356. + }
  15357. + ft5x46->in_suspend = true;
  15358. +
  15359. +out:
  15360. + mutex_unlock(&ft5x46->mutex);
  15361. + return error;
  15362. +}
  15363. +EXPORT_SYMBOL_GPL(ft5x46_suspend);
  15364. +
  15365. +int ft5x46_resume(struct ft5x46_data *ft5x46)
  15366. +{
  15367. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  15368. +
  15369. + if (ft5x46->wakeup_mode)
  15370. + ft5x46_disable_irq(ft5x46);
  15371. +
  15372. + mutex_lock(&ft5x46->mutex);
  15373. +
  15374. + if (!ft5x46->in_suspend)
  15375. + goto out;
  15376. +
  15377. + gpio_set_value(pdata->reset_gpio, 0);
  15378. + mdelay(5);
  15379. + gpio_set_value(pdata->reset_gpio, 1);
  15380. + mdelay(5);
  15381. +
  15382. + mutex_unlock(&ft5x46->mutex);
  15383. +
  15384. + schedule_delayed_work(&ft5x46->noise_filter_delayed_work,
  15385. + NOISE_FILTER_DELAY);
  15386. +
  15387. + mutex_lock(&ft5x46->mutex);
  15388. + ft5x46->in_suspend = false;
  15389. +
  15390. +out:
  15391. + mutex_unlock(&ft5x46->mutex);
  15392. +
  15393. + if (ft5x46->cover_mode) {
  15394. + msleep(100);
  15395. + ft5x46_cover_mode(ft5x46, ft5x46->cover_mode);
  15396. + }
  15397. +
  15398. + ft5x46_enable_irq(ft5x46);
  15399. +
  15400. + return 0;
  15401. +}
  15402. +EXPORT_SYMBOL_GPL(ft5x46_resume);
  15403. +
  15404. +#ifdef CONFIG_HAS_EARLYSUSPEND
  15405. +static void ft5x46_early_suspend(struct early_suspend *h)
  15406. +{
  15407. + struct ft5x46_data *ft5x46 = container_of(h,
  15408. + struct ft5x46_data, early_suspend);
  15409. + ft5x46_suspend(ft5x46);
  15410. +}
  15411. +
  15412. +static void ft5x46_early_resume(struct early_suspend *h)
  15413. +{
  15414. + struct ft5x46_data *ft5x46 = container_of(h,
  15415. + struct ft5x46_data, early_suspend);
  15416. + ft5x46_resume(ft5x46);
  15417. +}
  15418. +#else
  15419. +static int ft5x46_input_disable(struct input_dev *in_dev)
  15420. +{
  15421. + struct ft5x46_data *ft5x46 = input_get_drvdata(in_dev);
  15422. +
  15423. + dev_info(ft5x46->dev, "ft5x46 disable!\n");
  15424. + ft5x46_suspend(ft5x46);
  15425. +
  15426. + return 0;
  15427. +}
  15428. +
  15429. +static int ft5x46_input_enable(struct input_dev *in_dev)
  15430. +{
  15431. + struct ft5x46_data *ft5x46 = input_get_drvdata(in_dev);
  15432. +
  15433. + dev_dbg(ft5x46->dev, "ft5x46 enable!\n");
  15434. + ft5x46_resume(ft5x46);
  15435. +
  15436. + return 0;
  15437. +}
  15438. +#endif
  15439. +
  15440. +static ssize_t ft5x46_vkeys_show(struct kobject *kobj,
  15441. + struct kobj_attribute *attr, char *buf)
  15442. +{
  15443. + return snprintf(buf, PAGE_SIZE,
  15444. + __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":200:2000:10:10:"
  15445. + __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":500:2000:10:10:"
  15446. + __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":800:2000:10:10"
  15447. + "\n");
  15448. +}
  15449. +
  15450. +static int ft5x46_get_lockdown_info(struct ft5x46_data *ft5x46)
  15451. +{
  15452. + int error = 0;
  15453. + int i, j;
  15454. + u8 val1, val2;
  15455. + struct ft5x46_rd_flash_packet packet;
  15456. +
  15457. + for (i = 0, error = -1; i < sizeof(reset_delay) && error; i++) {
  15458. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0xaa);
  15459. + if (error)
  15460. + continue;
  15461. + msleep(50);
  15462. +
  15463. + error = ft5x46_write_byte(ft5x46, FT5X0X_REG_RESET, 0x55);
  15464. + if (error)
  15465. + continue;
  15466. + msleep(200);
  15467. + dev_info(ft5x46->dev, "[FTS] step1: Reset device.\n");
  15468. + error = ft5x46_hid_to_std_i2c(ft5x46);
  15469. + if (error) {
  15470. + dev_err(ft5x46->dev, "HidI2c change to StdI2c fail!\n");
  15471. + }
  15472. + for (j = 0; j < 10; j++) {
  15473. + error = ft5x46_send_byte(ft5x46, 2, 0x55, 0xaa);
  15474. + msleep(5);
  15475. + if (!error)
  15476. + break;
  15477. + }
  15478. + if (error)
  15479. + continue;
  15480. +
  15481. + dev_info(ft5x46->dev, "[FTS] step2: Enter upgrade mode.\n");
  15482. +
  15483. + error = ft5x46_send_byte(ft5x46, 4, 0x90, 0x00, 0x00, 0x00);
  15484. + if (error) {
  15485. + dev_err(ft5x46->dev, "Failed to send 90 00 00 00\n");
  15486. + continue;
  15487. + }
  15488. +
  15489. + error = ft5x46_recv_byte(ft5x46, 2, &val1, &val2);
  15490. + if (error) {
  15491. + dev_err(ft5x46->dev, "Failed to receive device id\n");
  15492. + continue;
  15493. + }
  15494. +
  15495. + dev_info(ft5x46->dev, "read id = 0x%x, 0x%x\n", val1, val2);
  15496. +
  15497. + dev_info(ft5x46->dev, "[FTS] step3: Check device id.\n");
  15498. +
  15499. + if (val1 == FT5316_UPGRADE_ID_1 && val2 == FT5316_UPGRADE_ID_2) {
  15500. + ft5x46->chip_id = FT5316_CHIP_ID;
  15501. + break;
  15502. + } else if (val1 == FT5X36_UPGRADE_ID_1 && val2 == FT5X36_UPGRADE_ID_2) {
  15503. + ft5x46->chip_id = FT5X36_CHIP_ID;
  15504. + break;
  15505. + } else if (val1 == FT5X46_UPGRADE_ID_1 && val2 == FT5X46_UPGRADE_ID_2) {
  15506. + ft5x46->chip_id = FT5X46_CHIP_ID;
  15507. + break;
  15508. + }
  15509. + }
  15510. +
  15511. + if (error)
  15512. + return error;
  15513. +
  15514. + packet.magic = 0x03;
  15515. + packet.addr_h = 0x00;
  15516. + packet.addr_m = 0xD7;
  15517. + packet.addr_l = 0xA0;
  15518. +
  15519. + error = ft5x46_send_block(ft5x46, &packet, FT5X46_RD_FLASH_PACKET_SIZE);
  15520. + msleep(5);
  15521. + error = ft5x46_recv_byte(ft5x46, 8,
  15522. + &ft5x46->lockdown_info[0], &ft5x46->lockdown_info[1],
  15523. + &ft5x46->lockdown_info[2], &ft5x46->lockdown_info[3],
  15524. + &ft5x46->lockdown_info[4], &ft5x46->lockdown_info[5],
  15525. + &ft5x46->lockdown_info[6], &ft5x46->lockdown_info[7]);
  15526. +
  15527. + for (i = 0; i < 8; i++)
  15528. + dev_info(ft5x46->dev, "Lockdown[%d] val = 0x%x\n", i, ft5x46->lockdown_info[i]);
  15529. +
  15530. + error = ft5x46_send_byte(ft5x46, 1, 0x07);
  15531. + if (error)
  15532. + return error;
  15533. + msleep(200);
  15534. +
  15535. + return error;
  15536. +}
  15537. +
  15538. +static ssize_t ft5x46_object_show(struct device *dev,
  15539. + struct device_attribute *attr, char *buf)
  15540. +{
  15541. + static struct {
  15542. + u8 addr;
  15543. + const char *fmt;
  15544. + } reg_list[] = {
  15545. + {0x80, "THGROUP %3d\n" },
  15546. + {0x81, "THPEAK %3d\n" },
  15547. + {0x82, "THCAL %3d\n" },
  15548. + {0x83, "THWATER %3d\n" },
  15549. + {0x84, "THTEMP %3d\n" },
  15550. + {0x85, "THDIFF %3d\n" },
  15551. + {0xae, "THBAREA %3d\n" },
  15552. + {0x86, "CTRL %02x\n"},
  15553. + {0xa0, "AUTOCLB %02x\n"},
  15554. + {0xa4, "MODE %02x\n"},
  15555. + {0xa5, "PMODE %02x\n"},
  15556. + {0xa7, "STATE %02x\n"},
  15557. + {0xa9, "ERR %02x\n"},
  15558. + {0x87, "TIME2MONITOR %3d\n" },
  15559. + {0x88, "PERIODACTIVE %3d\n" },
  15560. + {0x89, "PERIODMONITOR %3d\n" },
  15561. + {0xa1, "LIBVERH %02x\n"},
  15562. + {0xa2, "LIBVERL %02x\n"},
  15563. + {0xa3, "CIPHER %02x\n"},
  15564. + {0xa6, "FIRMID %02x\n"},
  15565. + {0xa8, "FT5201ID %02x\n"},
  15566. + {},
  15567. + };
  15568. +
  15569. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15570. + int i, error, count = 0;
  15571. + u8 val;
  15572. +
  15573. + mutex_lock(&ft5x46->mutex);
  15574. + for (i = 0; reg_list[i].addr != 0; i++) {
  15575. + error = ft5x46_read_byte(ft5x46, reg_list[i].addr, &val);
  15576. + if (error)
  15577. + break;
  15578. +
  15579. + count += snprintf(buf+count, PAGE_SIZE-count,
  15580. + reg_list[i].fmt, val);
  15581. + }
  15582. + mutex_unlock(&ft5x46->mutex);
  15583. +
  15584. + return error ? : count;
  15585. +}
  15586. +
  15587. +static ssize_t ft5x46_object_store(struct device *dev,
  15588. + struct device_attribute *attr,
  15589. + const char *buf, size_t count)
  15590. +{
  15591. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15592. + u8 addr, val;
  15593. + int error;
  15594. +
  15595. + mutex_lock(&ft5x46->mutex);
  15596. + if (sscanf(buf, "%hhx=%hhx", &addr, &val) == 2)
  15597. + error = ft5x46_write_byte(ft5x46, addr, val);
  15598. + else
  15599. + error = -EINVAL;
  15600. + mutex_unlock(&ft5x46->mutex);
  15601. +
  15602. + return error ? : count;
  15603. +}
  15604. +
  15605. +static ssize_t ft5x46_dbgdump_show(struct device *dev,
  15606. + struct device_attribute *attr, char *buf)
  15607. +{
  15608. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15609. + int count;
  15610. +
  15611. + mutex_lock(&ft5x46->mutex);
  15612. + count = snprintf(buf, PAGE_SIZE, "%d\n", ft5x46->dbgdump);
  15613. + mutex_unlock(&ft5x46->mutex);
  15614. +
  15615. + return count;
  15616. +}
  15617. +
  15618. +static ssize_t ft5x46_dbgdump_store(struct device *dev,
  15619. + struct device_attribute *attr,
  15620. + const char *buf, size_t count)
  15621. +{
  15622. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15623. + unsigned long dbgdump;
  15624. + int error;
  15625. +
  15626. + mutex_lock(&ft5x46->mutex);
  15627. + error = sscanf(buf, "%lu", &dbgdump);
  15628. + if (!error)
  15629. + ft5x46->dbgdump = dbgdump;
  15630. + mutex_unlock(&ft5x46->mutex);
  15631. +
  15632. + return error ? : count;
  15633. +}
  15634. +
  15635. +static int ft5x46_updatefw_with_filename(struct ft5x46_data *ft5x46,
  15636. + const char *filename, bool *upgraded)
  15637. +{
  15638. + struct ft5x46_firmware_data firmware;
  15639. + const struct firmware *fw;
  15640. + int error;
  15641. +
  15642. + error = request_firmware(&fw, filename, ft5x46->dev);
  15643. + if (!error) {
  15644. + firmware.data = kmalloc((int)fw->size, GFP_KERNEL);
  15645. + memcpy(firmware.data, fw->data, (int)fw->size);
  15646. + firmware.size = fw->size;
  15647. +
  15648. + mutex_lock(&ft5x46->mutex);
  15649. + if (ft5x46->chip_id == FT5316_CHIP_ID)
  15650. + error = ft5x06_load_firmware(ft5x46, &firmware, upgraded);
  15651. + else
  15652. + error = ft5x46_load_firmware(ft5x46, &firmware, upgraded);
  15653. + mutex_unlock(&ft5x46->mutex);
  15654. +
  15655. + kfree(firmware.data);
  15656. + release_firmware(fw);
  15657. + }
  15658. +
  15659. + return error;
  15660. +}
  15661. +
  15662. +static ssize_t ft5x46_updatefw_store(struct device *dev,
  15663. + struct device_attribute *attr,
  15664. + const char *buf, size_t count)
  15665. +{
  15666. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15667. + int error;
  15668. + bool upgraded;
  15669. +
  15670. + error = ft5x46_updatefw_with_filename(ft5x46,
  15671. + "ft5x06.bin", &upgraded);
  15672. +
  15673. + return error ? : count;
  15674. +}
  15675. +
  15676. +static ssize_t ft5x46_tpfwver_show(struct device *dev,
  15677. + struct device_attribute *attr, char *buf)
  15678. +{
  15679. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15680. + ssize_t num_read_chars = 0;
  15681. + u8 fwver = 0;
  15682. + int error;
  15683. + mutex_lock(&ft5x46->mutex);
  15684. + error = ft5x46_read_byte(ft5x46, FT5X0X_REG_FW_VER, &fwver);
  15685. + if (error)
  15686. + num_read_chars = snprintf(buf, PAGE_SIZE, "Get firmware version failed!\n");
  15687. + else
  15688. + num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);
  15689. + mutex_unlock(&ft5x46->mutex);
  15690. + return num_read_chars;
  15691. +}
  15692. +
  15693. +static int ft5x46_enter_factory(struct ft5x46_data *ft5x46_ts)
  15694. +{
  15695. + u8 reg_val;
  15696. + int error;
  15697. + int error_code = -1;
  15698. +
  15699. + error = ft5x46_write_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE,
  15700. + FT5X0X_DEVICE_MODE_TEST);
  15701. + if (error)
  15702. + return error_code;
  15703. + msleep(100);
  15704. + error = ft5x46_read_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE, &reg_val);
  15705. + if (error)
  15706. + return error_code;
  15707. + if ((reg_val & 0x70) != FT5X0X_DEVICE_MODE_TEST) {
  15708. + dev_info(ft5x46_ts->dev, "ERROR: The Touch Panel was not put in Factory Mode.");
  15709. + return error_code;
  15710. + }
  15711. +
  15712. + return 0;
  15713. +}
  15714. +
  15715. +static int ft5x46_enter_work(struct ft5x46_data *ft5x46_ts)
  15716. +{
  15717. + u8 reg_val;
  15718. + int error;
  15719. + int error_code = -1;
  15720. + error = ft5x46_write_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE,
  15721. + FT5X0X_DEVICE_MODE_NORMAL);
  15722. + if (error)
  15723. + return error_code;
  15724. + msleep(100);
  15725. + error = ft5x46_read_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE, &reg_val);
  15726. + if (error)
  15727. + return error_code;
  15728. + if ((reg_val & 0x70) != FT5X0X_DEVICE_MODE_NORMAL) {
  15729. + dev_info(ft5x46_ts->dev, "ERROR: The Touch Panel was not put in Normal Mode.\n");
  15730. + return error_code;
  15731. + }
  15732. +
  15733. + return 0;
  15734. +}
  15735. +
  15736. +#define FT5X0X_MAX_RX_NUM 22
  15737. +static int ft5x46_get_rawData(struct ft5x46_data *ft5x46_ts,
  15738. + u16 *rawdata)
  15739. +{
  15740. + int ret_val = 0;
  15741. + int error;
  15742. + u8 val;
  15743. + int row_num = 0;
  15744. + u8 read_buffer[FT5X0X_MAX_RX_NUM * 2];
  15745. + int read_len;
  15746. + int i;
  15747. + struct ft5x46_ts_platform_data *pdata = ft5x46_ts->dev->platform_data;
  15748. + int index = ft5x46_ts->current_index;
  15749. + int tx_num = pdata->testdata[index].tx_num;
  15750. + int rx_num = pdata->testdata[index].rx_num;
  15751. +
  15752. + error = ft5x46_read_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE, &val);
  15753. + if (error < 0) {
  15754. + dev_err(ft5x46_ts->dev, "ERROR: Read mode failed!\n");
  15755. + ret_val = -1;
  15756. + goto error_return;
  15757. + }
  15758. + val |= 0x80;
  15759. + error = ft5x46_write_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE, val);
  15760. + if (error < 0) {
  15761. + dev_err(ft5x46_ts->dev, "ERROR: Write mode failed!\n");
  15762. + ret_val = -1;
  15763. + goto error_return;
  15764. + }
  15765. + msleep(20);
  15766. + error = ft5x46_read_byte(ft5x46_ts, FT5X0X_REG_DEVIDE_MODE, &val);
  15767. + if (error < 0) {
  15768. + dev_err(ft5x46_ts->dev, "ERROR: Read mode failed!\n");
  15769. + ret_val = -1;
  15770. + goto error_return;
  15771. + }
  15772. + if (0x00 != (val & 0x80)) {
  15773. + dev_err(ft5x46_ts->dev, "ERROR: Read mode failed!\n");
  15774. + ret_val = -1;
  15775. + goto error_return;
  15776. + }
  15777. + dev_info(ft5x46_ts->dev, "Read rawdata......\n");
  15778. + for (row_num = 0; row_num < tx_num; row_num++) {
  15779. + memset(read_buffer, 0x00, rx_num * 2);
  15780. + error = ft5x46_write_byte(ft5x46_ts, FT5X0X_REG_ROW_ADDR, row_num);
  15781. + if (error < 0) {
  15782. + dev_err(ft5x46_ts->dev, "ERROR: Write row addr failed!\n");
  15783. + ret_val = -1;
  15784. + goto error_return;
  15785. + }
  15786. + msleep(1);
  15787. + read_len = rx_num * 2;
  15788. + error = ft5x46_write_byte(ft5x46_ts, 0x10, read_len);
  15789. + if (error < 0) {
  15790. + dev_err(ft5x46_ts->dev, "ERROR: Write len failed!\n");
  15791. + ret_val = -1;
  15792. + goto error_return;
  15793. + }
  15794. + error = ft5x46_read_block(ft5x46_ts, 0x10,
  15795. + read_buffer, rx_num * 2);
  15796. + if (error < 0) {
  15797. + dev_err(ft5x46_ts->dev,
  15798. + "ERROR: Coule not read row %u data!\n", row_num);
  15799. + ret_val = -1;
  15800. + goto error_return;
  15801. + }
  15802. + for (i = 0; i < rx_num; i++) {
  15803. + rawdata[row_num * rx_num + i] = read_buffer[i<<1];
  15804. + rawdata[row_num * rx_num + i] = rawdata[row_num * rx_num + i] << 8;
  15805. + rawdata[row_num * rx_num + i] |= read_buffer[(i<<1)+1];
  15806. + }
  15807. + }
  15808. +error_return:
  15809. + return ret_val;
  15810. +}
  15811. +
  15812. +static ssize_t ft5x46_rawdata_show(struct device *dev,
  15813. + struct device_attribute *attr, char *buf)
  15814. +{
  15815. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15816. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  15817. + int index = ft5x46->current_index;
  15818. + u16 *rawdata;
  15819. + int error;
  15820. + int i = 0, j = 0;
  15821. + int num_read_chars = 0;
  15822. + int tx_num = pdata->testdata[index].tx_num;
  15823. + int rx_num = pdata->testdata[index].rx_num;
  15824. +
  15825. + rawdata = (u16 *)kmalloc(sizeof(u16) * tx_num * rx_num, GFP_KERNEL);
  15826. + if (rawdata == NULL)
  15827. + return -ENOMEM;
  15828. +
  15829. + mutex_lock(&ft5x46->mutex);
  15830. +
  15831. + disable_irq_nosync(ft5x46->irq);
  15832. + error = ft5x46_enter_factory(ft5x46);
  15833. + if (error < 0) {
  15834. + dev_err(ft5x46->dev, "ERROR: Could not enter factory mode!\n");
  15835. + goto end;
  15836. + }
  15837. +
  15838. + error = ft5x46_get_rawData(ft5x46, rawdata);
  15839. + if (error < 0)
  15840. + snprintf(buf, PAGE_SIZE, "%s", "Could not get rawdata\n");
  15841. + else {
  15842. + for (i = 0; i < tx_num; i++) {
  15843. + for (j = 0; j < rx_num; j++) {
  15844. + num_read_chars += snprintf(&buf[num_read_chars], PAGE_SIZE,
  15845. + "%u ", rawdata[i * rx_num + j]);
  15846. + }
  15847. + buf[num_read_chars-1] = '\n';
  15848. + }
  15849. + }
  15850. +
  15851. + error = ft5x46_enter_work(ft5x46);
  15852. + if (error < 0)
  15853. + dev_err(ft5x46->dev, "ERROR: Could not enter work mode!\n");
  15854. +
  15855. +end:
  15856. + enable_irq(ft5x46->irq);
  15857. + mutex_unlock(&ft5x46->mutex);
  15858. + kfree(rawdata);
  15859. + return num_read_chars;
  15860. +}
  15861. +
  15862. +unsigned int ft5x46_do_selftest(struct ft5x46_data *ft5x46)
  15863. +{
  15864. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  15865. + int index = ft5x46->current_index;
  15866. + u16 *testdata;
  15867. + int i, j;
  15868. + int error;
  15869. + int tx_num = pdata->testdata[index].tx_num;
  15870. + int rx_num = pdata->testdata[index].rx_num;
  15871. + int final_tx_num = tx_num;
  15872. + int final_rx_num = rx_num;
  15873. +
  15874. + testdata = (u16 *)kmalloc(sizeof(u16) * tx_num * rx_num, GFP_KERNEL);
  15875. + if (testdata == NULL)
  15876. + return -ENOMEM;
  15877. +
  15878. + error = ft5x46_get_rawData(ft5x46, testdata);
  15879. + if (error)
  15880. + return 0;
  15881. +
  15882. + if (tx_num > rx_num)
  15883. + final_tx_num -= 1;
  15884. + else
  15885. + final_rx_num -= 1;
  15886. +
  15887. + for (i = 0; i < final_tx_num; i++) {
  15888. + for (j = 0; j < final_rx_num; j++) {
  15889. + if (testdata[i * rx_num + j] < pdata->raw_min ||
  15890. + testdata[i * rx_num + j] > pdata->raw_max)
  15891. + return 0;
  15892. + }
  15893. + }
  15894. +
  15895. + return 1;
  15896. +}
  15897. +
  15898. +static ssize_t ft5x46_selftest_store(struct device *dev,
  15899. + struct device_attribute *attr,
  15900. + const char *buf, size_t count)
  15901. +{
  15902. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15903. + int error;
  15904. + unsigned long val;
  15905. +
  15906. + error = sscanf(buf, "%lu", &val);
  15907. + if (error)
  15908. + return error;
  15909. + if (val != 1)
  15910. + return -EINVAL;
  15911. +
  15912. + mutex_lock(&ft5x46->mutex);
  15913. +
  15914. + disable_irq_nosync(ft5x46->irq);
  15915. + error = ft5x46_enter_factory(ft5x46);
  15916. + if (error < 0) {
  15917. + dev_err(ft5x46->dev, "ERROR: Could not enter factory mode!\n");
  15918. + goto end;
  15919. + }
  15920. +
  15921. + ft5x46->test_result = ft5x46_do_selftest(ft5x46);
  15922. +
  15923. + error = ft5x46_enter_work(ft5x46);
  15924. + if (error < 0)
  15925. + dev_err(ft5x46->dev, "ERROR: Could not enter work mode!\n");
  15926. +
  15927. +end:
  15928. + enable_irq(ft5x46->irq);
  15929. + mutex_unlock(&ft5x46->mutex);
  15930. + return count;
  15931. +}
  15932. +
  15933. +static ssize_t ft5x46_selftest_show(struct device *dev,
  15934. + struct device_attribute *attr, char *buf)
  15935. +{
  15936. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15937. +
  15938. + return snprintf(&buf[0], PAGE_SIZE, "%u\n", ft5x46->test_result);
  15939. +}
  15940. +
  15941. +static ssize_t ft5x46_lockdown_info_store(struct device *dev,
  15942. + struct device_attribute *attr,
  15943. + const char *buf, size_t count)
  15944. +{
  15945. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15946. + int error;
  15947. + unsigned long val;
  15948. +
  15949. + error = sscanf(buf, "%lu", &val);
  15950. + if (error)
  15951. + return error;
  15952. + if (val != 1)
  15953. + return -EINVAL;
  15954. +
  15955. + error = ft5x46_get_lockdown_info(ft5x46);
  15956. + if (error)
  15957. + return -EINVAL;
  15958. + else
  15959. + return count;
  15960. +}
  15961. +
  15962. +static ssize_t ft5x46_lockdown_info_show(struct device *dev,
  15963. + struct device_attribute *attr, char *buf)
  15964. +{
  15965. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15966. + int error;
  15967. +
  15968. + error = ft5x46_get_lockdown_info(ft5x46);
  15969. + if (error)
  15970. + return snprintf(buf, PAGE_SIZE, "Failed to get lockdown info\n");
  15971. + else
  15972. + return snprintf(buf, PAGE_SIZE, "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
  15973. + (int)ft5x46->lockdown_info[0], (int)ft5x46->lockdown_info[1],
  15974. + (int)ft5x46->lockdown_info[2], (int)ft5x46->lockdown_info[3],
  15975. + (int)ft5x46->lockdown_info[4], (int)ft5x46->lockdown_info[5],
  15976. + (int)ft5x46->lockdown_info[6], (int)ft5x46->lockdown_info[7]);
  15977. +}
  15978. +
  15979. +static ssize_t ft5x46_config_info_show(struct device *dev,
  15980. + struct device_attribute *attr, char *buf)
  15981. +{
  15982. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15983. +
  15984. + return snprintf(buf, PAGE_SIZE, "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
  15985. + (int)ft5x46->config_info[0], (int)ft5x46->config_info[1],
  15986. + (int)ft5x46->config_info[2], (int)ft5x46->config_info[3],
  15987. + (int)ft5x46->config_info[4], (int)ft5x46->config_info[5],
  15988. + (int)ft5x46->config_info[6], (int)ft5x46->config_info[7]);
  15989. +}
  15990. +
  15991. +static ssize_t ft5x46_wakeup_mode_store(struct device *dev,
  15992. + struct device_attribute *attr,
  15993. + const char *buf, size_t count)
  15994. +{
  15995. + int error;
  15996. + unsigned long val;
  15997. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  15998. +
  15999. + error = sscanf(buf, "%lu", &val);
  16000. +
  16001. + if (!error)
  16002. + ft5x46->wakeup_mode = !!val;
  16003. +
  16004. + if (ft5x46->in_suspend)
  16005. + ft5x46_wakeup_reconfigure(ft5x46, (bool)val);
  16006. +
  16007. + return error ? : count;
  16008. +}
  16009. +
  16010. +static ssize_t ft5x46_wakeup_mode_show(struct device *dev,
  16011. + struct device_attribute *attr, char *buf)
  16012. +{
  16013. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  16014. +
  16015. + return snprintf(buf, PAGE_SIZE, "%d\n", (int)ft5x46->wakeup_mode);
  16016. +}
  16017. +
  16018. +static ssize_t ft5x46_panel_color_show(struct device *dev,
  16019. + struct device_attribute *attr, char *buf)
  16020. +{
  16021. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  16022. + int error, count = 0;
  16023. +
  16024. + if (ft5x46->in_suspend)
  16025. + ft5x46_resume(ft5x46);
  16026. +
  16027. + error = ft5x46_get_lockdown_info(ft5x46);
  16028. + if (error || ft5x46->lockdown_info[2] == 0)
  16029. + count = snprintf(buf, PAGE_SIZE, "0\n");
  16030. + else
  16031. + count = snprintf(buf, PAGE_SIZE, "%c\n", ft5x46->lockdown_info[2]);
  16032. +
  16033. + return count;
  16034. +}
  16035. +
  16036. +#ifdef FT5X46_DEBUG_PERMISSION
  16037. +static DEVICE_ATTR(tpfwver, 0400, ft5x46_tpfwver_show, NULL);
  16038. +static DEVICE_ATTR(object, 0600, ft5x46_object_show, ft5x46_object_store);
  16039. +static DEVICE_ATTR(dbgdump, 0600, ft5x46_dbgdump_show, ft5x46_dbgdump_store);
  16040. +static DEVICE_ATTR(updatefw, 0200, NULL, ft5x46_updatefw_store);
  16041. +static DEVICE_ATTR(rawdatashow, 0400, ft5x46_rawdata_show, NULL);
  16042. +static DEVICE_ATTR(selftest, 0600, ft5x46_selftest_show, ft5x46_selftest_store);
  16043. +static DEVICE_ATTR(lockdown_info, 0600, ft5x46_lockdown_info_show, ft5x46_lockdown_info_store);
  16044. +static DEVICE_ATTR(config_info, 0400, ft5x46_config_info_show, NULL);
  16045. +static DEVICE_ATTR(wakeup_mode, 0600, ft5x46_wakeup_mode_show, ft5x46_wakeup_mode_store);
  16046. +static DEVICE_ATTR(panel_color, 0400, ft5x46_panel_color_show, NULL);
  16047. +#else
  16048. +static DEVICE_ATTR(tpfwver, 0400, ft5x46_tpfwver_show, NULL);
  16049. +static DEVICE_ATTR(object, 0600, ft5x46_object_show, ft5x46_object_store);
  16050. +static DEVICE_ATTR(dbgdump, 0600, ft5x46_dbgdump_show, ft5x46_dbgdump_store);
  16051. +static DEVICE_ATTR(updatefw, 0200, NULL, ft5x46_updatefw_store);
  16052. +static DEVICE_ATTR(rawdatashow, 0400, ft5x46_rawdata_show, NULL);
  16053. +static DEVICE_ATTR(selftest, 0600, ft5x46_selftest_show, ft5x46_selftest_store);
  16054. +static DEVICE_ATTR(lockdown_info, 0600, ft5x46_lockdown_info_show, ft5x46_lockdown_info_store);
  16055. +static DEVICE_ATTR(config_info, 0400, ft5x46_config_info_show, NULL);
  16056. +static DEVICE_ATTR(wakeup_mode, 0600, ft5x46_wakeup_mode_show, ft5x46_wakeup_mode_store);
  16057. +static DEVICE_ATTR(panel_color, 0400, ft5x46_panel_color_show, NULL);
  16058. +#endif
  16059. +
  16060. +static struct attribute *ft5x46_attrs[] = {
  16061. + &dev_attr_tpfwver.attr,
  16062. + &dev_attr_object.attr,
  16063. + &dev_attr_dbgdump.attr,
  16064. + &dev_attr_updatefw.attr,
  16065. + &dev_attr_rawdatashow.attr,
  16066. + &dev_attr_selftest.attr,
  16067. + &dev_attr_lockdown_info.attr,
  16068. + &dev_attr_config_info.attr,
  16069. + &dev_attr_wakeup_mode.attr,
  16070. + &dev_attr_panel_color.attr,
  16071. + NULL
  16072. +};
  16073. +
  16074. +static const struct attribute_group ft5x46_attr_group = {
  16075. + .attrs = ft5x46_attrs
  16076. +};
  16077. +
  16078. +static int ft5x46_power_on(struct ft5x46_data *data, bool on)
  16079. +{
  16080. + int rc = 0;
  16081. +
  16082. + if (on) {
  16083. + rc = regulator_enable(data->vddio);
  16084. + if (rc) {
  16085. + dev_err(data->dev,
  16086. + "Regulator vddio enable failed rc=%d\n", rc);
  16087. + return rc;
  16088. + }
  16089. + msleep(1);
  16090. + rc = regulator_enable(data->vdd);
  16091. + if (rc) {
  16092. + dev_err(data->dev,
  16093. + "Regulator vdd enable failed rc=%d\n", rc);
  16094. + return rc;
  16095. + }
  16096. +
  16097. + } else {
  16098. + rc = regulator_disable(data->vddio);
  16099. + if (rc) {
  16100. + dev_err(data->dev,
  16101. + "Regulator vddio disable failed rc=%d\n", rc);
  16102. + return rc;
  16103. + }
  16104. +
  16105. + rc = regulator_disable(data->vdd);
  16106. + if (rc) {
  16107. + dev_err(data->dev,
  16108. + "Regulator vdd disable failed rc=%d\n", rc);
  16109. + return rc;
  16110. + }
  16111. + }
  16112. +
  16113. + return rc;
  16114. +}
  16115. +
  16116. +static int ft5x46_power_init(struct ft5x46_data *data, bool on)
  16117. +{
  16118. + int rc;
  16119. +
  16120. + if (!on)
  16121. + goto pwr_deinit;
  16122. +
  16123. + data->vdd = regulator_get(data->dev, "vdd");
  16124. + if (IS_ERR(data->vdd)) {
  16125. + rc = PTR_ERR(data->vdd);
  16126. + dev_err(data->dev,
  16127. + "Regulator get failed vdd rc=%d\n", rc);
  16128. + goto exit;
  16129. + }
  16130. +
  16131. + data->vddio = regulator_get(data->dev, "vddio");
  16132. + if (IS_ERR(data->vddio)) {
  16133. + rc = PTR_ERR(data->vddio);
  16134. + dev_err(data->dev,
  16135. + "Regulator get failed vddio rc=%d\n", rc);
  16136. + goto err_get_vddio;
  16137. + }
  16138. +
  16139. + return 0;
  16140. +
  16141. +pwr_deinit:
  16142. + regulator_put(data->vddio);
  16143. +err_get_vddio:
  16144. + regulator_put(data->vdd);
  16145. +exit:
  16146. + return rc;
  16147. +}
  16148. +
  16149. +static void ft5x46_dt_dump(struct device *dev,
  16150. + struct ft5x46_ts_platform_data *pdata)
  16151. +{
  16152. + int j;
  16153. +
  16154. + dev_dbg(dev, "i2c-pull-up = %d\n", (int)pdata->i2c_pull_up);
  16155. + dev_dbg(dev, "reset gpio = %d\n", (int)pdata->reset_gpio);
  16156. + dev_dbg(dev, "irq gpio = %d\n", (int)pdata->irq_gpio);
  16157. + dev_dbg(dev, "x_max = %d\n", (int)pdata->x_max);
  16158. + dev_dbg(dev, "y_max = %d\n", (int)pdata->y_max);
  16159. + dev_dbg(dev, "z_max = %d\n", (int)pdata->z_max);
  16160. + dev_dbg(dev, "w_max = %d\n", (int)pdata->w_max);
  16161. + dev_dbg(dev, "landing_jiffies = %d\n", (int)pdata->landing_jiffies);
  16162. + dev_dbg(dev, "landing_threshold = %d\n", (int)pdata->landing_threshold);
  16163. + dev_dbg(dev, "staying_threshold = %d\n", (int)pdata->staying_threshold);
  16164. + dev_dbg(dev, "raw min = %d\n", (int)pdata->raw_min);
  16165. + dev_dbg(dev, "raw max = %d\n", (int)pdata->raw_max);
  16166. + dev_dbg(dev, "fw delay 55 ms = %d\n", (int)pdata->ui.delay_55);
  16167. + dev_dbg(dev, "fw delay aa ms = %d\n", (int)pdata->ui.delay_aa);
  16168. + dev_dbg(dev, "fw upgrade id 1 = %d\n", (int)pdata->ui.upgrade_id_1);
  16169. + dev_dbg(dev, "fw upgrade id 2 = %d\n", (int)pdata->ui.upgrade_id_2);
  16170. + dev_dbg(dev, "fw delay readid ms = %d\n", (int)pdata->ui.delay_readid);
  16171. + dev_dbg(dev, "fw delay readid ms = %d\n", (int)pdata->ui.delay_erase);
  16172. +
  16173. + for (j = 0; j < pdata->cfg_size; j++) {
  16174. + dev_dbg(dev, "firmare %d chip = 0x%x, vendor = 0x%x name = %s\n",
  16175. + j, pdata->firmware[j].chip,
  16176. + pdata->firmware[j].vendor,
  16177. + pdata->firmware[j].fwname);
  16178. + }
  16179. +}
  16180. +
  16181. +static int ft5x46_initialize_pinctrl(struct ft5x46_data *ft5x46)
  16182. +{
  16183. + int ret = 0;
  16184. +
  16185. + ft5x46->ts_pinctrl = devm_pinctrl_get(ft5x46->dev);
  16186. + if (IS_ERR_OR_NULL(ft5x46->ts_pinctrl)) {
  16187. + pr_err("Target does not use pinctrl\n");
  16188. + ret = PTR_ERR(ft5x46->ts_pinctrl);
  16189. + ft5x46->ts_pinctrl = NULL;
  16190. + return ret;
  16191. + }
  16192. +
  16193. + ft5x46->gpio_state_active
  16194. + = pinctrl_lookup_state(ft5x46->ts_pinctrl, "pmx_ts_active");
  16195. + if (IS_ERR_OR_NULL(ft5x46->gpio_state_active)) {
  16196. + pr_err("Can not get ts default pinstate\n");
  16197. + ret = PTR_ERR(ft5x46->gpio_state_active);
  16198. + ft5x46->ts_pinctrl = NULL;
  16199. + return ret;
  16200. + }
  16201. +
  16202. + ft5x46->gpio_state_suspend
  16203. + = pinctrl_lookup_state(ft5x46->ts_pinctrl, "pmx_ts_suspend");
  16204. + if (IS_ERR_OR_NULL(ft5x46->gpio_state_suspend)) {
  16205. + pr_err("Can not get ts sleep pinstate\n");
  16206. + ret = PTR_ERR(ft5x46->gpio_state_suspend);
  16207. + ft5x46->ts_pinctrl = NULL;
  16208. + return ret;
  16209. + }
  16210. +
  16211. + return 0;
  16212. +}
  16213. +
  16214. +static int ft5x46_pinctrl_select(struct ft5x46_data *ft5x46, bool on)
  16215. +{
  16216. + int ret = 0;
  16217. + struct pinctrl_state *pins_state;
  16218. +
  16219. + pins_state = on ? ft5x46->gpio_state_active : ft5x46->gpio_state_suspend;
  16220. + if (!IS_ERR_OR_NULL(pins_state)) {
  16221. + ret = pinctrl_select_state(ft5x46->ts_pinctrl, pins_state);
  16222. + if (ret) {
  16223. + dev_err(ft5x46->dev, "Cannot set %s pins\n",
  16224. + on ? "pmx_ts_active" : "pmx_ts_suspend");
  16225. + return ret;
  16226. + }
  16227. + } else {
  16228. + dev_err(ft5x46->dev, "not a valid '%s' pinstate\n",
  16229. + on ? "pmx_ts_active" : "pmx_ts_suspend");
  16230. + }
  16231. +
  16232. + return 0;
  16233. +}
  16234. +
  16235. +#if defined(CONFIG_FB)
  16236. +static int fb_notifier_cb(struct notifier_block *self,
  16237. + unsigned long event, void *data)
  16238. +{
  16239. + struct fb_event *evdata = data;
  16240. + int *blank;
  16241. + struct ft5x46_data *ft5x46 =
  16242. + container_of(self, struct ft5x46_data, fb_notif);
  16243. +
  16244. + if (evdata && evdata->data && event == FB_EVENT_BLANK && ft5x46) {
  16245. + blank = evdata->data;
  16246. + if (*blank == FB_BLANK_UNBLANK) {
  16247. + dev_dbg(ft5x46->dev, "##### UNBLANK SCREEN #####\n");
  16248. + ft5x46_input_enable(ft5x46->input);
  16249. + } else if (*blank == FB_BLANK_POWERDOWN) {
  16250. + dev_dbg(ft5x46->dev, "##### BLANK SCREEN #####\n");
  16251. + ft5x46_input_disable(ft5x46->input);
  16252. + }
  16253. + }
  16254. +
  16255. + return 0;
  16256. +}
  16257. +
  16258. +static int ft5x46_configure_sleep(struct ft5x46_data *ft5x46, bool enable)
  16259. +{
  16260. + int ret;
  16261. +
  16262. + ft5x46->fb_notif.notifier_call = fb_notifier_cb;
  16263. + if (enable) {
  16264. + ret = fb_register_client(&ft5x46->fb_notif);
  16265. + if (ret) {
  16266. + dev_err(ft5x46->dev,
  16267. + "Unable to register fb_notifier, err: %d\n", ret);
  16268. + }
  16269. + } else {
  16270. + ret = fb_unregister_client(&ft5x46->fb_notif);
  16271. + if (ret) {
  16272. + dev_err(ft5x46->dev,
  16273. + "Unable to unregister fb_notifier, err: %d\n", ret);
  16274. + }
  16275. + }
  16276. + return ret;
  16277. +}
  16278. +#elif defined(CONFIG_HAS_EARLYSUSPEND)
  16279. +static int ft5x46_configure_sleep(struct ft5x46_data *ft5x46, bool enable)
  16280. +{
  16281. + if (enable) {
  16282. + ft5x46->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN+1;
  16283. + ft5x46->early_suspend.suspend = ft5x46_early_suspend;
  16284. + ft5x46->early_suspend.resume = ft5x46_early_resume;
  16285. + register_early_suspend(&ft5x46->early_suspend);
  16286. + } else {
  16287. + unregister_early_suspend(&ft5x46->early_suspend);
  16288. + }
  16289. +
  16290. + return 0;
  16291. +}
  16292. +#else
  16293. +static int ft5x46_configure_sleep(struct ft5x46_data *ft5x46, bool enable)
  16294. +{
  16295. + if (enable)
  16296. +
  16297. + ft5x46_input_enable(ft5x46->input);
  16298. + else
  16299. +
  16300. + ft5x46_input_disable(ft5x46->input);
  16301. + return 0;
  16302. +}
  16303. +#endif
  16304. +
  16305. +#ifdef CONFIG_OF
  16306. +static int ft5x46_parse_dt(struct device *dev,
  16307. + struct ft5x46_ts_platform_data *pdata)
  16308. +{
  16309. + int rc, j;
  16310. + struct device_node *np = dev->of_node;
  16311. + u32 temp_val, num_fw;
  16312. + struct device_node *sub_np;
  16313. +
  16314. + pdata->i2c_pull_up = of_property_read_bool(np,
  16315. + "ft5x46_i2c,i2c-pull-up");
  16316. + pdata->reset_gpio = of_get_named_gpio_flags(np, "ft5x46_i2c,reset-gpio",
  16317. + 0, &pdata->reset_gpio_flags);
  16318. + if (pdata->reset_gpio < 0)
  16319. + return pdata->reset_gpio;
  16320. +
  16321. + pdata->irq_gpio = of_get_named_gpio_flags(np, "ft5x46_i2c,irq-gpio",
  16322. + 0, &pdata->irq_gpio_flags);
  16323. + if (pdata->irq_gpio < 0)
  16324. + return pdata->irq_gpio;
  16325. +
  16326. + rc = of_property_read_u32(np, "ft5x46_i2c,x-max", &pdata->x_max);
  16327. + if (rc) {
  16328. + dev_err(dev, "can't read x-max\n");
  16329. + return rc;
  16330. + }
  16331. + rc = of_property_read_u32(np, "ft5x46_i2c,y-max", &pdata->y_max);
  16332. + if (rc) {
  16333. + dev_err(dev, "can't read y-max\n");
  16334. + return rc;
  16335. + }
  16336. + rc = of_property_read_u32(np, "ft5x46_i2c,z-max", &pdata->z_max);
  16337. + if (rc) {
  16338. + dev_err(dev, "can't read z-max\n");
  16339. + return rc;
  16340. + }
  16341. + rc = of_property_read_u32(np, "ft5x46_i2c,w-max", &pdata->w_max);
  16342. + if (rc) {
  16343. + dev_err(dev, "can't read w-max\n");
  16344. + return rc;
  16345. + }
  16346. +
  16347. + rc = of_property_read_u32(np, "ft5x46_i2c,landing-jiffies", &temp_val);
  16348. + if (rc) {
  16349. + dev_err(dev, "can't read landing-jiffies\n");
  16350. + return rc;
  16351. + } else
  16352. + pdata->landing_jiffies = (unsigned long)temp_val;
  16353. + rc = of_property_read_u32(np, "ft5x46_i2c,landing-threshold", &pdata->landing_threshold);
  16354. + if (rc) {
  16355. + dev_err(dev, "can't read landing-threshold\n");
  16356. + return rc;
  16357. + }
  16358. + rc = of_property_read_u32(np, "ft5x46_i2c,staying-threshold", &pdata->staying_threshold);
  16359. + if (rc) {
  16360. + dev_err(dev, "can't read staying-threshold\n");
  16361. + return rc;
  16362. + }
  16363. +
  16364. + rc = of_property_read_u32(np, "ft5x46_i2c,raw-min", &temp_val);
  16365. + if (rc) {
  16366. + dev_err(dev, "can't read raw-min\n");
  16367. + return rc;
  16368. + } else
  16369. + pdata->raw_min = (u16)temp_val;
  16370. + rc = of_property_read_u32(np, "ft5x46_i2c,raw-max", &temp_val);
  16371. + if (rc) {
  16372. + dev_err(dev, "can't read raw-max\n");
  16373. + return rc;
  16374. + } else
  16375. + pdata->raw_max = (u16)temp_val;
  16376. + rc = of_property_read_u32(np, "ft5x46_i2c,open-min", &temp_val);
  16377. + if (rc)
  16378. + dev_err(dev, "can't read open-min\n");
  16379. + else
  16380. + pdata->open_min = (u16)temp_val;
  16381. + rc = of_property_read_u32(np, "ft5x46_i2c,open-max", &temp_val);
  16382. + if (rc)
  16383. + dev_err(dev, "can't read open-max\n");
  16384. + else
  16385. + pdata->open_max = (u16)temp_val;
  16386. + rc = of_property_read_u32(np, "ft5x46_i2c,short-min", &temp_val);
  16387. + if (rc)
  16388. + dev_err(dev, "can't read short-min\n");
  16389. + else
  16390. + pdata->short_min = (u16)temp_val;
  16391. + rc = of_property_read_u32(np, "ft5x46_i2c,short-max", &temp_val);
  16392. + if (rc)
  16393. + dev_err(dev, "can't read short-max\n");
  16394. + else
  16395. + pdata->short_max = (u32)temp_val;
  16396. + rc = of_property_read_u32(np, "ft5x46_i2c,imin-cc", &temp_val);
  16397. + if (rc)
  16398. + dev_err(dev, "can't read imin-cc\n");
  16399. + else
  16400. + pdata->imin_cc = (u32)temp_val;
  16401. + rc = of_property_read_u32(np, "ft5x46_i2c,imin-cg", &temp_val);
  16402. + if (rc)
  16403. + dev_err(dev, "can't read short-max\n");
  16404. + else
  16405. + pdata->imin_cg = (u32)temp_val;
  16406. +
  16407. + pdata->has_key = of_property_read_bool(np, "ft5x46_i2c,has-key");
  16408. + if (pdata->has_key) {
  16409. + rc = of_property_read_u32(np, "ft5x46_i2c,key-rx1", &temp_val);
  16410. + if (rc)
  16411. + dev_err(dev, "can't read key-rx1\n");
  16412. + else
  16413. + pdata->key_rx1 = (u32)temp_val;
  16414. + rc = of_property_read_u32(np, "ft5x46_i2c,key-rx2", &temp_val);
  16415. + if (rc)
  16416. + dev_err(dev, "can't read key-rx2\n");
  16417. + else
  16418. + pdata->key_rx2 = (u32)temp_val;
  16419. + rc = of_property_read_u32(np, "ft5x46_i2c,key-rx3", &temp_val);
  16420. + if (rc)
  16421. + dev_err(dev, "can't read key-rx3\n");
  16422. + else
  16423. + pdata->key_rx3 = (u32)temp_val;
  16424. + }
  16425. + rc = of_property_read_u32(np, "ft5x46_i2c,fw-delay-55-ms", &temp_val);
  16426. + if (rc) {
  16427. + dev_err(dev, "can't read delay_55\n");
  16428. + return rc;
  16429. + } else
  16430. + pdata->ui.delay_55 = (u16)temp_val;
  16431. +
  16432. + rc = of_property_read_u32(np, "ft5x46_i2c,fw-delay-aa-ms", &temp_val);
  16433. + if (rc) {
  16434. + dev_err(dev, "can't read delay_aa\n");
  16435. + return rc;
  16436. + } else
  16437. + pdata->ui.delay_aa = (u16)temp_val;
  16438. +
  16439. + rc = of_property_read_u32(np, "ft5x46_i2c,fw-upgrade-id1", &temp_val);
  16440. + if (rc) {
  16441. + dev_err(dev, "can't read fw-upgrade-id1\n");
  16442. + return rc;
  16443. + } else
  16444. + pdata->ui.upgrade_id_1 = (u8)temp_val;
  16445. +
  16446. + rc = of_property_read_u32(np, "ft5x46_i2c,fw-upgrade-id2", &temp_val);
  16447. + if (rc) {
  16448. + dev_err(dev, "can't read fw-upgrade-id2\n");
  16449. + return rc;
  16450. + } else
  16451. + pdata->ui.upgrade_id_2 = (u8)temp_val;
  16452. +
  16453. + rc = of_property_read_u32(np, "ft5x46_i2c,fw-delay-readid-ms", &temp_val);
  16454. + if (rc) {
  16455. + dev_err(dev, "can't read fw-delay-readid-ms\n");
  16456. + return rc;
  16457. + } else
  16458. + pdata->ui.delay_readid = (u16)temp_val;
  16459. +
  16460. + rc = of_property_read_u32(np, "ft5x46_i2c,fw-delay-erase-ms", &temp_val);
  16461. + if (rc) {
  16462. + dev_err(dev, "can't read fw-delay-erase-ms\n");
  16463. + return rc;
  16464. + } else
  16465. + pdata->ui.delay_erase = (u16)temp_val;
  16466. + rc = of_property_read_u32(np, "ft5x46_i2c,firmware-array-size", &num_fw);
  16467. + if (rc) {
  16468. + dev_err(dev, "can't get firmware-array-size\n");
  16469. + return rc;
  16470. + }
  16471. +
  16472. + pdata->firmware = kzalloc(sizeof(struct ft5x46_firmware_data) * (num_fw + 1),
  16473. + GFP_KERNEL);
  16474. + if (pdata->firmware == NULL)
  16475. + return -ENOMEM;
  16476. + pdata->testdata = kzalloc(sizeof(struct ft5x46_test_data) * num_fw, GFP_KERNEL);
  16477. + if (pdata->testdata == NULL)
  16478. + return -ENOMEM;
  16479. +
  16480. + pdata->cfg_size = num_fw;
  16481. + j = 0;
  16482. + for_each_child_of_node(np, sub_np) {
  16483. + rc = of_property_read_u32(sub_np, "ft5x46_i2c,chip", &temp_val);
  16484. + if (rc) {
  16485. + dev_err(dev, "can't get chip id\n");
  16486. + return rc;
  16487. + } else
  16488. + pdata->firmware[j].chip = (u8)temp_val;
  16489. +
  16490. + rc = of_property_read_u32(sub_np, "ft5x46_i2c,vendor", &temp_val);
  16491. + if (rc) {
  16492. + dev_err(dev, "can't get vendor id\n");
  16493. + return rc;
  16494. + } else
  16495. + pdata->firmware[j].vendor = (u8)temp_val;
  16496. +
  16497. + rc = of_property_read_string(sub_np, "ft5x46_i2c,fw-name",
  16498. + &pdata->firmware[j].fwname);
  16499. + if (rc && (rc != -EINVAL)) {
  16500. + dev_err(dev, "can't read fw-name\n");
  16501. + return rc;
  16502. + }
  16503. + pdata->firmware[j].size = 0;
  16504. +
  16505. + rc = of_property_read_u32(sub_np, "ft5x46_i2c,tx-num", &pdata->testdata[j].tx_num);
  16506. + if (rc) {
  16507. + dev_err(dev, "can't read tx-num\n");
  16508. + return rc;
  16509. + }
  16510. + rc = of_property_read_u32(sub_np, "ft5x46_i2c,rx-num", &pdata->testdata[j].rx_num);
  16511. + if (rc) {
  16512. + dev_err(dev, "can't read rx-num\n");
  16513. + return rc;
  16514. + }
  16515. +
  16516. + j++;
  16517. + }
  16518. +
  16519. + ft5x46_dt_dump(dev, pdata);
  16520. +
  16521. + return 0;
  16522. +}
  16523. +#else
  16524. +static int ft5x46_parse_dt(struct device *dev,
  16525. + struct ft5x46_ts_platform_data *pdata)
  16526. +{
  16527. + return -ENODEV;
  16528. +}
  16529. +#endif
  16530. +
  16531. +static int ft5x46_read_config_info(struct ft5x46_data *ft5x46)
  16532. +{
  16533. + int error;
  16534. +
  16535. + error = ft5x46_read_block(ft5x46, FT5X0X_REG_CONFIG_INFO,
  16536. + ft5x46->config_info, FT5X46_CONFIG_INFO_SIZE);
  16537. + if (error) {
  16538. + dev_err(ft5x46->dev, "Read config info register %d failed\n",
  16539. + FT5X0X_REG_CONFIG_INFO);
  16540. + return error;
  16541. + }
  16542. +
  16543. + dev_info(ft5x46->dev, "Config info: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
  16544. + ft5x46->config_info[0], ft5x46->config_info[1],
  16545. + ft5x46->config_info[2], ft5x46->config_info[3],
  16546. + ft5x46->config_info[4], ft5x46->config_info[5],
  16547. + ft5x46->config_info[6], ft5x46->config_info[7]);
  16548. +
  16549. + return 0;
  16550. +}
  16551. +
  16552. +static void ft5x46_cover_mode(struct ft5x46_data *ft5x46, bool enable)
  16553. +{
  16554. + ft5x46_write_byte(ft5x46, FT5X46_COVER_REG, enable);
  16555. +}
  16556. +
  16557. +static void ft5x46_switch_mode_work(struct work_struct *work)
  16558. +{
  16559. + struct ft5x46_mode_switch *ms = container_of(work, struct ft5x46_mode_switch, switch_mode_work);
  16560. + struct ft5x46_data *ft5x46 = ms->data;
  16561. + u8 value = ms->mode;
  16562. +
  16563. + if (value == FT5X46_INPUT_EVENT_WAKUP_MODE_ON || value == FT5X46_INPUT_EVENT_WAKUP_MODE_OFF) {
  16564. + if (ft5x46) {
  16565. + ft5x46->wakeup_mode = value - FT5X46_INPUT_EVENT_WAKUP_MODE_OFF;
  16566. +
  16567. + if (ft5x46->in_suspend)
  16568. + ft5x46_wakeup_reconfigure(ft5x46,
  16569. + (bool)(value - FT5X46_INPUT_EVENT_WAKUP_MODE_OFF));
  16570. + }
  16571. + } else if (value == FT5X46_INPUT_EVENT_COVER_MODE_ON || value == FT5X46_INPUT_EVENT_COVER_MODE_OFF) {
  16572. + if (ft5x46) {
  16573. + ft5x46->cover_mode = value - FT5X46_INPUT_EVENT_COVER_MODE_OFF;
  16574. + ft5x46_cover_mode(ft5x46, ft5x46->cover_mode);
  16575. + }
  16576. + }
  16577. +
  16578. + if (ms != NULL) {
  16579. + kfree(ms);
  16580. + ms = NULL;
  16581. + }
  16582. +}
  16583. +
  16584. +static int ft5x46_input_event(struct input_dev *dev,
  16585. + unsigned int type, unsigned int code, int value)
  16586. +{
  16587. + struct ft5x46_data *ft5x46 = input_get_drvdata(dev);
  16588. + struct ft5x46_mode_switch *ms;
  16589. +
  16590. + if (type == EV_SYN && code == SYN_CONFIG) {
  16591. + dev_info(ft5x46->dev,
  16592. + "event write value = %d\n", value);
  16593. +
  16594. + if (value >= FT5X46_INPUT_EVENT_START && value <= FT5X46_INPUT_EVENT_END) {
  16595. + ms = (struct ft5x46_mode_switch *)kmalloc(sizeof(struct ft5x46_mode_switch), GFP_ATOMIC);
  16596. + if (ms != NULL) {
  16597. + ms->data = ft5x46;
  16598. + ms->mode = (u8)value;
  16599. + INIT_WORK(&ms->switch_mode_work, ft5x46_switch_mode_work);
  16600. + schedule_work(&ms->switch_mode_work);
  16601. + } else {
  16602. + dev_err(ft5x46->dev,
  16603. + "Failed in allocating memory for ft5x46_mode_switch!\n");
  16604. + return -ENOMEM;
  16605. + }
  16606. + }
  16607. + }
  16608. +
  16609. + return 0;
  16610. +}
  16611. +
  16612. +#ifdef FT5X46_APK_DEBUG_CHANNEL
  16613. +static ssize_t ft5x46_apk_debug_read(struct file *file, char __user *buffer,
  16614. + size_t buflen, loff_t *fpos)
  16615. +{
  16616. + struct ft5x46_data *ft5x46 = ft_data;
  16617. + int ret = 0;
  16618. + unsigned char *buf = NULL;
  16619. + int num_read_chars = 0;
  16620. + u8 val;
  16621. +
  16622. + buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  16623. +
  16624. + switch (proc_operate_mode) {
  16625. + case FT5X46_PROC_UPGRADE:
  16626. + ret = ft5x46_read_byte(ft5x46, FT5X0X_REG_FW_VER, &val);
  16627. + if (ret < 0)
  16628. + num_read_chars = snprintf(buf, PAGE_SIZE,
  16629. + "%s", "Get FW version failed.\n");
  16630. + else
  16631. + num_read_chars = snprintf(buf, PAGE_SIZE,
  16632. + "current fw version:0x%02x\n", val);
  16633. + break;
  16634. +
  16635. + case FT5X46_PROC_READ_REGISTER:
  16636. + ret = ft5x46_recv_byte(ft5x46, 1, &val);
  16637. + if (ret < 0) {
  16638. + dev_err(ft5x46->dev, "%s: read register failed\n", __func__);
  16639. + } else {
  16640. + buf[0] = val;
  16641. + num_read_chars = 1;
  16642. + }
  16643. + break;
  16644. +
  16645. + case FT5X46_PROC_READ_DATA:
  16646. + ret = ft5x46_recv_block(ft5x46, buf, buflen);
  16647. + if (ret < 0) {
  16648. + dev_err(ft5x46->dev, "%s: read data failed\n", __func__);
  16649. + } else {
  16650. + num_read_chars = buflen;
  16651. + }
  16652. + break;
  16653. +
  16654. + case FT5X46_PROC_WRITE_REGISTER:
  16655. + case FT5X46_PROC_WRITE_DATA:
  16656. + default:
  16657. + break;
  16658. + }
  16659. +
  16660. + if (ret == 0) {
  16661. + ret = copy_to_user(buffer, buf, min((int)buflen, num_read_chars));
  16662. + }
  16663. +
  16664. + kfree(buf);
  16665. + return ret;
  16666. +}
  16667. +
  16668. +#define FT5X46_MAX_FIRMWARE_LENGTH 128
  16669. +
  16670. +static ssize_t ft5x46_apk_debug_write(struct file *file, const char __user *buffer,
  16671. + size_t buflen, loff_t *fpos)
  16672. +{
  16673. + struct ft5x46_data *ft5x46 = ft_data;
  16674. + unsigned char writebuf[FT5X0X_PACKET_LENGTH];
  16675. + char upgrade_file_name[FT5X46_MAX_FIRMWARE_LENGTH];
  16676. + int ret = 0;
  16677. +
  16678. + if (copy_from_user(&writebuf, buffer,
  16679. + ((buflen < FT5X0X_PACKET_LENGTH) ? buflen : FT5X0X_PACKET_LENGTH))) {
  16680. + dev_err(ft5x46->dev, "%s: copy from user failed\n", __func__);
  16681. + return -EFAULT;
  16682. + }
  16683. +
  16684. + proc_operate_mode = writebuf[0];
  16685. + switch (proc_operate_mode) {
  16686. + case FT5X46_PROC_UPGRADE:
  16687. + memset(upgrade_file_name, 0, FT5X46_MAX_FIRMWARE_LENGTH);
  16688. + snprintf(upgrade_file_name, FT5X46_MAX_FIRMWARE_LENGTH,
  16689. + "%s", writebuf + 1);
  16690. + upgrade_file_name[buflen - 1] = '\0';
  16691. + dev_info(ft5x46->dev, "%s: upgrade file name: %s\n",
  16692. + __func__, upgrade_file_name);
  16693. + ret = ft5x46_updatefw_with_filename(ft5x46, upgrade_file_name, NULL);
  16694. + if (ret < 0) {
  16695. + dev_err(ft5x46->dev, "%s: upgrade failed\n",
  16696. + __func__);
  16697. + return ret;
  16698. + }
  16699. + break;
  16700. +
  16701. + case FT5X46_PROC_READ_REGISTER:
  16702. + dev_info(ft5x46->dev, "%s: read register from %d\n",
  16703. + __func__, writebuf[1]);
  16704. + ret = ft5x46_send_byte(ft5x46, 1, writebuf[1]);
  16705. + if (ret < 0) {
  16706. + dev_err(ft5x46->dev, "%s: read register failed\n", __func__);
  16707. + return ret;
  16708. + }
  16709. + break;
  16710. +
  16711. + case FT5X46_PROC_WRITE_REGISTER:
  16712. + dev_info(ft5x46->dev, "%s: write to register %d: %d\n",
  16713. + __func__, writebuf[1], writebuf[2]);
  16714. + ret = ft5x46_write_byte(ft5x46, writebuf[1], writebuf[2]);
  16715. + if (ret < 0) {
  16716. + dev_err(ft5x46->dev, "%s: write register failed\n", __func__);
  16717. + return ret;
  16718. + }
  16719. + break;
  16720. +
  16721. + case FT5X46_PROC_AUTOCLB:
  16722. +#ifdef CONFIG_TOUCHSCREEN_FT5X46_CALIBRATE
  16723. + dev_info(ft5x46->dev, "%s: Auto calibration\n", __func__);
  16724. + ft5x46_auto_calib(ft5x46);
  16725. +#endif
  16726. + break;
  16727. +
  16728. + case FT5X46_PROC_READ_DATA:
  16729. + case FT5X46_PROC_WRITE_DATA:
  16730. + dev_info(ft5x46->dev, "%s: Read/Write data\n", __func__);
  16731. + ret = ft5x46_send_block(ft5x46, writebuf + 1, buflen - 1);
  16732. + if (ret < 0) {
  16733. + dev_err(ft5x46->dev, "%s: read/write data failed\n", __func__);
  16734. + return ret;
  16735. + }
  16736. + break;
  16737. +
  16738. + default:
  16739. + break;
  16740. + }
  16741. +
  16742. + return buflen;
  16743. +}
  16744. +
  16745. +static const struct file_operations ft5x46_proc_operations = {
  16746. + .read = ft5x46_apk_debug_read,
  16747. + .write = ft5x46_apk_debug_write,
  16748. +};
  16749. +
  16750. +static int ft5x46_create_apk_debug_channel(struct ft5x46_data *ft5x46)
  16751. +{
  16752. + ft5x46_proc_entry = proc_create(FT5X46_PROC_NAME, 0600, NULL, &ft5x46_proc_operations);
  16753. + if (!ft5x46_proc_entry) {
  16754. + dev_err(ft5x46->dev, "Unable to create proc entry\n");
  16755. + return -ENOMEM;
  16756. + } else {
  16757. + dev_info(ft5x46->dev, "Create proc entry successfully\n");
  16758. + }
  16759. +
  16760. + return 0;
  16761. +}
  16762. +
  16763. +static void ft5x46_release_apk_debug_channel(struct ft5x46_data *ft5x46)
  16764. +{
  16765. + if (ft5x46_proc_entry)
  16766. + remove_proc_entry(FT5X46_PROC_NAME, NULL);
  16767. +}
  16768. +#endif
  16769. +
  16770. +#ifdef CONFIG_PM
  16771. +int ft5x46_pm_suspend(struct device *dev)
  16772. +{
  16773. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  16774. +
  16775. + if (ft5x46->wakeup_mode) {
  16776. + dev_info(dev, "touch enable irq wake\n");
  16777. + disable_irq(ft5x46->irq);
  16778. + enable_irq_wake(ft5x46->irq);
  16779. + }
  16780. +
  16781. + return 0;
  16782. +}
  16783. +EXPORT_SYMBOL_GPL(ft5x46_pm_suspend);
  16784. +
  16785. +int ft5x46_pm_resume(struct device *dev)
  16786. +{
  16787. + struct ft5x46_data *ft5x46 = dev_get_drvdata(dev);
  16788. +
  16789. + if (ft5x46->wakeup_mode) {
  16790. + dev_info(dev, "touch disable irq wake\n");
  16791. + disable_irq_wake(ft5x46->irq);
  16792. + enable_irq(ft5x46->irq);
  16793. + }
  16794. +
  16795. + return 0;
  16796. +}
  16797. +EXPORT_SYMBOL_GPL(ft5x46_pm_resume);
  16798. +#endif
  16799. +
  16800. +struct ft5x46_data *ft5x46_probe(struct device *dev,
  16801. + const struct ft5x46_bus_ops *bops)
  16802. +{
  16803. + int error;
  16804. + struct ft5x46_data *ft5x46;
  16805. + struct ft5x46_ts_platform_data *pdata;
  16806. +
  16807. + /* check input argument */
  16808. + if (dev->of_node) {
  16809. + pdata = devm_kzalloc(dev,
  16810. + sizeof(struct ft5x46_ts_platform_data), GFP_KERNEL);
  16811. + if (!pdata) {
  16812. + dev_err(dev, "Failed to allocate memory!\n");
  16813. + return ERR_PTR(-ENOMEM);
  16814. + }
  16815. +
  16816. + error = ft5x46_parse_dt(dev, pdata);
  16817. + if (error)
  16818. + goto err;
  16819. + } else
  16820. + pdata = dev->platform_data;
  16821. +
  16822. + if (pdata == NULL) {
  16823. + dev_err(dev, "platform data doesn't exist\n");
  16824. + error = -EINVAL;
  16825. + goto err;
  16826. + }
  16827. +
  16828. + /* alloc and init data object */
  16829. + ft5x46 = kzalloc(sizeof(struct ft5x46_data), GFP_KERNEL);
  16830. + if (ft5x46 == NULL) {
  16831. + dev_err(dev, "fail to allocate data object\n");
  16832. + error = -ENOMEM;
  16833. + goto err;
  16834. + }
  16835. + ft_data = ft5x46;
  16836. + ft5x46->dev = dev;
  16837. + ft5x46->irq = gpio_to_irq(pdata->irq_gpio);
  16838. + ft5x46->bops = bops;
  16839. + if (dev->of_node)
  16840. + ft5x46->dev->platform_data = pdata;
  16841. +
  16842. + if (gpio_is_valid(pdata->irq_gpio)) {
  16843. + error = gpio_request(pdata->irq_gpio, "ft5x46_irq_gpio");
  16844. + if (error < 0) {
  16845. + dev_err(dev, "irq gpio request failed");
  16846. + goto err_free_data;
  16847. + }
  16848. + error = gpio_direction_input(pdata->irq_gpio);
  16849. + if (error < 0) {
  16850. + dev_err(dev, "set_direction for irq gpio failed\n");
  16851. + goto free_irq_gpio;
  16852. + }
  16853. + }
  16854. +
  16855. + if (gpio_is_valid(pdata->reset_gpio)) {
  16856. + error = gpio_request(pdata->reset_gpio, "ft5x46_reset_gpio");
  16857. + if (error < 0) {
  16858. + dev_err(dev, "irq gpio request failed");
  16859. + goto free_irq_gpio;
  16860. + }
  16861. + error = gpio_direction_output(pdata->reset_gpio, 0);
  16862. + if (error < 0) {
  16863. + dev_err(dev, "set_direction for irq gpio failed\n");
  16864. + goto free_reset_gpio;
  16865. + }
  16866. + }
  16867. +
  16868. + /* init platform stuff */
  16869. + if (pdata->power_init) {
  16870. + error = pdata->power_init(true);
  16871. + if (error) {
  16872. + dev_err(dev, "fail to power_init platform (pdata)\n");
  16873. + goto free_reset_gpio;
  16874. + }
  16875. + } else {
  16876. + error = ft5x46_power_init(ft5x46, true);
  16877. + if (error) {
  16878. + dev_err(dev, "fail to power_init platform\n");
  16879. + goto free_reset_gpio;
  16880. + }
  16881. + }
  16882. +
  16883. + if (pdata->power_on) {
  16884. + error = pdata->power_on(true);
  16885. + if (error) {
  16886. + dev_err(dev, "fail to power on (pdata)!\n");
  16887. + goto err_power_init;
  16888. + }
  16889. + } else {
  16890. + error = ft5x46_power_on(ft5x46, true);
  16891. + if (error) {
  16892. + dev_err(dev, "fail to power on\n");
  16893. + goto err_power_init;
  16894. + }
  16895. + }
  16896. +
  16897. + error = ft5x46_initialize_pinctrl(ft5x46);
  16898. + if (error || !ft5x46->ts_pinctrl) {
  16899. + dev_err(dev, "Initialize pinctrl failed\n");
  16900. + goto err_power;
  16901. + } else {
  16902. + error = ft5x46_pinctrl_select(ft5x46, true);
  16903. + if (error < 0) {
  16904. + dev_err(dev, "pinctrl select failed\n");
  16905. + goto err_power;
  16906. + }
  16907. + }
  16908. +
  16909. + msleep(10);
  16910. + gpio_set_value_cansleep(pdata->reset_gpio, 1);
  16911. +
  16912. + msleep(200);
  16913. + mutex_init(&ft5x46->mutex);
  16914. +
  16915. + /* alloc and init input device */
  16916. + ft5x46->input = input_allocate_device();
  16917. + if (ft5x46->input == NULL) {
  16918. + dev_err(dev, "fail to allocate input device\n");
  16919. + error = -ENOMEM;
  16920. + goto err_pinctrl_init;
  16921. + }
  16922. +
  16923. + input_set_drvdata(ft5x46->input, ft5x46);
  16924. + ft5x46->input->name = "backtouch";
  16925. + ft5x46->input->id.bustype = bops->bustype;
  16926. + ft5x46->input->id.vendor = 0x4654; /* FocalTech */
  16927. + ft5x46->input->id.product = 0x5000; /* ft5x0x */
  16928. + ft5x46->input->id.version = 0x0100; /* 1.0 */
  16929. + ft5x46->input->dev.parent = dev;
  16930. + ft5x46->input->event = ft5x46_input_event;
  16931. +
  16932. + /* init touch parameter */
  16933. + input_mt_init_slots(ft5x46->input, FT5X0X_MAX_FINGER, 0);
  16934. + set_bit(ABS_MT_TOUCH_MAJOR, ft5x46->input->absbit);
  16935. + set_bit(ABS_MT_POSITION_X, ft5x46->input->absbit);
  16936. + set_bit(ABS_MT_POSITION_Y, ft5x46->input->absbit);
  16937. + set_bit(ABS_MT_WIDTH_MAJOR, ft5x46->input->absbit);
  16938. + set_bit(INPUT_PROP_DIRECT, ft5x46->input->propbit);
  16939. +
  16940. + input_set_abs_params(ft5x46->input,
  16941. + ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
  16942. + input_set_abs_params(ft5x46->input,
  16943. + ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
  16944. + input_set_abs_params(ft5x46->input,
  16945. + ABS_MT_TOUCH_MAJOR, 0, pdata->z_max, 0, 0);
  16946. + input_set_abs_params(ft5x46->input,
  16947. + ABS_MT_WIDTH_MAJOR, 0, pdata->w_max, 0, 0);
  16948. + input_set_abs_params(ft5x46->input,
  16949. + ABS_MT_TRACKING_ID, 0, 10, 0, 0);
  16950. + input_set_capability(ft5x46->input, EV_KEY, KEY_WAKEUP);
  16951. +
  16952. + set_bit(EV_KEY, ft5x46->input->evbit);
  16953. + set_bit(EV_ABS, ft5x46->input->evbit);
  16954. + set_bit(BTN_TOUCH, ft5x46->input->keybit);
  16955. +
  16956. + set_bit(KEY_HOME, ft5x46->input->keybit);
  16957. + set_bit(KEY_MENU, ft5x46->input->keybit);
  16958. + set_bit(KEY_BACK, ft5x46->input->keybit);
  16959. +
  16960. + msleep(200);
  16961. + error = ft5x46_hid_to_std_i2c(ft5x46);
  16962. + if (error) {
  16963. + dev_err(dev, "Failed to switch to StdI2C\n");
  16964. +
  16965. + }
  16966. + error = ft5x46_read_byte(ft5x46, FT5X0X_REG_CHIP_ID, &ft5x46->chip_id);
  16967. + if (error) {
  16968. + dev_err(dev, "failed to read chip id\n");
  16969. + goto err_free_input;
  16970. + } else {
  16971. + dev_info(dev, "ft5x46 chip id = %02x\n", ft5x46->chip_id);
  16972. + }
  16973. + error = ft5x46_read_config_info(ft5x46);
  16974. + if (error) {
  16975. + dev_err(dev, "Failed to read config info\n");
  16976. + goto err_free_input;
  16977. + }
  16978. +
  16979. + /* register input device */
  16980. + error = input_register_device(ft5x46->input);
  16981. + if (error) {
  16982. + dev_err(dev, "fail to register input device\n");
  16983. + goto err_free_input;
  16984. + }
  16985. +
  16986. + ft5x46->input->phys =
  16987. + kobject_get_path(&ft5x46->input->dev.kobj, GFP_KERNEL);
  16988. + if (ft5x46->input->phys == NULL) {
  16989. + dev_err(dev, "fail to get input device path\n");
  16990. + error = -ENOMEM;
  16991. + goto err_unregister_input;
  16992. + }
  16993. +
  16994. + /* start interrupt process */
  16995. + error = request_threaded_irq(ft5x46->irq, NULL, ft5x46_interrupt,
  16996. + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "ft5x46", ft5x46);
  16997. + if (error) {
  16998. + dev_err(dev, "fail to request interrupt\n");
  16999. + goto err_free_phys;
  17000. + }
  17001. + ft5x46->irq_enabled = true;
  17002. + /* export sysfs entries */
  17003. + error = sysfs_create_group(&dev->kobj, &ft5x46_attr_group);
  17004. + if (error) {
  17005. + dev_err(dev, "fail to export sysfs entires\n");
  17006. + goto err_free_irq;
  17007. + }
  17008. + error = ft5x46_configure_sleep(ft5x46, true);
  17009. + if (error) {
  17010. + dev_err(dev, "Failed to configure sleep\n");
  17011. + goto err_sysfs_create_group;
  17012. + }
  17013. +
  17014. + ft5x46->vkeys_dir = kobject_create_and_add("board_properties",
  17015. + NULL);
  17016. + if (!ft5x46->vkeys_dir) {
  17017. + error = -ENOMEM;
  17018. + dev_err(dev, "Failed to create board_properties entry\n");
  17019. + goto err_configure_sleep;
  17020. + }
  17021. +
  17022. + sysfs_attr_init(&ft5x46->vkeys_attr.attr);
  17023. + ft5x46->vkeys_attr.attr.name = "virtualkeys.ft5x46";
  17024. + ft5x46->vkeys_attr.attr.mode = S_IRUGO;
  17025. + ft5x46->vkeys_attr.show = ft5x46_vkeys_show;
  17026. +
  17027. + error = sysfs_create_file(ft5x46->vkeys_dir,
  17028. + &ft5x46->vkeys_attr.attr);
  17029. + if (error) {
  17030. + dev_err(dev, "Failed to create virtual keys entry\n");
  17031. + goto err_put_vkeys_dir;
  17032. + }
  17033. +
  17034. +#ifdef FT5X46_APK_DEBUG_CHANNEL
  17035. + error = ft5x46_create_apk_debug_channel(ft5x46);
  17036. + if (error) {
  17037. + dev_err(dev, "Failed to create APK debug channel\n");
  17038. + goto err_sysfs_create_virtualkeys;
  17039. + }
  17040. +#endif
  17041. + INIT_DELAYED_WORK(&ft5x46->noise_filter_delayed_work,
  17042. + ft5x46_noise_filter_delayed_work);
  17043. +
  17044. + return ft5x46;
  17045. +
  17046. +#ifdef FT5X46_APK_DEBUG_CHANNEL
  17047. +err_sysfs_create_virtualkeys:
  17048. + sysfs_remove_file(ft5x46->vkeys_dir, &ft5x46->vkeys_attr.attr);
  17049. +#endif
  17050. +err_put_vkeys_dir:
  17051. + kobject_put(ft5x46->vkeys_dir);
  17052. +err_configure_sleep:
  17053. + ft5x46_configure_sleep(ft5x46, false);
  17054. +err_sysfs_create_group:
  17055. + sysfs_remove_group(&dev->kobj, &ft5x46_attr_group);
  17056. +err_free_irq:
  17057. + free_irq(ft5x46->irq, ft5x46);
  17058. +err_free_phys:
  17059. + kfree(ft5x46->input->phys);
  17060. +err_unregister_input:
  17061. + input_unregister_device(ft5x46->input);
  17062. + ft5x46->input = NULL;
  17063. +err_free_input:
  17064. + input_free_device(ft5x46->input);
  17065. +err_pinctrl_init:
  17066. + if (ft5x46->ts_pinctrl) {
  17067. + devm_pinctrl_put(ft5x46->ts_pinctrl);
  17068. + ft5x46->ts_pinctrl = NULL;
  17069. + }
  17070. +err_power:
  17071. + if (pdata->power_on)
  17072. + pdata->power_on(false);
  17073. + else
  17074. + ft5x46_power_on(ft5x46, false);
  17075. +err_power_init:
  17076. + if (pdata->power_init)
  17077. + pdata->power_init(false);
  17078. + else
  17079. + ft5x46_power_init(ft5x46, false);
  17080. +free_reset_gpio:
  17081. + if (gpio_is_valid(pdata->reset_gpio))
  17082. + gpio_free(pdata->reset_gpio);
  17083. +free_irq_gpio:
  17084. + if (gpio_is_valid(pdata->irq_gpio))
  17085. + gpio_free(pdata->irq_gpio);
  17086. +err_free_data:
  17087. + kfree(ft5x46);
  17088. +err:
  17089. + return ERR_PTR(error);
  17090. +}
  17091. +EXPORT_SYMBOL_GPL(ft5x46_probe);
  17092. +
  17093. +void ft5x46_remove(struct ft5x46_data *ft5x46)
  17094. +{
  17095. + struct ft5x46_ts_platform_data *pdata = ft5x46->dev->platform_data;
  17096. +
  17097. + cancel_delayed_work_sync(&ft5x46->noise_filter_delayed_work);
  17098. + ft5x46_configure_sleep(ft5x46, false);
  17099. +#ifdef FT5X46_APK_DEBUG_CHANNEL
  17100. + ft5x46_release_apk_debug_channel(ft5x46);
  17101. +#endif
  17102. + sysfs_remove_group(&ft5x46->dev->kobj, &ft5x46_attr_group);
  17103. + free_irq(ft5x46->irq, ft5x46);
  17104. + kfree(ft5x46->input->phys);
  17105. + input_unregister_device(ft5x46->input);
  17106. + if (pdata->firmware) {
  17107. + if (pdata->firmware->data)
  17108. + kfree(pdata->firmware->data);
  17109. + kfree(pdata->firmware);
  17110. + }
  17111. + if (pdata->testdata)
  17112. + kfree(pdata->testdata);
  17113. + if (gpio_is_valid(pdata->reset_gpio))
  17114. + gpio_free(pdata->reset_gpio);
  17115. + if (gpio_is_valid(pdata->irq_gpio))
  17116. + gpio_free(pdata->irq_gpio);
  17117. + if (pdata->power_on)
  17118. + pdata->power_on(false);
  17119. + else
  17120. + ft5x46_power_on(ft5x46, false);
  17121. + if (pdata->power_init)
  17122. + pdata->power_init(false);
  17123. + else
  17124. + ft5x46_power_init(ft5x46, false);
  17125. + kfree(ft5x46);
  17126. +}
  17127. +EXPORT_SYMBOL_GPL(ft5x46_remove);
  17128. +
  17129. +MODULE_AUTHOR("Zhang Bo <zhangbo_a@xiaomi.com>");
  17130. +MODULE_DESCRIPTION("ft5x0x touchscreen input driver");
  17131. +MODULE_LICENSE("GPL");
  17132. diff --git a/drivers/input/touchscreen/ft5x46/ft5x46_ts_i2c.c b/drivers/input/touchscreen/ft5x46/ft5x46_ts_i2c.c
  17133. new file mode 100644
  17134. index 0000000..c21b8f3
  17135. --- /dev/null
  17136. +++ b/drivers/input/touchscreen/ft5x46/ft5x46_ts_i2c.c
  17137. @@ -0,0 +1,256 @@
  17138. +/*
  17139. + * Copyright (C) 2017 XiaoMi, Inc.
  17140. + *
  17141. + * This software is licensed under the terms of the GNU General Public
  17142. + * License version 2, as published by the Free Software Foundation, and
  17143. + * may be copied, distributed, and modified under those terms.
  17144. + *
  17145. + * This program is distributed in the hope that it will be useful,
  17146. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17147. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17148. + * GNU General Public License for more details.
  17149. + *
  17150. + */
  17151. +
  17152. +#include <linux/i2c.h>
  17153. +#include <linux/input.h>
  17154. +#include <linux/module.h>
  17155. +#include <linux/interrupt.h>
  17156. +#include <linux/input/ft5x46_ts.h>
  17157. +#include "focaltech_test.h"
  17158. +struct i2c_client *fts_i2c_client;
  17159. +static int ft5x46_i2c_recv(struct device *dev,
  17160. + void *buf, int len)
  17161. +{
  17162. + struct i2c_client *client = to_i2c_client(dev);
  17163. + int count = i2c_master_recv(client, buf, len);
  17164. + return count < 0 ? count : 0;
  17165. +}
  17166. +
  17167. +static int ft5x46_i2c_send(struct device *dev,
  17168. + const void *buf, int len)
  17169. +{
  17170. + struct i2c_client *client = to_i2c_client(dev);
  17171. + int count = i2c_master_send(client, buf, len);
  17172. + return count < 0 ? count : 0;
  17173. +}
  17174. +
  17175. +/*******************************************************************************
  17176. +* Name: fts_i2c_read
  17177. +* Brief:
  17178. +* Input:
  17179. +* Output:
  17180. +* Return:
  17181. +*******************************************************************************/
  17182. +int fts_i2c_read(struct i2c_client *client, char *writebuf,
  17183. + int writelen, char *readbuf, int readlen)
  17184. +{
  17185. + int ret;
  17186. +
  17187. + if (readlen > 0) {
  17188. + if (writelen > 0) {
  17189. + struct i2c_msg msgs[] = {
  17190. + {
  17191. + .addr = client->addr,
  17192. + .flags = 0,
  17193. + .len = writelen,
  17194. + .buf = writebuf,
  17195. + },
  17196. + {
  17197. + .addr = client->addr,
  17198. + .flags = I2C_M_RD,
  17199. + .len = readlen,
  17200. + .buf = readbuf,
  17201. + },
  17202. + };
  17203. + ret = i2c_transfer(client->adapter, msgs, 2);
  17204. + if (ret < 0)
  17205. + dev_err(&client->dev, "%s:i2c read error.\n",
  17206. + __func__);
  17207. + } else {
  17208. + struct i2c_msg msgs[] = {
  17209. + {
  17210. + .addr = client->addr,
  17211. + .flags = I2C_M_RD,
  17212. + .len = readlen,
  17213. + .buf = readbuf,
  17214. + },
  17215. + };
  17216. + ret = i2c_transfer(client->adapter, msgs, 1);
  17217. + if (ret < 0)
  17218. + dev_err(&client->dev, "%s:i2c read error.\n",
  17219. + __func__);
  17220. + }
  17221. + }
  17222. + return ret;
  17223. +}
  17224. +
  17225. +int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen)
  17226. +{
  17227. + int ret;
  17228. +
  17229. + struct i2c_msg msgs[] = {
  17230. + {
  17231. + .addr = client->addr,
  17232. + .flags = 0,
  17233. + .len = writelen,
  17234. + .buf = writebuf,
  17235. + },
  17236. + };
  17237. +
  17238. + if (writelen > 0) {
  17239. + ret = i2c_transfer(client->adapter, msgs, 1);
  17240. + if (ret < 0)
  17241. + dev_err(&client->dev, "%s: i2c write error.\n",
  17242. + __func__);
  17243. + }
  17244. + return ret;
  17245. +}
  17246. +
  17247. +static int ft5x46_i2c_read(struct device *dev,
  17248. + u8 addr, void *buf, u8 len)
  17249. +{
  17250. + struct i2c_client *client = to_i2c_client(dev);
  17251. + int i, count = 0;
  17252. +
  17253. + for (i = 0; i < len; i += count) {
  17254. + count = i2c_smbus_read_i2c_block_data(
  17255. + client, addr + i, len - i, buf + i);
  17256. + if (count < 0)
  17257. + break;
  17258. + }
  17259. +
  17260. + return count < 0 ? count : 0;
  17261. +}
  17262. +
  17263. +static int ft5x46_i2c_write(struct device *dev,
  17264. + u8 addr, const void *buf, u8 len)
  17265. +{
  17266. + struct i2c_client *client = to_i2c_client(dev);
  17267. + int i, error = 0;
  17268. +
  17269. + for (i = 0; i < len; i += I2C_SMBUS_BLOCK_MAX) {
  17270. + /* transfer at most I2C_SMBUS_BLOCK_MAX one time */
  17271. + error = i2c_smbus_write_i2c_block_data(
  17272. + client, addr + i, len - i, buf + i);
  17273. + if (error)
  17274. + break;
  17275. + }
  17276. +
  17277. + return error;
  17278. +}
  17279. +
  17280. +static const struct ft5x46_bus_ops ft5x46_i2c_bops = {
  17281. + .bustype = BUS_I2C,
  17282. + .recv = ft5x46_i2c_recv,
  17283. + .send = ft5x46_i2c_send,
  17284. + .read = ft5x46_i2c_read,
  17285. + .write = ft5x46_i2c_write,
  17286. +};
  17287. +
  17288. +static int ft5x46_i2c_probe(struct i2c_client *client,
  17289. + const struct i2c_device_id *id)
  17290. +{
  17291. + struct ft5x46_data *ft5x46;
  17292. +
  17293. + if (!i2c_check_functionality(client->adapter,
  17294. + I2C_FUNC_SMBUS_I2C_BLOCK)) {
  17295. + dev_err(&client->dev, "incompatible i2c adapter.");
  17296. + return -ENODEV;
  17297. + }
  17298. +
  17299. + ft5x46 = ft5x46_probe(&client->dev, &ft5x46_i2c_bops);
  17300. + if (IS_ERR(ft5x46))
  17301. + return PTR_ERR(ft5x46);
  17302. +
  17303. +
  17304. + i2c_set_clientdata(client, ft5x46);
  17305. + fts_i2c_client = client;
  17306. + fts_test_module_init(client);
  17307. + device_init_wakeup(&client->dev, 1);
  17308. +
  17309. + return 0;
  17310. +}
  17311. +
  17312. +static int ft5x46_i2c_remove(struct i2c_client *client)
  17313. +{
  17314. + struct ft5x46_data *ft5x0x = i2c_get_clientdata(client);
  17315. + fts_test_module_exit(client);
  17316. + ft5x46_remove(ft5x0x);
  17317. + return 0;
  17318. +}
  17319. +
  17320. +static const struct i2c_device_id ft5x46_i2c_id[] = {
  17321. + {"ft5x46_i2c", 0},
  17322. + {/* end list */}
  17323. +};
  17324. +MODULE_DEVICE_TABLE(i2c, ft5x0x_i2c_id);
  17325. +
  17326. +#ifdef CONFIG_OF
  17327. +static struct of_device_id ft5x46_match_table[] = {
  17328. + { .compatible = "ft,ft5x46_i2c", },
  17329. + { },
  17330. +};
  17331. +#else
  17332. +#define ft5x46_match_table NULL
  17333. +#endif
  17334. +
  17335. +#ifdef CONFIG_PM
  17336. +static int ft5x46_i2c_suspend(struct device *dev)
  17337. +{
  17338. + int ret = 0;
  17339. +
  17340. + if (device_may_wakeup(dev))
  17341. + ret = ft5x46_pm_suspend(dev);
  17342. +
  17343. + return ret;
  17344. +}
  17345. +
  17346. +static int ft5x46_i2c_resume(struct device *dev)
  17347. +{
  17348. + int ret = 0;
  17349. +
  17350. + if (device_may_wakeup(dev))
  17351. + ret = ft5x46_pm_resume(dev);
  17352. +
  17353. + return ret;
  17354. +}
  17355. +
  17356. +static const struct dev_pm_ops ft5x46_i2c_pm_ops = {
  17357. +#ifndef CONFIG_HAS_EARLYSUSPEND
  17358. + .suspend = ft5x46_i2c_suspend,
  17359. + .resume = ft5x46_i2c_resume,
  17360. +#endif
  17361. +};
  17362. +#endif
  17363. +
  17364. +static struct i2c_driver ft5x46_i2c_driver = {
  17365. + .driver = {
  17366. + .name = "ft5x46_i2c",
  17367. + .owner = THIS_MODULE,
  17368. + .of_match_table = ft5x46_match_table,
  17369. +#ifdef CONFIG_PM
  17370. + .pm = &ft5x46_i2c_pm_ops,
  17371. +#endif
  17372. + },
  17373. + .probe = ft5x46_i2c_probe,
  17374. + .remove = ft5x46_i2c_remove,
  17375. + .id_table = ft5x46_i2c_id,
  17376. +};
  17377. +
  17378. +static int __init ft5x46_i2c_init(void)
  17379. +{
  17380. + return i2c_add_driver(&ft5x46_i2c_driver);
  17381. +}
  17382. +late_initcall(ft5x46_i2c_init);
  17383. +
  17384. +static void __exit ft5x46_i2c_exit(void)
  17385. +{
  17386. + i2c_del_driver(&ft5x46_i2c_driver);
  17387. +}
  17388. +module_exit(ft5x46_i2c_exit);
  17389. +
  17390. +MODULE_ALIAS("i2c:ft5x46_i2c");
  17391. +MODULE_AUTHOR("Tao Jun <taojun@xiaomi.com>");
  17392. +MODULE_DESCRIPTION("i2c driver for ft5x46 touchscreen");
  17393. +MODULE_LICENSE("GPL");
  17394. diff --git a/drivers/input/touchscreen/ft5x46/ft5x46_ts_spi.c b/drivers/input/touchscreen/ft5x46/ft5x46_ts_spi.c
  17395. new file mode 100644
  17396. index 0000000..f7208e1
  17397. --- /dev/null
  17398. +++ b/drivers/input/touchscreen/ft5x46/ft5x46_ts_spi.c
  17399. @@ -0,0 +1,133 @@
  17400. +/*
  17401. + * Copyright (C) 2017 XiaoMi, Inc.
  17402. + *
  17403. + * This software is licensed under the terms of the GNU General Public
  17404. + * License version 2, as published by the Free Software Foundation, and
  17405. + * may be copied, distributed, and modified under those terms.
  17406. + *
  17407. + * This program is distributed in the hope that it will be useful,
  17408. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17409. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17410. + * GNU General Public License for more details.
  17411. + *
  17412. + */
  17413. +
  17414. +#include <linux/input.h>
  17415. +#include <linux/module.h>
  17416. +#include <linux/spi/spi.h>
  17417. +#include "ft5x46_ts.h"
  17418. +
  17419. +#define FT5X0X_SPI_READ 0x8000
  17420. +
  17421. +static int ft5x46_spi_xfer(struct device *dev,
  17422. + u16 addr, const u8 *tx_buf, u8 *rx_buf, u8 len)
  17423. +{
  17424. + struct spi_device *spi = to_spi_device(dev);
  17425. + struct spi_transfer xfers[2];
  17426. + struct spi_message msg;
  17427. +
  17428. + spi_message_init(&msg);
  17429. + memset(xfers, 0, sizeof(xfers));
  17430. +
  17431. + /* 16th bit indicate read(1) or write(0) */
  17432. + if (tx_buf)
  17433. + addr &= ~FT5X0X_SPI_READ;
  17434. + else
  17435. + addr |= FT5X0X_SPI_READ;
  17436. + addr = cpu_to_be16(addr); /* MSB first */
  17437. +
  17438. + xfers[0].tx_buf = &addr;
  17439. + xfers[0].len = sizeof(addr);
  17440. + spi_message_add_tail(&xfers[0], &msg);
  17441. +
  17442. + xfers[1].tx_buf = tx_buf;
  17443. + xfers[1].rx_buf = rx_buf;
  17444. + xfers[1].len = len;
  17445. + spi_message_add_tail(&xfers[1], &msg);
  17446. +
  17447. + return spi_sync(spi, &msg);
  17448. +}
  17449. +
  17450. +static int ft5x46_spi_recv(struct device *dev,
  17451. + void *buf, int len)
  17452. +{
  17453. + return ft5x46_spi_xfer(dev, 0, NULL, buf, len);
  17454. +}
  17455. +
  17456. +static int ft5x46_spi_send(struct device *dev,
  17457. + const void *buf, int len)
  17458. +{
  17459. + return ft5x46_spi_xfer(dev, 0, buf, NULL, len);
  17460. +}
  17461. +
  17462. +static int ft5x46_spi_read(struct device *dev,
  17463. + u8 addr, void *buf, u8 len)
  17464. +{
  17465. + return ft5x46_spi_xfer(dev, addr, NULL, buf, len);
  17466. +}
  17467. +
  17468. +static int ft5x46_spi_write(struct device *dev,
  17469. + u8 addr, const void *buf, u8 len)
  17470. +{
  17471. + return ft5x46_spi_xfer(dev, addr, buf, NULL, len);
  17472. +}
  17473. +
  17474. +static const struct ft5x46_bus_ops ft5x46_spi_bops = {
  17475. + .bustype = BUS_SPI,
  17476. + .recv = ft5x46_spi_recv,
  17477. + .send = ft5x46_spi_send,
  17478. + .read = ft5x46_spi_read,
  17479. + .write = ft5x46_spi_write,
  17480. +};
  17481. +
  17482. +static int ft5x46_spi_probe(struct spi_device *spi)
  17483. +{
  17484. + struct ft5x46_data *ft5x46;
  17485. +
  17486. + ft5x46 = ft5x46_probe(&spi->dev, &ft5x46_spi_bops);
  17487. + if (IS_ERR(ft5x46))
  17488. + return PTR_ERR(ft5x46);
  17489. +
  17490. + spi_set_drvdata(spi, ft5x46);
  17491. + return 0;
  17492. +}
  17493. +
  17494. +static int ft5x46_spi_remove(struct spi_device *spi)
  17495. +{
  17496. + struct ft5x46_data *ft5x46 = spi_get_drvdata(spi);
  17497. + ft5x46_remove(ft5x46);
  17498. + return 0;
  17499. +}
  17500. +
  17501. +static const struct spi_device_id ft5x46_spi_id[] = {
  17502. + {"ft5x46_spi", 0},
  17503. + {/* end list */}
  17504. +};
  17505. +MODULE_DEVICE_TABLE(spi, ft5x46_spi_id);
  17506. +
  17507. +static struct spi_driver ft5x46_spi_driver = {
  17508. + .probe = ft5x46_spi_probe,
  17509. + .remove = ft5x46_spi_remove,
  17510. + .driver = {
  17511. + .name = "ft5x46_spi",
  17512. + .owner = THIS_MODULE,
  17513. + },
  17514. + .id_table = ft5x46_spi_id,
  17515. +};
  17516. +
  17517. +static int __init ft5x46_spi_init(void)
  17518. +{
  17519. + return spi_register_driver(&ft5x46_spi_driver);
  17520. +}
  17521. +module_init(ft5x0x_spi_init);
  17522. +
  17523. +static void __exit ft5x46_spi_exit(void)
  17524. +{
  17525. + spi_unregister_driver(&ft5x46_spi_driver);
  17526. +}
  17527. +module_exit(ft5x46_spi_exit);
  17528. +
  17529. +MODULE_ALIAS("spi:ft5x46_spi");
  17530. +MODULE_AUTHOR("Tao Jun <taojun@xiaomi.com>");
  17531. +MODULE_DESCRIPTION("spi driver for ft5x0x touchscreen");
  17532. +MODULE_LICENSE("GPL");
  17533. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/Kconfig b/drivers/input/touchscreen/synaptics_dsx_force/Kconfig
  17534. new file mode 100644
  17535. index 0000000..b34228f
  17536. --- /dev/null
  17537. +++ b/drivers/input/touchscreen/synaptics_dsx_force/Kconfig
  17538. @@ -0,0 +1,124 @@
  17539. +#
  17540. +# Synaptics DSX touchscreen driver configuration
  17541. +#
  17542. +menuconfig TOUCHSCREEN_SYNAPTICS_DSX_FORCE
  17543. + bool "Synaptics DSX touchscreen"
  17544. + default y
  17545. + help
  17546. + Say Y here if you have a Synaptics DSX touchscreen connected
  17547. + to your system.
  17548. +
  17549. + If unsure, say N.
  17550. +
  17551. +if TOUCHSCREEN_SYNAPTICS_DSX_FORCE
  17552. +
  17553. +choice
  17554. + default TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE
  17555. + prompt "Synaptics DSX bus interface"
  17556. +config TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE
  17557. + bool "RMI over I2C"
  17558. + depends on I2C
  17559. +config TOUCHSCREEN_SYNAPTICS_DSX_SPI_FORCE
  17560. + bool "RMI over SPI"
  17561. + depends on SPI_MASTER
  17562. +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C_FORCE
  17563. + bool "HID over I2C"
  17564. + depends on I2C
  17565. +endchoice
  17566. +
  17567. +config TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17568. + tristate "Synaptics DSX core driver module"
  17569. + depends on I2C || SPI_MASTER
  17570. + help
  17571. + Say Y here to enable basic touch reporting functionality.
  17572. +
  17573. + If unsure, say N.
  17574. +
  17575. + To compile this driver as a module, choose M here: the
  17576. + module will be called synaptics_dsx_core.
  17577. +
  17578. +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_FORCE
  17579. + tristate "Synaptics DSX RMI device module"
  17580. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17581. + help
  17582. + Say Y here to enable support for direct RMI register access.
  17583. +
  17584. + If unsure, say N.
  17585. +
  17586. + To compile this driver as a module, choose M here: the
  17587. + module will be called synaptics_dsx_rmi_dev.
  17588. +
  17589. +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_FORCE
  17590. + tristate "Synaptics DSX firmware update module"
  17591. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17592. + help
  17593. + Say Y here to enable support for doing firmware update.
  17594. +
  17595. + If unsure, say N.
  17596. +
  17597. + To compile this driver as a module, choose M here: the
  17598. + module will be called synaptics_dsx_fw_update.
  17599. +
  17600. +config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_FORCE
  17601. + tristate "Synaptics DSX test reporting module"
  17602. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17603. + help
  17604. + Say Y here to enable support for retrieving production test reports.
  17605. +
  17606. + If unsure, say N.
  17607. +
  17608. + To compile this driver as a module, choose M here: the
  17609. + module will be called synaptics_dsx_test_reporting.
  17610. +
  17611. +config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY_FORCE
  17612. + tristate "Synaptics DSX proximity module"
  17613. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17614. + help
  17615. + Say Y here to enable support for proximity functionality.
  17616. +
  17617. + If unsure, say N.
  17618. +
  17619. + To compile this driver as a module, choose M here: the
  17620. + module will be called synaptics_dsx_proximity.
  17621. +
  17622. +config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN_FORCE
  17623. + tristate "Synaptics DSX active pen module"
  17624. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17625. + help
  17626. + Say Y here to enable support for active pen functionality.
  17627. +
  17628. + If unsure, say N.
  17629. +
  17630. + To compile this driver as a module, choose M here: the
  17631. + module will be called synaptics_dsx_active_pen.
  17632. +
  17633. +config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE_FORCE
  17634. + tristate "Synaptics DSX user defined gesture module"
  17635. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17636. + help
  17637. + Say Y here to enable support for user defined gesture functionality.
  17638. +
  17639. + If unsure, say N.
  17640. +
  17641. + To compile this driver as a module, choose M here: the
  17642. + module will be called synaptics_dsx_gesture.
  17643. +
  17644. +config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO_FORCE
  17645. + tristate "Synaptics DSX video module"
  17646. + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE
  17647. + help
  17648. + Say Y here to enable support for video communication functionality.
  17649. +
  17650. + If unsure, say N.
  17651. +
  17652. + To compile this driver as a module, choose M here: the
  17653. + module will be called synaptics_dsx_video.
  17654. +
  17655. +config TOUCH_DEBUG_FS
  17656. + bool "touch debugfs suport"
  17657. + default n
  17658. + depends on DEBUG_FS
  17659. + help
  17660. + Say Y here to enable support for touch debugfs.
  17661. +
  17662. +endif
  17663. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/Makefile b/drivers/input/touchscreen/synaptics_dsx_force/Makefile
  17664. new file mode 100644
  17665. index 0000000..f613ea9
  17666. --- /dev/null
  17667. +++ b/drivers/input/touchscreen/synaptics_dsx_force/Makefile
  17668. @@ -0,0 +1,17 @@
  17669. +#
  17670. +# Makefile for the Synaptics DSX touchscreen driver.
  17671. +#
  17672. +
  17673. +# Each configuration option enables a list of files.
  17674. +
  17675. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C_FORCE) += synaptics_dsx_i2c.o
  17676. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI_FORCE) += synaptics_dsx_spi.o
  17677. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C_FORCE) += synaptics_dsx_rmi_hid_i2c.o
  17678. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_FORCE) += synaptics_dsx_core.o
  17679. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_FORCE) += synaptics_dsx_rmi_dev.o
  17680. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_FORCE) += synaptics_dsx_fw_update.o
  17681. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_FORCE) += synaptics_dsx_test_reporting.o
  17682. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY_FORCE) += synaptics_dsx_proximity.o
  17683. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN_FORCE) += synaptics_dsx_active_pen.o
  17684. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_GESTURE_FORCE) += synaptics_dsx_gesture.o
  17685. +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_VIDEO_FORCE) += synaptics_dsx_video.o
  17686. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_active_pen.c b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_active_pen.c
  17687. new file mode 100644
  17688. index 0000000..38a0d4b
  17689. --- /dev/null
  17690. +++ b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_active_pen.c
  17691. @@ -0,0 +1,631 @@
  17692. +/*
  17693. + * Synaptics DSX touchscreen driver
  17694. + *
  17695. + * Copyright (C) 2012-2015 Synaptics Incorporated. All rights reserved.
  17696. + *
  17697. + * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
  17698. + * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
  17699. + * Copyright (C) 2017 XiaoMi, Inc.
  17700. + *
  17701. + * This program is free software; you can redistribute it and/or modify
  17702. + * it under the terms of the GNU General Public License as published by
  17703. + * the Free Software Foundation; either version 2 of the License, or
  17704. + * (at your option) any later version.
  17705. + *
  17706. + * This program is distributed in the hope that it will be useful,
  17707. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17708. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17709. + * GNU General Public License for more details.
  17710. + *
  17711. + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  17712. + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  17713. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  17714. + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  17715. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  17716. + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  17717. + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  17718. + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  17719. + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  17720. + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  17721. + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  17722. + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  17723. + * DOLLARS.
  17724. + */
  17725. +
  17726. +#include <linux/kernel.h>
  17727. +#include <linux/module.h>
  17728. +#include <linux/slab.h>
  17729. +#include <linux/interrupt.h>
  17730. +#include <linux/delay.h>
  17731. +#include <linux/input.h>
  17732. +#include <linux/platform_device.h>
  17733. +#include <linux/input/synaptics_dsx.h>
  17734. +#include "synaptics_dsx_core.h"
  17735. +
  17736. +#define APEN_PHYS_NAME "synaptics_dsx/active_pen"
  17737. +
  17738. +#define ACTIVE_PEN_MAX_PRESSURE_16BIT 65535
  17739. +#define ACTIVE_PEN_MAX_PRESSURE_8BIT 255
  17740. +
  17741. +struct synaptics_rmi4_f12_query_8 {
  17742. + union {
  17743. + struct {
  17744. + unsigned char size_of_query9;
  17745. + struct {
  17746. + unsigned char data0_is_present:1;
  17747. + unsigned char data1_is_present:1;
  17748. + unsigned char data2_is_present:1;
  17749. + unsigned char data3_is_present:1;
  17750. + unsigned char data4_is_present:1;
  17751. + unsigned char data5_is_present:1;
  17752. + unsigned char data6_is_present:1;
  17753. + unsigned char data7_is_present:1;
  17754. + } __packed;
  17755. + };
  17756. + unsigned char data[2];
  17757. + };
  17758. +};
  17759. +
  17760. +struct apen_data_8b_pressure {
  17761. + union {
  17762. + struct {
  17763. + unsigned char status_pen:1;
  17764. + unsigned char status_invert:1;
  17765. + unsigned char status_barrel:1;
  17766. + unsigned char status_reserved:5;
  17767. + unsigned char x_lsb;
  17768. + unsigned char x_msb;
  17769. + unsigned char y_lsb;
  17770. + unsigned char y_msb;
  17771. + unsigned char pressure_msb;
  17772. + unsigned char battery_state;
  17773. + unsigned char pen_id_0_7;
  17774. + unsigned char pen_id_8_15;
  17775. + unsigned char pen_id_16_23;
  17776. + unsigned char pen_id_24_31;
  17777. + } __packed;
  17778. + unsigned char data[11];
  17779. + };
  17780. +};
  17781. +
  17782. +struct apen_data {
  17783. + union {
  17784. + struct {
  17785. + unsigned char status_pen:1;
  17786. + unsigned char status_invert:1;
  17787. + unsigned char status_barrel:1;
  17788. + unsigned char status_reserved:5;
  17789. + unsigned char x_lsb;
  17790. + unsigned char x_msb;
  17791. + unsigned char y_lsb;
  17792. + unsigned char y_msb;
  17793. + unsigned char pressure_lsb;
  17794. + unsigned char pressure_msb;
  17795. + unsigned char battery_state;
  17796. + unsigned char pen_id_0_7;
  17797. + unsigned char pen_id_8_15;
  17798. + unsigned char pen_id_16_23;
  17799. + unsigned char pen_id_24_31;
  17800. + } __packed;
  17801. + unsigned char data[12];
  17802. + };
  17803. +};
  17804. +
  17805. +struct synaptics_rmi4_apen_handle {
  17806. + bool apen_present;
  17807. + unsigned char intr_mask;
  17808. + unsigned char battery_state;
  17809. + unsigned short query_base_addr;
  17810. + unsigned short control_base_addr;
  17811. + unsigned short data_base_addr;
  17812. + unsigned short command_base_addr;
  17813. + unsigned short apen_data_addr;
  17814. + unsigned short max_pressure;
  17815. + unsigned int pen_id;
  17816. + struct input_dev *apen_dev;
  17817. + struct apen_data *apen_data;
  17818. + struct synaptics_rmi4_data *rmi4_data;
  17819. +};
  17820. +
  17821. +static struct synaptics_rmi4_apen_handle *apen;
  17822. +
  17823. +DECLARE_COMPLETION(apen_remove_complete);
  17824. +
  17825. +static void apen_lift(void)
  17826. +{
  17827. + input_report_key(apen->apen_dev, BTN_TOUCH, 0);
  17828. + input_report_key(apen->apen_dev, BTN_TOOL_PEN, 0);
  17829. + input_report_key(apen->apen_dev, BTN_TOOL_RUBBER, 0);
  17830. + input_sync(apen->apen_dev);
  17831. + apen->apen_present = false;
  17832. +
  17833. + return;
  17834. +}
  17835. +
  17836. +static void apen_report(void)
  17837. +{
  17838. + int retval;
  17839. + int x;
  17840. + int y;
  17841. + int pressure;
  17842. + static int invert = -1;
  17843. + struct apen_data_8b_pressure *apen_data_8b;
  17844. + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;
  17845. +
  17846. + retval = synaptics_rmi4_reg_read(rmi4_data,
  17847. + apen->apen_data_addr,
  17848. + apen->apen_data->data,
  17849. + sizeof(apen->apen_data->data));
  17850. + if (retval < 0) {
  17851. + dev_err(rmi4_data->pdev->dev.parent,
  17852. + "%s: Failed to read active pen data\n",
  17853. + __func__);
  17854. + return;
  17855. + }
  17856. +
  17857. + if (apen->apen_data->status_pen == 0) {
  17858. + if (apen->apen_present)
  17859. + apen_lift();
  17860. +
  17861. + dev_dbg(rmi4_data->pdev->dev.parent,
  17862. + "%s: No active pen data\n",
  17863. + __func__);
  17864. +
  17865. + return;
  17866. + }
  17867. +
  17868. + x = (apen->apen_data->x_msb << 8) | (apen->apen_data->x_lsb);
  17869. + y = (apen->apen_data->y_msb << 8) | (apen->apen_data->y_lsb);
  17870. +
  17871. + if ((x == -1) && (y == -1)) {
  17872. + if (apen->apen_present)
  17873. + apen_lift();
  17874. +
  17875. + dev_dbg(rmi4_data->pdev->dev.parent,
  17876. + "%s: Active pen in range but no valid x & y\n",
  17877. + __func__);
  17878. +
  17879. + return;
  17880. + }
  17881. +
  17882. + if (!apen->apen_present)
  17883. + invert = -1;
  17884. +
  17885. + if (invert != -1 && invert != apen->apen_data->status_invert)
  17886. + apen_lift();
  17887. +
  17888. + invert = apen->apen_data->status_invert;
  17889. +
  17890. + if (apen->max_pressure == ACTIVE_PEN_MAX_PRESSURE_16BIT) {
  17891. + pressure = (apen->apen_data->pressure_msb << 8) |
  17892. + apen->apen_data->pressure_lsb;
  17893. + apen->battery_state = apen->apen_data->battery_state;
  17894. + apen->pen_id = (apen->apen_data->pen_id_24_31 << 24) |
  17895. + (apen->apen_data->pen_id_16_23 << 16) |
  17896. + (apen->apen_data->pen_id_8_15 << 8) |
  17897. + apen->apen_data->pen_id_0_7;
  17898. + } else {
  17899. + apen_data_8b = (struct apen_data_8b_pressure *)apen->apen_data;
  17900. + pressure = apen_data_8b->pressure_msb;
  17901. + apen->battery_state = apen_data_8b->battery_state;
  17902. + apen->pen_id = (apen_data_8b->pen_id_24_31 << 24) |
  17903. + (apen_data_8b->pen_id_16_23 << 16) |
  17904. + (apen_data_8b->pen_id_8_15 << 8) |
  17905. + apen_data_8b->pen_id_0_7;
  17906. + }
  17907. +
  17908. + input_report_key(apen->apen_dev, BTN_TOUCH, pressure > 0 ? 1 : 0);
  17909. + input_report_key(apen->apen_dev,
  17910. + apen->apen_data->status_invert > 0 ?
  17911. + BTN_TOOL_RUBBER : BTN_TOOL_PEN, 1);
  17912. + input_report_key(apen->apen_dev,
  17913. + BTN_STYLUS, apen->apen_data->status_barrel > 0 ?
  17914. + 1 : 0);
  17915. + input_report_abs(apen->apen_dev, ABS_X, x);
  17916. + input_report_abs(apen->apen_dev, ABS_Y, y);
  17917. + input_report_abs(apen->apen_dev, ABS_PRESSURE, pressure);
  17918. +
  17919. + input_sync(apen->apen_dev);
  17920. +
  17921. + dev_dbg(rmi4_data->pdev->dev.parent,
  17922. + "%s: Active pen: "
  17923. + "status = %d, "
  17924. + "invert = %d, "
  17925. + "barrel = %d, "
  17926. + "x = %d, "
  17927. + "y = %d, "
  17928. + "pressure = %d\n",
  17929. + __func__,
  17930. + apen->apen_data->status_pen,
  17931. + apen->apen_data->status_invert,
  17932. + apen->apen_data->status_barrel,
  17933. + x, y, pressure);
  17934. +
  17935. + apen->apen_present = true;
  17936. +
  17937. + return;
  17938. +}
  17939. +
  17940. +static void apen_set_params(void)
  17941. +{
  17942. + input_set_abs_params(apen->apen_dev, ABS_X, 0,
  17943. + apen->rmi4_data->sensor_max_x, 0, 0);
  17944. + input_set_abs_params(apen->apen_dev, ABS_Y, 0,
  17945. + apen->rmi4_data->sensor_max_y, 0, 0);
  17946. + input_set_abs_params(apen->apen_dev, ABS_PRESSURE, 0,
  17947. + apen->max_pressure, 0, 0);
  17948. +
  17949. + return;
  17950. +}
  17951. +
  17952. +static int apen_pressure(struct synaptics_rmi4_f12_query_8 *query_8)
  17953. +{
  17954. + int retval;
  17955. + unsigned char ii;
  17956. + unsigned char data_reg_presence;
  17957. + unsigned char size_of_query_9;
  17958. + unsigned char *query_9;
  17959. + unsigned char *data_desc;
  17960. + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;
  17961. +
  17962. + data_reg_presence = query_8->data[1];
  17963. +
  17964. + size_of_query_9 = query_8->size_of_query9;
  17965. + query_9 = kmalloc(size_of_query_9, GFP_KERNEL);
  17966. +
  17967. + retval = synaptics_rmi4_reg_read(rmi4_data,
  17968. + apen->query_base_addr + 9,
  17969. + query_9,
  17970. + size_of_query_9);
  17971. + if (retval < 0)
  17972. + goto exit;
  17973. +
  17974. + data_desc = query_9;
  17975. +
  17976. + for (ii = 0; ii < 6; ii++) {
  17977. + if (!(data_reg_presence & (1 << ii)))
  17978. + continue; /* The data register is not present */
  17979. + data_desc++; /* Jump over the size entry */
  17980. + while (*data_desc & (1 << 7))
  17981. + data_desc++;
  17982. + data_desc++; /* Go to the next descriptor */
  17983. + }
  17984. +
  17985. + data_desc++; /* Jump over the size entry */
  17986. + /* Check for the presence of subpackets 1 and 2 */
  17987. + if ((*data_desc & (3 << 1)) == (3 << 1))
  17988. + apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_16BIT;
  17989. + else
  17990. + apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_8BIT;
  17991. +
  17992. +exit:
  17993. + kfree(query_9);
  17994. +
  17995. + return retval;
  17996. +}
  17997. +
  17998. +static int apen_reg_init(void)
  17999. +{
  18000. + int retval;
  18001. + unsigned char data_offset;
  18002. + unsigned char size_of_query8;
  18003. + struct synaptics_rmi4_f12_query_8 query_8;
  18004. + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;
  18005. +
  18006. + retval = synaptics_rmi4_reg_read(rmi4_data,
  18007. + apen->query_base_addr + 7,
  18008. + &size_of_query8,
  18009. + sizeof(size_of_query8));
  18010. + if (retval < 0)
  18011. + return retval;
  18012. +
  18013. + retval = synaptics_rmi4_reg_read(rmi4_data,
  18014. + apen->query_base_addr + 8,
  18015. + query_8.data,
  18016. + sizeof(query_8.data));
  18017. + if (retval < 0)
  18018. + return retval;
  18019. +
  18020. + if ((size_of_query8 >= 2) && (query_8.data6_is_present)) {
  18021. + data_offset = query_8.data0_is_present +
  18022. + query_8.data1_is_present +
  18023. + query_8.data2_is_present +
  18024. + query_8.data3_is_present +
  18025. + query_8.data4_is_present +
  18026. + query_8.data5_is_present;
  18027. + apen->apen_data_addr = apen->data_base_addr + data_offset;
  18028. + retval = apen_pressure(&query_8);
  18029. + if (retval < 0)
  18030. + return retval;
  18031. + } else {
  18032. + dev_err(rmi4_data->pdev->dev.parent,
  18033. + "%s: Active pen support unavailable\n",
  18034. + __func__);
  18035. + retval = -ENODEV;
  18036. + }
  18037. +
  18038. + return retval;
  18039. +}
  18040. +
  18041. +static int apen_scan_pdt(void)
  18042. +{
  18043. + int retval;
  18044. + unsigned char ii;
  18045. + unsigned char page;
  18046. + unsigned char intr_count = 0;
  18047. + unsigned char intr_off;
  18048. + unsigned char intr_src;
  18049. + unsigned short addr;
  18050. + struct synaptics_rmi4_fn_desc fd;
  18051. + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;
  18052. +
  18053. + for (page = 0; page < PAGES_TO_SERVICE; page++) {
  18054. + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
  18055. + addr |= (page << 8);
  18056. +
  18057. + retval = synaptics_rmi4_reg_read(rmi4_data,
  18058. + addr,
  18059. + (unsigned char *)&fd,
  18060. + sizeof(fd));
  18061. + if (retval < 0)
  18062. + return retval;
  18063. +
  18064. + addr &= ~(MASK_8BIT << 8);
  18065. +
  18066. + if (fd.fn_number) {
  18067. + dev_dbg(rmi4_data->pdev->dev.parent,
  18068. + "%s: Found F%02x\n",
  18069. + __func__, fd.fn_number);
  18070. + switch (fd.fn_number) {
  18071. + case SYNAPTICS_RMI4_F12:
  18072. + goto f12_found;
  18073. + break;
  18074. + }
  18075. + } else {
  18076. + break;
  18077. + }
  18078. +
  18079. + intr_count += fd.intr_src_count;
  18080. + }
  18081. + }
  18082. +
  18083. + dev_err(rmi4_data->pdev->dev.parent,
  18084. + "%s: Failed to find F12\n",
  18085. + __func__);
  18086. + return -EINVAL;
  18087. +
  18088. +f12_found:
  18089. + apen->query_base_addr = fd.query_base_addr | (page << 8);
  18090. + apen->control_base_addr = fd.ctrl_base_addr | (page << 8);
  18091. + apen->data_base_addr = fd.data_base_addr | (page << 8);
  18092. + apen->command_base_addr = fd.cmd_base_addr | (page << 8);
  18093. +
  18094. + retval = apen_reg_init();
  18095. + if (retval < 0) {
  18096. + dev_err(rmi4_data->pdev->dev.parent,
  18097. + "%s: Failed to initialize active pen registers\n",
  18098. + __func__);
  18099. + return retval;
  18100. + }
  18101. +
  18102. + apen->intr_mask = 0;
  18103. + intr_src = fd.intr_src_count;
  18104. + intr_off = intr_count % 8;
  18105. + for (ii = intr_off;
  18106. + ii < (intr_src + intr_off);
  18107. + ii++) {
  18108. + apen->intr_mask |= 1 << ii;
  18109. + }
  18110. +
  18111. + rmi4_data->intr_mask[0] |= apen->intr_mask;
  18112. +
  18113. + addr = rmi4_data->f01_ctrl_base_addr + 1;
  18114. +
  18115. + retval = synaptics_rmi4_reg_write(rmi4_data,
  18116. + addr,
  18117. + &(rmi4_data->intr_mask[0]),
  18118. + sizeof(rmi4_data->intr_mask[0]));
  18119. + if (retval < 0) {
  18120. + dev_err(rmi4_data->pdev->dev.parent,
  18121. + "%s: Failed to set interrupt enable bit\n",
  18122. + __func__);
  18123. + return retval;
  18124. + }
  18125. +
  18126. + return 0;
  18127. +}
  18128. +
  18129. +static void synaptics_rmi4_apen_attn(struct synaptics_rmi4_data *rmi4_data,
  18130. + unsigned char intr_mask)
  18131. +{
  18132. + if (!apen)
  18133. + return;
  18134. +
  18135. + if (apen->intr_mask & intr_mask)
  18136. + apen_report();
  18137. +
  18138. + return;
  18139. +}
  18140. +
  18141. +static int synaptics_rmi4_apen_init(struct synaptics_rmi4_data *rmi4_data)
  18142. +{
  18143. + int retval;
  18144. +
  18145. + if (apen) {
  18146. + dev_dbg(rmi4_data->pdev->dev.parent,
  18147. + "%s: Handle already exists\n",
  18148. + __func__);
  18149. + return 0;
  18150. + }
  18151. +
  18152. + apen = kzalloc(sizeof(*apen), GFP_KERNEL);
  18153. + if (!apen) {
  18154. + dev_err(rmi4_data->pdev->dev.parent,
  18155. + "%s: Failed to alloc mem for apen\n",
  18156. + __func__);
  18157. + retval = -ENOMEM;
  18158. + goto exit;
  18159. + }
  18160. +
  18161. + apen->apen_data = kzalloc(sizeof(*(apen->apen_data)), GFP_KERNEL);
  18162. + if (!apen->apen_data) {
  18163. + dev_err(rmi4_data->pdev->dev.parent,
  18164. + "%s: Failed to alloc mem for apen_data\n",
  18165. + __func__);
  18166. + retval = -ENOMEM;
  18167. + goto exit_free_apen;
  18168. + }
  18169. +
  18170. + apen->rmi4_data = rmi4_data;
  18171. +
  18172. + retval = apen_scan_pdt();
  18173. + if (retval < 0)
  18174. + goto exit_free_apen_data;
  18175. +
  18176. + apen->apen_dev = input_allocate_device();
  18177. + if (apen->apen_dev == NULL) {
  18178. + dev_err(rmi4_data->pdev->dev.parent,
  18179. + "%s: Failed to allocate active pen device\n",
  18180. + __func__);
  18181. + retval = -ENOMEM;
  18182. + goto exit_free_apen_data;
  18183. + }
  18184. +
  18185. + apen->apen_dev->name = ACTIVE_PEN_DRIVER_NAME;
  18186. + apen->apen_dev->phys = APEN_PHYS_NAME;
  18187. + apen->apen_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
  18188. + apen->apen_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION;
  18189. + apen->apen_dev->dev.parent = rmi4_data->pdev->dev.parent;
  18190. + input_set_drvdata(apen->apen_dev, rmi4_data);
  18191. +
  18192. + set_bit(EV_KEY, apen->apen_dev->evbit);
  18193. + set_bit(EV_ABS, apen->apen_dev->evbit);
  18194. + set_bit(BTN_TOUCH, apen->apen_dev->keybit);
  18195. + set_bit(BTN_TOOL_PEN, apen->apen_dev->keybit);
  18196. + set_bit(BTN_TOOL_RUBBER, apen->apen_dev->keybit);
  18197. + set_bit(BTN_STYLUS, apen->apen_dev->keybit);
  18198. +#ifdef INPUT_PROP_DIRECT
  18199. + set_bit(INPUT_PROP_DIRECT, apen->apen_dev->propbit);
  18200. +#endif
  18201. +
  18202. + apen_set_params();
  18203. +
  18204. + retval = input_register_device(apen->apen_dev);
  18205. + if (retval) {
  18206. + dev_err(rmi4_data->pdev->dev.parent,
  18207. + "%s: Failed to register active pen device\n",
  18208. + __func__);
  18209. + goto exit_free_input_device;
  18210. + }
  18211. +
  18212. + return 0;
  18213. +
  18214. +exit_free_input_device:
  18215. + input_free_device(apen->apen_dev);
  18216. +
  18217. +exit_free_apen_data:
  18218. + kfree(apen->apen_data);
  18219. +
  18220. +exit_free_apen:
  18221. + kfree(apen);
  18222. + apen = NULL;
  18223. +
  18224. +exit:
  18225. + return retval;
  18226. +}
  18227. +
  18228. +static void synaptics_rmi4_apen_remove(struct synaptics_rmi4_data *rmi4_data)
  18229. +{
  18230. + if (!apen)
  18231. + goto exit;
  18232. +
  18233. + input_unregister_device(apen->apen_dev);
  18234. + kfree(apen->apen_data);
  18235. + kfree(apen);
  18236. + apen = NULL;
  18237. +
  18238. +exit:
  18239. + complete(&apen_remove_complete);
  18240. +
  18241. + return;
  18242. +}
  18243. +
  18244. +static void synaptics_rmi4_apen_reset(struct synaptics_rmi4_data *rmi4_data)
  18245. +{
  18246. + if (!apen) {
  18247. + synaptics_rmi4_apen_init(rmi4_data);
  18248. + return;
  18249. + }
  18250. +
  18251. + apen_lift();
  18252. +
  18253. + apen_scan_pdt();
  18254. +
  18255. + return;
  18256. +}
  18257. +
  18258. +static void synaptics_rmi4_apen_reinit(struct synaptics_rmi4_data *rmi4_data)
  18259. +{
  18260. + if (!apen)
  18261. + return;
  18262. +
  18263. + apen_lift();
  18264. +
  18265. + return;
  18266. +}
  18267. +
  18268. +static void synaptics_rmi4_apen_e_suspend(struct synaptics_rmi4_data *rmi4_data)
  18269. +{
  18270. + if (!apen)
  18271. + return;
  18272. +
  18273. + apen_lift();
  18274. +
  18275. + return;
  18276. +}
  18277. +
  18278. +static void synaptics_rmi4_apen_suspend(struct synaptics_rmi4_data *rmi4_data)
  18279. +{
  18280. + if (!apen)
  18281. + return;
  18282. +
  18283. + apen_lift();
  18284. +
  18285. + return;
  18286. +}
  18287. +
  18288. +static struct synaptics_rmi4_exp_fn active_pen_module = {
  18289. + .fn_type = RMI_ACTIVE_PEN,
  18290. + .init = synaptics_rmi4_apen_init,
  18291. + .remove = synaptics_rmi4_apen_remove,
  18292. + .reset = synaptics_rmi4_apen_reset,
  18293. + .reinit = synaptics_rmi4_apen_reinit,
  18294. + .early_suspend = synaptics_rmi4_apen_e_suspend,
  18295. + .suspend = synaptics_rmi4_apen_suspend,
  18296. + .resume = NULL,
  18297. + .late_resume = NULL,
  18298. + .attn = synaptics_rmi4_apen_attn,
  18299. +};
  18300. +
  18301. +static int __init rmi4_active_pen_module_init(void)
  18302. +{
  18303. + synaptics_rmi4_new_function_force(&active_pen_module, true);
  18304. +
  18305. + return 0;
  18306. +}
  18307. +
  18308. +static void __exit rmi4_active_pen_module_exit(void)
  18309. +{
  18310. + synaptics_rmi4_new_function_force(&active_pen_module, false);
  18311. +
  18312. + wait_for_completion(&apen_remove_complete);
  18313. +
  18314. + return;
  18315. +}
  18316. +
  18317. +module_init(rmi4_active_pen_module_init);
  18318. +module_exit(rmi4_active_pen_module_exit);
  18319. +
  18320. +MODULE_AUTHOR("Synaptics, Inc.");
  18321. +MODULE_DESCRIPTION("Synaptics DSX Active Pen Module");
  18322. +MODULE_LICENSE("GPL v2");
  18323. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.c
  18324. new file mode 100644
  18325. index 0000000..f61f2f0
  18326. --- /dev/null
  18327. +++ b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.c
  18328. @@ -0,0 +1,5987 @@
  18329. +/*
  18330. + * Synaptics DSX touchscreen driver
  18331. + *
  18332. + * Copyright (C) 2012-2015 Synaptics Incorporated. All rights reserved.
  18333. + *
  18334. + * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
  18335. + * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
  18336. + * Copyright (C) 2017 XiaoMi, Inc.
  18337. + *
  18338. + * This program is free software; you can redistribute it and/or modify
  18339. + * it under the terms of the GNU General Public License as published by
  18340. + * the Free Software Foundation; either version 2 of the License, or
  18341. + * (at your option) any later version.
  18342. + *
  18343. + * This program is distributed in the hope that it will be useful,
  18344. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18345. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18346. + * GNU General Public License for more details.
  18347. + *
  18348. + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  18349. + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  18350. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  18351. + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  18352. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  18353. + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  18354. + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  18355. + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  18356. + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  18357. + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  18358. + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  18359. + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  18360. + * DOLLARS.
  18361. + */
  18362. +
  18363. +#include <linux/kernel.h>
  18364. +#include <linux/module.h>
  18365. +#include <linux/slab.h>
  18366. +#include <linux/interrupt.h>
  18367. +#include <linux/delay.h>
  18368. +#include <linux/input.h>
  18369. +#include <linux/gpio.h>
  18370. +#include <linux/platform_device.h>
  18371. +#include <linux/regulator/consumer.h>
  18372. +#include <linux/input/synaptics_dsx.h>
  18373. +#include <linux/hwinfo.h>
  18374. +#include "synaptics_dsx_core.h"
  18375. +#ifdef KERNEL_ABOVE_2_6_38
  18376. +#include <linux/input/mt.h>
  18377. +#endif
  18378. +
  18379. +#if defined(CONFIG_SECURE_TOUCH)
  18380. +#include <linux/pm_runtime.h>
  18381. +#include <linux/errno.h>
  18382. +#endif
  18383. +
  18384. +#ifdef CONFIG_TOUCH_DEBUG_FS
  18385. +#include <linux/fs.h>
  18386. +#include <linux/debugfs.h>
  18387. +#include <linux/uaccess.h>
  18388. +#endif
  18389. +#include <linux/mdss_io_util.h>
  18390. +
  18391. +#define INPUT_PHYS_NAME "synaptics_dsx/touch_input"
  18392. +#define STYLUS_PHYS_NAME "synaptics_dsx/stylus"
  18393. +
  18394. +#define VIRTUAL_KEY_MAP_FILE_NAME "virtualkeys." PLATFORM_DRIVER_NAME
  18395. +
  18396. +#ifdef KERNEL_ABOVE_2_6_38
  18397. +#define TYPE_B_PROTOCOL
  18398. +#endif
  18399. +
  18400. +#define WAKEUP_GESTURE false
  18401. +
  18402. +#define NO_0D_WHILE_2D
  18403. +#define REPORT_2D_Z
  18404. +#define REPORT_2D_W
  18405. +
  18406. +#define REPORT_2D_PRESSURE
  18407. +
  18408. +
  18409. +#define F12_DATA_15_WORKAROUND
  18410. +
  18411. +#define IGNORE_FN_INIT_FAILURE
  18412. +/*
  18413. +#define FB_READY_RESET
  18414. +#define FB_READY_WAIT_MS 100
  18415. +#define FB_READY_TIMEOUT_S 30
  18416. +*/
  18417. +#define RPT_TYPE (1 << 0)
  18418. +#define RPT_X_LSB (1 << 1)
  18419. +#define RPT_X_MSB (1 << 2)
  18420. +#define RPT_Y_LSB (1 << 3)
  18421. +#define RPT_Y_MSB (1 << 4)
  18422. +#define RPT_Z (1 << 5)
  18423. +#define RPT_WX (1 << 6)
  18424. +#define RPT_WY (1 << 7)
  18425. +#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB)
  18426. +
  18427. +#define REBUILD_WORK_DELAY_MS 500 /* ms */
  18428. +
  18429. +#define EXP_FN_WORK_DELAY_MS 500 /* ms */
  18430. +#define MAX_F11_TOUCH_WIDTH 15
  18431. +#define MAX_F12_TOUCH_WIDTH 255
  18432. +#define MAX_F12_TOUCH_PRESSURE 255
  18433. +
  18434. +#define CHECK_STATUS_TIMEOUT_MS 100
  18435. +
  18436. +#define F01_STD_QUERY_LEN 21
  18437. +#define F01_BUID_ID_OFFSET 18
  18438. +#define F01_PROD_ID_OFFSET 11
  18439. +
  18440. +#define STATUS_NO_ERROR 0x00
  18441. +#define STATUS_RESET_OCCURRED 0x01
  18442. +#define STATUS_INVALID_CONFIG 0x02
  18443. +#define STATUS_DEVICE_FAILURE 0x03
  18444. +#define STATUS_CONFIG_CRC_FAILURE 0x04
  18445. +#define STATUS_FIRMWARE_CRC_FAILURE 0x05
  18446. +#define STATUS_CRC_IN_PROGRESS 0x06
  18447. +
  18448. +#define NORMAL_OPERATION (0 << 0)
  18449. +#define SENSOR_SLEEP (1 << 0)
  18450. +#define NO_SLEEP_OFF (0 << 2)
  18451. +#define NO_SLEEP_ON (1 << 2)
  18452. +#define CONFIGURED (1 << 7)
  18453. +
  18454. +#define F11_CONTINUOUS_MODE 0x00
  18455. +#define F11_WAKEUP_GESTURE_MODE 0x04
  18456. +#define F12_CONTINUOUS_MODE 0x00
  18457. +#define F12_WAKEUP_GESTURE_MODE 0x02
  18458. +#define F12_UDG_DETECT 0x0f
  18459. +#define F12_HOMEKEY_DETECT 0x0c
  18460. +
  18461. +#define DOUBLE_TAP 0x01
  18462. +#define HOMEKEY_WAKEUP 0x80
  18463. +
  18464. +#define INPUT_EVENT_START 0
  18465. +#define INPUT_EVENT_SENSITIVE_MODE_OFF 0
  18466. +#define INPUT_EVENT_SENSITIVE_MODE_ON 1
  18467. +#define INPUT_EVENT_STYLUS_MODE_OFF 2
  18468. +#define INPUT_EVENT_STYLUS_MODE_ON 3
  18469. +#define INPUT_EVENT_WAKUP_MODE_OFF 4
  18470. +#define INPUT_EVENT_WAKUP_MODE_ON 5
  18471. +#define INPUT_EVENT_COVER_MODE_OFF 6
  18472. +#define INPUT_EVENT_COVER_MODE_ON 7
  18473. +#define INPUT_EVENT_END 7
  18474. +
  18475. +#define BUTTON_WG_EN 1
  18476. +
  18477. +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
  18478. + bool *was_in_bl_mode);
  18479. +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data);
  18480. +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data);
  18481. +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data,
  18482. + bool rebuild);
  18483. +static void synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data,
  18484. + bool enable);
  18485. +static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data,
  18486. + bool enable);
  18487. +static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
  18488. + bool enable, bool attn_only);
  18489. +static void synaptics_rmi4_wakeup_reconfigure(struct synaptics_rmi4_data *rmi4_data,
  18490. + bool enable);
  18491. +
  18492. +#if defined(CONFIG_SECURE_TOUCH)
  18493. +static ssize_t synaptics_secure_touch_enable_show(struct device *dev,
  18494. + struct device_attribute *attr, char *buf);
  18495. +
  18496. +static ssize_t synaptics_secure_touch_enable_store(struct device *dev,
  18497. + struct device_attribute *attr, const char *buf, size_t count);
  18498. +
  18499. +static ssize_t synaptics_secure_touch_show(struct device *dev,
  18500. + struct device_attribute *attr, char *buf);
  18501. +#endif
  18502. +
  18503. +#ifdef CONFIG_FB
  18504. +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self,
  18505. + unsigned long event, void *data);
  18506. +static int synaptics_rmi4_fb_notifier_cb_tddi(struct notifier_block *self,
  18507. + unsigned long event, void *data);
  18508. +#endif
  18509. +
  18510. +#define DISP_REG_VDD (1<<0)
  18511. +#define DISP_REG_LAB (1<<1)
  18512. +#define DISP_REG_IBB (1<<2)
  18513. +#define DISP_REG_ALL (DISP_REG_VDD | DISP_REG_LAB | DISP_REG_IBB)
  18514. +
  18515. +static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, unsigned int flag, bool enable);
  18516. +static void mdss_reset_ctrl(const struct synaptics_dsx_board_data *bdata, bool on);
  18517. +static void mdss_reset_action(const struct synaptics_dsx_board_data *bdata);
  18518. +
  18519. +#ifdef CONFIG_HAS_EARLYSUSPEND
  18520. +#ifndef CONFIG_FB
  18521. +#define USE_EARLYSUSPEND
  18522. +#endif
  18523. +#endif
  18524. +
  18525. +#ifdef USE_EARLYSUSPEND
  18526. +static void synaptics_rmi4_early_suspend(struct early_suspend *h);
  18527. +
  18528. +static void synaptics_rmi4_late_resume(struct early_suspend *h);
  18529. +#endif
  18530. +static irqreturn_t synaptics_rmi4_irq(int irq, void *data);
  18531. +static int synaptics_rmi4_suspend(struct device *dev);
  18532. +
  18533. +static int synaptics_rmi4_resume(struct device *dev);
  18534. +
  18535. +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
  18536. + struct device_attribute *attr, const char *buf, size_t count);
  18537. +
  18538. +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
  18539. + struct device_attribute *attr, char *buf);
  18540. +
  18541. +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
  18542. + struct device_attribute *attr, char *buf);
  18543. +
  18544. +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
  18545. + struct device_attribute *attr, char *buf);
  18546. +
  18547. +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
  18548. + struct device_attribute *attr, char *buf);
  18549. +
  18550. +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
  18551. + struct device_attribute *attr, const char *buf, size_t count);
  18552. +
  18553. +static ssize_t synaptics_rmi4_suspend_store(struct device *dev,
  18554. + struct device_attribute *attr, const char *buf, size_t count);
  18555. +
  18556. +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev,
  18557. + struct device_attribute *attr, char *buf);
  18558. +
  18559. +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev,
  18560. + struct device_attribute *attr, const char *buf, size_t count);
  18561. +
  18562. +static ssize_t synaptics_rmi4_irq_enable_show(struct device *dev,
  18563. + struct device_attribute *attr, char *buf);
  18564. +
  18565. +static ssize_t synaptics_rmi4_irq_enable_store(struct device *dev,
  18566. + struct device_attribute *attr, const char *buf, size_t count);
  18567. +
  18568. +static ssize_t synaptics_rmi4_panel_color_show(struct device *dev,
  18569. + struct device_attribute *attr, char *buf);
  18570. +
  18571. +static ssize_t synaptics_rmi4_panel_vendor_show(struct device *dev,
  18572. + struct device_attribute *attr, char *buf);
  18573. +
  18574. +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,
  18575. + struct kobj_attribute *attr, char *buf);
  18576. +
  18577. +struct synaptics_rmi4_f01_device_status {
  18578. + union {
  18579. + struct {
  18580. + unsigned char status_code:4;
  18581. + unsigned char reserved:2;
  18582. + unsigned char flash_prog:1;
  18583. + unsigned char unconfigured:1;
  18584. + } __packed;
  18585. + unsigned char data[1];
  18586. + };
  18587. +};
  18588. +
  18589. +struct synaptics_rmi4_f11_query_0_5 {
  18590. + union {
  18591. + struct {
  18592. + /* query 0 */
  18593. + unsigned char f11_query0_b0__2:3;
  18594. + unsigned char has_query_9:1;
  18595. + unsigned char has_query_11:1;
  18596. + unsigned char has_query_12:1;
  18597. + unsigned char has_query_27:1;
  18598. + unsigned char has_query_28:1;
  18599. +
  18600. + /* query 1 */
  18601. + unsigned char num_of_fingers:3;
  18602. + unsigned char has_rel:1;
  18603. + unsigned char has_abs:1;
  18604. + unsigned char has_gestures:1;
  18605. + unsigned char has_sensitibity_adjust:1;
  18606. + unsigned char f11_query1_b7:1;
  18607. +
  18608. + /* query 2 */
  18609. + unsigned char num_of_x_electrodes;
  18610. +
  18611. + /* query 3 */
  18612. + unsigned char num_of_y_electrodes;
  18613. +
  18614. + /* query 4 */
  18615. + unsigned char max_electrodes:7;
  18616. + unsigned char f11_query4_b7:1;
  18617. +
  18618. + /* query 5 */
  18619. + unsigned char abs_data_size:2;
  18620. + unsigned char has_anchored_finger:1;
  18621. + unsigned char has_adj_hyst:1;
  18622. + unsigned char has_dribble:1;
  18623. + unsigned char has_bending_correction:1;
  18624. + unsigned char has_large_object_suppression:1;
  18625. + unsigned char has_jitter_filter:1;
  18626. + } __packed;
  18627. + unsigned char data[6];
  18628. + };
  18629. +};
  18630. +
  18631. +struct synaptics_rmi4_f11_query_7_8 {
  18632. + union {
  18633. + struct {
  18634. + /* query 7 */
  18635. + unsigned char has_single_tap:1;
  18636. + unsigned char has_tap_and_hold:1;
  18637. + unsigned char has_double_tap:1;
  18638. + unsigned char has_early_tap:1;
  18639. + unsigned char has_flick:1;
  18640. + unsigned char has_press:1;
  18641. + unsigned char has_pinch:1;
  18642. + unsigned char has_chiral_scroll:1;
  18643. +
  18644. + /* query 8 */
  18645. + unsigned char has_palm_detect:1;
  18646. + unsigned char has_rotate:1;
  18647. + unsigned char has_touch_shapes:1;
  18648. + unsigned char has_scroll_zones:1;
  18649. + unsigned char individual_scroll_zones:1;
  18650. + unsigned char has_multi_finger_scroll:1;
  18651. + unsigned char has_multi_finger_scroll_edge_motion:1;
  18652. + unsigned char has_multi_finger_scroll_inertia:1;
  18653. + } __packed;
  18654. + unsigned char data[2];
  18655. + };
  18656. +};
  18657. +
  18658. +struct synaptics_rmi4_f11_query_9 {
  18659. + union {
  18660. + struct {
  18661. + unsigned char has_pen:1;
  18662. + unsigned char has_proximity:1;
  18663. + unsigned char has_large_object_sensitivity:1;
  18664. + unsigned char has_suppress_on_large_object_detect:1;
  18665. + unsigned char has_two_pen_thresholds:1;
  18666. + unsigned char has_contact_geometry:1;
  18667. + unsigned char has_pen_hover_discrimination:1;
  18668. + unsigned char has_pen_hover_and_edge_filters:1;
  18669. + } __packed;
  18670. + unsigned char data[1];
  18671. + };
  18672. +};
  18673. +
  18674. +struct synaptics_rmi4_f11_query_12 {
  18675. + union {
  18676. + struct {
  18677. + unsigned char has_small_object_detection:1;
  18678. + unsigned char has_small_object_detection_tuning:1;
  18679. + unsigned char has_8bit_w:1;
  18680. + unsigned char has_2d_adjustable_mapping:1;
  18681. + unsigned char has_general_information_2:1;
  18682. + unsigned char has_physical_properties:1;
  18683. + unsigned char has_finger_limit:1;
  18684. + unsigned char has_linear_cofficient_2:1;
  18685. + } __packed;
  18686. + unsigned char data[1];
  18687. + };
  18688. +};
  18689. +
  18690. +struct synaptics_rmi4_f11_query_27 {
  18691. + union {
  18692. + struct {
  18693. + unsigned char f11_query27_b0:1;
  18694. + unsigned char has_pen_position_correction:1;
  18695. + unsigned char has_pen_jitter_filter_coefficient:1;
  18696. + unsigned char has_group_decomposition:1;
  18697. + unsigned char has_wakeup_gesture:1;
  18698. + unsigned char has_small_finger_correction:1;
  18699. + unsigned char has_data_37:1;
  18700. + unsigned char f11_query27_b7:1;
  18701. + } __packed;
  18702. + unsigned char data[1];
  18703. + };
  18704. +};
  18705. +
  18706. +struct synaptics_rmi4_f11_ctrl_6_9 {
  18707. + union {
  18708. + struct {
  18709. + unsigned char sensor_max_x_pos_7_0;
  18710. + unsigned char sensor_max_x_pos_11_8:4;
  18711. + unsigned char f11_ctrl7_b4__7:4;
  18712. + unsigned char sensor_max_y_pos_7_0;
  18713. + unsigned char sensor_max_y_pos_11_8:4;
  18714. + unsigned char f11_ctrl9_b4__7:4;
  18715. + } __packed;
  18716. + unsigned char data[4];
  18717. + };
  18718. +};
  18719. +
  18720. +struct synaptics_rmi4_f11_data_1_5 {
  18721. + union {
  18722. + struct {
  18723. + unsigned char x_position_11_4;
  18724. + unsigned char y_position_11_4;
  18725. + unsigned char x_position_3_0:4;
  18726. + unsigned char y_position_3_0:4;
  18727. + unsigned char wx:4;
  18728. + unsigned char wy:4;
  18729. + unsigned char z;
  18730. + } __packed;
  18731. + unsigned char data[5];
  18732. + };
  18733. +};
  18734. +
  18735. +struct synaptics_rmi4_f12_query_5 {
  18736. + union {
  18737. + struct {
  18738. + unsigned char size_of_query6;
  18739. + struct {
  18740. + unsigned char ctrl0_is_present:1;
  18741. + unsigned char ctrl1_is_present:1;
  18742. + unsigned char ctrl2_is_present:1;
  18743. + unsigned char ctrl3_is_present:1;
  18744. + unsigned char ctrl4_is_present:1;
  18745. + unsigned char ctrl5_is_present:1;
  18746. + unsigned char ctrl6_is_present:1;
  18747. + unsigned char ctrl7_is_present:1;
  18748. + } __packed;
  18749. + struct {
  18750. + unsigned char ctrl8_is_present:1;
  18751. + unsigned char ctrl9_is_present:1;
  18752. + unsigned char ctrl10_is_present:1;
  18753. + unsigned char ctrl11_is_present:1;
  18754. + unsigned char ctrl12_is_present:1;
  18755. + unsigned char ctrl13_is_present:1;
  18756. + unsigned char ctrl14_is_present:1;
  18757. + unsigned char ctrl15_is_present:1;
  18758. + } __packed;
  18759. + struct {
  18760. + unsigned char ctrl16_is_present:1;
  18761. + unsigned char ctrl17_is_present:1;
  18762. + unsigned char ctrl18_is_present:1;
  18763. + unsigned char ctrl19_is_present:1;
  18764. + unsigned char ctrl20_is_present:1;
  18765. + unsigned char ctrl21_is_present:1;
  18766. + unsigned char ctrl22_is_present:1;
  18767. + unsigned char ctrl23_is_present:1;
  18768. + } __packed;
  18769. + struct {
  18770. + unsigned char ctrl24_is_present:1;
  18771. + unsigned char ctrl25_is_present:1;
  18772. + unsigned char ctrl26_is_present:1;
  18773. + unsigned char ctrl27_is_present:1;
  18774. + unsigned char ctrl28_is_present:1;
  18775. + unsigned char ctrl29_is_present:1;
  18776. + unsigned char ctrl30_is_present:1;
  18777. + unsigned char ctrl31_is_present:1;
  18778. + } __packed;
  18779. + struct {
  18780. + unsigned char ctrl32_is_present:1;
  18781. + unsigned char ctrl33_is_present:1;
  18782. + unsigned char ctrl34_is_present:1;
  18783. + unsigned char ctrl35_is_present:1;
  18784. + unsigned char ctrl36_is_present:1;
  18785. + unsigned char ctrl37_is_present:1;
  18786. + unsigned char ctrl38_is_present:1;
  18787. + unsigned char ctrl39_is_present:1;
  18788. + } __packed;
  18789. + struct {
  18790. + unsigned char ctrl40_is_present:1;
  18791. + unsigned char ctrl41_is_present:1;
  18792. + unsigned char ctrl42_is_present:1;
  18793. + unsigned char ctrl43_is_present:1;
  18794. + unsigned char ctrl44_is_present:1;
  18795. + unsigned char ctrl45_is_present:1;
  18796. + unsigned char ctrl46_is_present:1;
  18797. + unsigned char ctrl47_is_present:1;
  18798. + } __packed;
  18799. + struct {
  18800. + unsigned char ctrl48_is_present:1;
  18801. + unsigned char ctrl49_is_present:1;
  18802. + unsigned char ctrl50_is_present:1;
  18803. + unsigned char ctrl51_is_present:1;
  18804. + unsigned char ctrl52_is_present:1;
  18805. + unsigned char ctrl53_is_present:1;
  18806. + unsigned char ctrl54_is_present:1;
  18807. + unsigned char ctrl55_is_present:1;
  18808. + } __packed;
  18809. + struct {
  18810. + unsigned char ctrl56_is_present:1;
  18811. + unsigned char ctrl57_is_present:1;
  18812. + unsigned char ctrl58_is_present:1;
  18813. + unsigned char ctrl59_is_present:1;
  18814. + unsigned char ctrl60_is_present:1;
  18815. + unsigned char ctrl61_is_present:1;
  18816. + unsigned char ctrl62_is_present:1;
  18817. + unsigned char ctrl63_is_present:1;
  18818. + } __packed;
  18819. + };
  18820. + unsigned char data[9];
  18821. + };
  18822. +};
  18823. +
  18824. +struct synaptics_rmi4_f12_query_8 {
  18825. + union {
  18826. + struct {
  18827. + unsigned char size_of_query9;
  18828. + struct {
  18829. + unsigned char data0_is_present:1;
  18830. + unsigned char data1_is_present:1;
  18831. + unsigned char data2_is_present:1;
  18832. + unsigned char data3_is_present:1;
  18833. + unsigned char data4_is_present:1;
  18834. + unsigned char data5_is_present:1;
  18835. + unsigned char data6_is_present:1;
  18836. + unsigned char data7_is_present:1;
  18837. + } __packed;
  18838. + struct {
  18839. + unsigned char data8_is_present:1;
  18840. + unsigned char data9_is_present:1;
  18841. + unsigned char data10_is_present:1;
  18842. + unsigned char data11_is_present:1;
  18843. + unsigned char data12_is_present:1;
  18844. + unsigned char data13_is_present:1;
  18845. + unsigned char data14_is_present:1;
  18846. + unsigned char data15_is_present:1;
  18847. + } __packed;
  18848. + struct {
  18849. + unsigned char data16_is_present:1;
  18850. + unsigned char data17_is_present:1;
  18851. + unsigned char data18_is_present:1;
  18852. + unsigned char data19_is_present:1;
  18853. + unsigned char data20_is_present:1;
  18854. + unsigned char data21_is_present:1;
  18855. + unsigned char data22_is_present:1;
  18856. + unsigned char data23_is_present:1;
  18857. + } __packed;
  18858. + struct {
  18859. + unsigned char data24_is_present:1;
  18860. + unsigned char data25_is_present:1;
  18861. + unsigned char data26_is_present:1;
  18862. + unsigned char data27_is_present:1;
  18863. + unsigned char data28_is_present:1;
  18864. + unsigned char data29_is_present:1;
  18865. + unsigned char data30_is_present:1;
  18866. + unsigned char data31_is_present:1;
  18867. + } __packed;
  18868. + };
  18869. + unsigned char data[5];
  18870. + };
  18871. +};
  18872. +
  18873. +struct synaptics_rmi4_f12_ctrl_8 {
  18874. + union {
  18875. + struct {
  18876. + unsigned char max_x_coord_lsb;
  18877. + unsigned char max_x_coord_msb;
  18878. + unsigned char max_y_coord_lsb;
  18879. + unsigned char max_y_coord_msb;
  18880. + unsigned char rx_pitch_lsb;
  18881. + unsigned char rx_pitch_msb;
  18882. + unsigned char tx_pitch_lsb;
  18883. + unsigned char tx_pitch_msb;
  18884. + unsigned char low_rx_clip;
  18885. + unsigned char high_rx_clip;
  18886. + unsigned char low_tx_clip;
  18887. + unsigned char high_tx_clip;
  18888. + unsigned char num_of_rx;
  18889. + unsigned char num_of_tx;
  18890. + };
  18891. + unsigned char data[14];
  18892. + };
  18893. +};
  18894. +
  18895. +struct synaptics_rmi4_f12_ctrl_23 {
  18896. + union {
  18897. + struct {
  18898. + unsigned char finger_enable:1;
  18899. + unsigned char active_stylus_enable:1;
  18900. + unsigned char palm_enable:1;
  18901. + unsigned char unclassified_object_enable:1;
  18902. + unsigned char hovering_finger_enable:1;
  18903. + unsigned char gloved_finger_enable:1;
  18904. + unsigned char f12_ctr23_00_b6__7:2;
  18905. + unsigned char max_reported_objects;
  18906. + unsigned char f12_ctr23_02_b0:1;
  18907. + unsigned char report_active_stylus_as_finger:1;
  18908. + unsigned char report_palm_as_finger:1;
  18909. + unsigned char report_unclassified_object_as_finger:1;
  18910. + unsigned char report_hovering_finger_as_finger:1;
  18911. + unsigned char report_gloved_finger_as_finger:1;
  18912. + unsigned char report_narrow_object_swipe_as_finger:1;
  18913. + unsigned char report_handedge_as_finger:1;
  18914. + unsigned char cover_enable:1;
  18915. + unsigned char stylus_enable:1;
  18916. + unsigned char eraser_enable:1;
  18917. + unsigned char small_object_enable:1;
  18918. + unsigned char f12_ctr23_03_b4__7:4;
  18919. + unsigned char report_cover_as_finger:1;
  18920. + unsigned char report_stylus_as_finger:1;
  18921. + unsigned char report_eraser_as_finger:1;
  18922. + unsigned char report_small_object_as_finger:1;
  18923. + unsigned char f12_ctr23_04_b4__7:4;
  18924. + };
  18925. + unsigned char data[5];
  18926. + };
  18927. +};
  18928. +
  18929. +struct synaptics_rmi4_f12_ctrl_31 {
  18930. + union {
  18931. + struct {
  18932. + unsigned char max_x_coord_lsb;
  18933. + unsigned char max_x_coord_msb;
  18934. + unsigned char max_y_coord_lsb;
  18935. + unsigned char max_y_coord_msb;
  18936. + unsigned char rx_pitch_lsb;
  18937. + unsigned char rx_pitch_msb;
  18938. + unsigned char rx_clip_low;
  18939. + unsigned char rx_clip_high;
  18940. + unsigned char wedge_clip_low;
  18941. + unsigned char wedge_clip_high;
  18942. + unsigned char num_of_p;
  18943. + unsigned char num_of_q;
  18944. + };
  18945. + unsigned char data[12];
  18946. + };
  18947. +};
  18948. +
  18949. +struct synaptics_rmi4_f12_ctrl_58 {
  18950. + union {
  18951. + struct {
  18952. + unsigned char reporting_format;
  18953. + unsigned char f12_ctr58_00_reserved;
  18954. + unsigned char min_force_lsb;
  18955. + unsigned char min_force_msb;
  18956. + unsigned char max_force_lsb;
  18957. + unsigned char max_force_msb;
  18958. + unsigned char light_press_threshold_lsb;
  18959. + unsigned char light_press_threshold_msb;
  18960. + unsigned char light_press_hysteresis_lsb;
  18961. + unsigned char light_press_hysteresis_msb;
  18962. + unsigned char hard_press_threshold_lsb;
  18963. + unsigned char hard_press_threshold_msb;
  18964. + unsigned char hard_press_hysteresis_lsb;
  18965. + unsigned char hard_press_hysteresis_msb;
  18966. + };
  18967. + unsigned char data[14];
  18968. + };
  18969. +};
  18970. +
  18971. +struct synaptics_rmi4_f12_finger_data {
  18972. + unsigned char object_type_and_status;
  18973. + unsigned char x_lsb;
  18974. + unsigned char x_msb;
  18975. + unsigned char y_lsb;
  18976. + unsigned char y_msb;
  18977. +#ifdef REPORT_2D_Z
  18978. + unsigned char z;
  18979. +#endif
  18980. +#ifdef REPORT_2D_W
  18981. + unsigned char wx;
  18982. + unsigned char wy;
  18983. +#endif
  18984. +};
  18985. +
  18986. +struct synaptics_rmi4_f1a_query {
  18987. + union {
  18988. + struct {
  18989. + unsigned char max_button_count:3;
  18990. + unsigned char f1a_query0_b3__4:2;
  18991. + unsigned char has_query4:1;
  18992. + unsigned char has_query3:1;
  18993. + unsigned char has_query2:1;
  18994. + unsigned char has_general_control:1;
  18995. + unsigned char has_interrupt_enable:1;
  18996. + unsigned char has_multibutton_select:1;
  18997. + unsigned char has_tx_rx_map:1;
  18998. + unsigned char has_perbutton_threshold:1;
  18999. + unsigned char has_release_threshold:1;
  19000. + unsigned char has_strongestbtn_hysteresis:1;
  19001. + unsigned char has_filter_strength:1;
  19002. + } __packed;
  19003. + unsigned char data[2];
  19004. + };
  19005. +};
  19006. +
  19007. +struct synaptics_rmi4_f1a_query_4 {
  19008. + union {
  19009. + struct {
  19010. + unsigned char has_ctrl19:1;
  19011. + unsigned char f1a_query4_b1__4:4;
  19012. + unsigned char has_ctrl24:1;
  19013. + unsigned char f1a_query4_b6__7:2;
  19014. + } __packed;
  19015. + unsigned char data[1];
  19016. + };
  19017. +};
  19018. +
  19019. +struct synaptics_rmi4_f1a_control_0 {
  19020. + union {
  19021. + struct {
  19022. + unsigned char multibutton_report:2;
  19023. + unsigned char filter_mode:2;
  19024. + unsigned char reserved:4;
  19025. + } __packed;
  19026. + unsigned char data[1];
  19027. + };
  19028. +};
  19029. +
  19030. +struct synaptics_rmi4_f1a_control {
  19031. + struct synaptics_rmi4_f1a_control_0 general_control;
  19032. + unsigned char button_int_enable;
  19033. + unsigned char multi_button;
  19034. + unsigned char *txrx_map;
  19035. + unsigned char *button_threshold;
  19036. + unsigned char button_release_threshold;
  19037. + unsigned char strongest_button_hysteresis;
  19038. + unsigned char filter_strength;
  19039. +};
  19040. +
  19041. +struct synaptics_rmi4_f1a_handle {
  19042. + int button_bitmask_size;
  19043. + unsigned char max_count;
  19044. + unsigned char valid_button_count;
  19045. + unsigned char *button_data_buffer;
  19046. + unsigned char *button_map;
  19047. + struct synaptics_rmi4_f1a_query button_query;
  19048. + struct synaptics_rmi4_f1a_control button_control;
  19049. +};
  19050. +
  19051. +struct synaptics_rmi4_exp_fhandler {
  19052. + struct synaptics_rmi4_exp_fn *exp_fn;
  19053. + bool insert;
  19054. + bool remove;
  19055. + struct list_head link;
  19056. +};
  19057. +
  19058. +struct synaptics_rmi4_exp_fn_data {
  19059. + bool initialized;
  19060. + bool queue_work;
  19061. + struct mutex mutex;
  19062. + struct list_head list;
  19063. + struct delayed_work work;
  19064. + struct workqueue_struct *workqueue;
  19065. + struct synaptics_rmi4_data *rmi4_data;
  19066. +};
  19067. +
  19068. +static struct synaptics_rmi4_exp_fn_data exp_data;
  19069. +
  19070. +static struct synaptics_dsx_button_map *vir_button_map;
  19071. +
  19072. +static struct device_attribute attrs[] = {
  19073. + __ATTR(reset, S_IWUSR,
  19074. + synaptics_rmi4_show_error,
  19075. + synaptics_rmi4_f01_reset_store),
  19076. + __ATTR(productinfo, S_IRUGO,
  19077. + synaptics_rmi4_f01_productinfo_show,
  19078. + synaptics_rmi4_store_error),
  19079. + __ATTR(buildid, S_IRUGO,
  19080. + synaptics_rmi4_f01_buildid_show,
  19081. + synaptics_rmi4_store_error),
  19082. + __ATTR(flashprog, S_IRUGO,
  19083. + synaptics_rmi4_f01_flashprog_show,
  19084. + synaptics_rmi4_store_error),
  19085. + __ATTR(0dbutton, (S_IRUGO | S_IWUSR),
  19086. + synaptics_rmi4_0dbutton_show,
  19087. + synaptics_rmi4_0dbutton_store),
  19088. + __ATTR(suspend, S_IWUSR,
  19089. + synaptics_rmi4_show_error,
  19090. + synaptics_rmi4_suspend_store),
  19091. + __ATTR(wake_gesture, (S_IRUGO | S_IWUSR),
  19092. + synaptics_rmi4_wake_gesture_show,
  19093. + synaptics_rmi4_wake_gesture_store),
  19094. + __ATTR(irq_enable, (S_IRUGO | S_IWUSR),
  19095. + synaptics_rmi4_irq_enable_show,
  19096. + synaptics_rmi4_irq_enable_store),
  19097. +};
  19098. +
  19099. +#if defined(CONFIG_SECURE_TOUCH)
  19100. +static DEVICE_ATTR(secure_touch_enable, (S_IRUGO | S_IWUSR | S_IWGRP), synaptics_secure_touch_enable_show, synaptics_secure_touch_enable_store);
  19101. +static DEVICE_ATTR(secure_touch, S_IRUGO , synaptics_secure_touch_show, NULL);
  19102. +
  19103. +static int synaptics_secure_touch_clk_prepare_enable(
  19104. + struct synaptics_rmi4_data *rmi4_data)
  19105. +{
  19106. + int ret;
  19107. +
  19108. + ret = clk_prepare_enable(rmi4_data->iface_clk);
  19109. + if (ret) {
  19110. + dev_err(rmi4_data->pdev->dev.parent,
  19111. + "error on clk_prepare_enable(iface_clk):%d\n", ret);
  19112. + return ret;
  19113. + }
  19114. +
  19115. + ret = clk_prepare_enable(rmi4_data->core_clk);
  19116. + if (ret) {
  19117. + clk_disable_unprepare(rmi4_data->iface_clk);
  19118. + dev_err(rmi4_data->pdev->dev.parent,
  19119. + "error clk_prepare_enable(core_clk):%d\n", ret);
  19120. + }
  19121. + return ret;
  19122. +}
  19123. +
  19124. +static void synaptics_secure_touch_clk_disable_unprepare(
  19125. + struct synaptics_rmi4_data *rmi4_data)
  19126. +{
  19127. + clk_disable_unprepare(rmi4_data->core_clk);
  19128. + clk_disable_unprepare(rmi4_data->iface_clk);
  19129. +}
  19130. +
  19131. +static void synaptics_secure_touch_init(struct synaptics_rmi4_data *data)
  19132. +{
  19133. + int ret = 0;
  19134. +
  19135. + data->st_initialized = 0;
  19136. + init_completion(&data->st_powerdown);
  19137. + init_completion(&data->st_irq_processed);
  19138. + /* Get clocks */
  19139. + data->core_clk = clk_get(data->pdev->dev.parent, "core_clk");
  19140. + if (IS_ERR(data->core_clk)) {
  19141. + ret = PTR_ERR(data->core_clk);
  19142. + dev_err(data->pdev->dev.parent,
  19143. + "%s: error on clk_get(core_clk):%d\n", __func__, ret);
  19144. + return;
  19145. + }
  19146. +
  19147. + data->iface_clk = clk_get(data->pdev->dev.parent, "iface_clk");
  19148. + if (IS_ERR(data->iface_clk)) {
  19149. + ret = PTR_ERR(data->iface_clk);
  19150. + dev_err(data->pdev->dev.parent,
  19151. + "%s: error on clk_get(iface_clk)\n", __func__);
  19152. + goto err_iface_clk;
  19153. + }
  19154. +
  19155. + data->st_initialized = 1;
  19156. + return;
  19157. +
  19158. +err_iface_clk:
  19159. + clk_put(data->core_clk);
  19160. + data->core_clk = NULL;
  19161. +}
  19162. +
  19163. +static void synaptics_secure_touch_notify(struct synaptics_rmi4_data *data)
  19164. +{
  19165. + sysfs_notify(&data->pdev->dev.parent->kobj, NULL, "secure_touch");
  19166. +}
  19167. +
  19168. +static irqreturn_t synaptics_filter_interrupt(struct synaptics_rmi4_data *data)
  19169. +{
  19170. + if (atomic_read(&data->st_enabled)) {
  19171. + if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0) {
  19172. + synaptics_secure_touch_notify(data);
  19173. + wait_for_completion_interruptible(
  19174. + &data->st_irq_processed);
  19175. + }
  19176. + return IRQ_HANDLED;
  19177. + }
  19178. + return IRQ_NONE;
  19179. +}
  19180. +
  19181. +static void synaptics_secure_touch_stop(
  19182. + struct synaptics_rmi4_data *data,
  19183. + int blocking)
  19184. +{
  19185. + if (atomic_read(&data->st_enabled)) {
  19186. + atomic_set(&data->st_pending_irqs, -1);
  19187. + synaptics_secure_touch_notify(data);
  19188. + if (blocking)
  19189. + wait_for_completion_interruptible(&data->st_powerdown);
  19190. + }
  19191. +}
  19192. +#else
  19193. +static void synaptics_secure_touch_init(struct synaptics_rmi4_data *data)
  19194. +{
  19195. +}
  19196. +
  19197. +static irqreturn_t synaptics_filter_interrupt(struct synaptics_rmi4_data *data)
  19198. +{
  19199. + return IRQ_NONE;
  19200. +}
  19201. +
  19202. +static void synaptics_secure_touch_stop(
  19203. + struct synaptics_rmi4_data *data,
  19204. + int blocking)
  19205. +{
  19206. +}
  19207. +#endif
  19208. +
  19209. +#if defined(CONFIG_SECURE_TOUCH)
  19210. +static ssize_t synaptics_secure_touch_enable_show(struct device *dev,
  19211. + struct device_attribute *attr, char *buf)
  19212. +{
  19213. + struct synaptics_rmi4_data *data = dev_get_drvdata(dev);
  19214. +
  19215. + return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
  19216. +}
  19217. +
  19218. +/*
  19219. + * Accept only "0" and "1" valid values.
  19220. + * "0" will reset the st_enabled flag, then wake up the reading process and
  19221. + * the interrupt handler.
  19222. + * The bus driver is notified via pm_runtime that it is not required to stay
  19223. + * awake anymore.
  19224. + * It will also make sure the queue of events is emptied in the controller,
  19225. + * in case a touch happened in between the secure touch being disabled and
  19226. + * the local ISR being ungated.
  19227. + * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
  19228. + * The bus driver is requested via pm_runtime to stay awake.
  19229. + */
  19230. +static ssize_t synaptics_secure_touch_enable_store(struct device *dev,
  19231. + struct device_attribute *attr,
  19232. + const char *buf, size_t count)
  19233. +{
  19234. + struct synaptics_rmi4_data *data = dev_get_drvdata(dev);
  19235. + struct i2c_client *client = container_of(data->pdev->dev.parent, struct i2c_client, dev);
  19236. + struct device *adapter = client->adapter->dev.parent;
  19237. + unsigned long value;
  19238. + int err = 0;
  19239. +
  19240. + if (count > 2)
  19241. + return -EINVAL;
  19242. +
  19243. + err = kstrtoul(buf, 10, &value);
  19244. + if (err != 0)
  19245. + return err;
  19246. +
  19247. + if (!data->st_initialized)
  19248. + return -EIO;
  19249. +
  19250. + err = count;
  19251. +
  19252. + switch (value) {
  19253. + case 0:
  19254. + if (atomic_read(&data->st_enabled) == 0)
  19255. + break;
  19256. +
  19257. + synaptics_secure_touch_clk_disable_unprepare(data);
  19258. + pm_runtime_put_sync(adapter);
  19259. + atomic_set(&data->st_enabled, 0);
  19260. + synaptics_secure_touch_notify(data);
  19261. + complete(&data->st_irq_processed);
  19262. + synaptics_rmi4_irq(data->irq, data);
  19263. + complete(&data->st_powerdown);
  19264. +
  19265. + break;
  19266. + case 1:
  19267. + if (atomic_read(&data->st_enabled)) {
  19268. + err = -EBUSY;
  19269. + break;
  19270. + }
  19271. +
  19272. + synchronize_irq(data->irq);
  19273. + if (pm_runtime_get_sync(adapter) < 0) {
  19274. + dev_err(data->pdev->dev.parent, "pm_runtime_get_sync failed\n");
  19275. + err = -EIO;
  19276. + break;
  19277. + }
  19278. +
  19279. + if (synaptics_secure_touch_clk_prepare_enable(data) < 0) {
  19280. + pm_runtime_put_sync(adapter);
  19281. + err = -EIO;
  19282. + break;
  19283. + }
  19284. + reinit_completion(&data->st_powerdown);
  19285. + reinit_completion(&data->st_irq_processed);
  19286. + atomic_set(&data->st_enabled, 1);
  19287. + atomic_set(&data->st_pending_irqs, 0);
  19288. + break;
  19289. + default:
  19290. + dev_err(data->pdev->dev.parent,
  19291. + "unsupported value: %lu\n", value);
  19292. + err = -EINVAL;
  19293. + break;
  19294. + }
  19295. + return err;
  19296. +}
  19297. +
  19298. +/*
  19299. + * This function returns whether there are pending interrupts, or
  19300. + * other error conditions that need to be signaled to the userspace library,
  19301. + * according tot he following logic:
  19302. + * - st_enabled is 0 if secure touch is not enabled, returning -EBADF
  19303. + * - st_pending_irqs is -1 to signal that secure touch is in being stopped,
  19304. + * returning -EINVAL
  19305. + * - st_pending_irqs is 1 to signal that there is a pending irq, returning
  19306. + * the value "1" to the sysfs read operation
  19307. + * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt
  19308. + * has been processed, so the interrupt handler can be allowed to continue.
  19309. + */
  19310. +static ssize_t synaptics_secure_touch_show(struct device *dev,
  19311. + struct device_attribute *attr, char *buf)
  19312. +{
  19313. + struct synaptics_rmi4_data *data = dev_get_drvdata(dev);
  19314. + int val = 0;
  19315. +
  19316. + if (atomic_read(&data->st_enabled) == 0)
  19317. + return -EBADF;
  19318. +
  19319. + if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1)
  19320. + return -EINVAL;
  19321. +
  19322. + if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1)
  19323. + val = 1;
  19324. + else
  19325. + complete(&data->st_irq_processed);
  19326. +
  19327. + return scnprintf(buf, PAGE_SIZE, "%u", val);
  19328. +
  19329. +}
  19330. +#endif
  19331. +
  19332. +static DEVICE_ATTR(panel_color, S_IRUSR, synaptics_rmi4_panel_color_show, NULL);
  19333. +static DEVICE_ATTR(panel_vendor, S_IRUSR, synaptics_rmi4_panel_vendor_show, NULL);
  19334. +
  19335. +static struct kobj_attribute virtual_key_map_attr = {
  19336. + .attr = {
  19337. + .name = VIRTUAL_KEY_MAP_FILE_NAME,
  19338. + .mode = S_IRUGO,
  19339. + },
  19340. + .show = synaptics_rmi4_virtual_key_map_show,
  19341. +};
  19342. +
  19343. +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
  19344. + struct device_attribute *attr, const char *buf, size_t count)
  19345. +{
  19346. + int retval;
  19347. + unsigned int reset;
  19348. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19349. +
  19350. + if (sscanf(buf, "%u", &reset) != 1)
  19351. + return -EINVAL;
  19352. +
  19353. + if (reset != 1)
  19354. + return -EINVAL;
  19355. +
  19356. + retval = synaptics_rmi4_reset_device(rmi4_data, false);
  19357. + if (retval < 0) {
  19358. + dev_err(rmi4_data->pdev->dev.parent,
  19359. + "%s: Failed to issue reset command, error = %d\n",
  19360. + __func__, retval);
  19361. + return retval;
  19362. + }
  19363. +
  19364. + return count;
  19365. +}
  19366. +
  19367. +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
  19368. + struct device_attribute *attr, char *buf)
  19369. +{
  19370. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19371. +
  19372. + return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n",
  19373. + (rmi4_data->rmi4_mod_info.product_info[0]),
  19374. + (rmi4_data->rmi4_mod_info.product_info[1]));
  19375. +}
  19376. +
  19377. +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
  19378. + struct device_attribute *attr, char *buf)
  19379. +{
  19380. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19381. +
  19382. + return snprintf(buf, PAGE_SIZE, "%u\n",
  19383. + rmi4_data->firmware_id);
  19384. +}
  19385. +
  19386. +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
  19387. + struct device_attribute *attr, char *buf)
  19388. +{
  19389. + int retval;
  19390. + struct synaptics_rmi4_f01_device_status device_status;
  19391. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19392. +
  19393. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19394. + rmi4_data->f01_data_base_addr,
  19395. + device_status.data,
  19396. + sizeof(device_status.data));
  19397. + if (retval < 0) {
  19398. + dev_err(rmi4_data->pdev->dev.parent,
  19399. + "%s: Failed to read device status, error = %d\n",
  19400. + __func__, retval);
  19401. + return retval;
  19402. + }
  19403. +
  19404. + return snprintf(buf, PAGE_SIZE, "%u\n",
  19405. + device_status.flash_prog);
  19406. +}
  19407. +
  19408. +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
  19409. + struct device_attribute *attr, char *buf)
  19410. +{
  19411. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19412. +
  19413. + return snprintf(buf, PAGE_SIZE, "%u\n",
  19414. + rmi4_data->button_0d_enabled);
  19415. +}
  19416. +
  19417. +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
  19418. + struct device_attribute *attr, const char *buf, size_t count)
  19419. +{
  19420. + int retval;
  19421. + unsigned int input;
  19422. + unsigned char ii;
  19423. + unsigned char intr_enable;
  19424. + struct synaptics_rmi4_fn *fhandler;
  19425. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19426. + struct synaptics_rmi4_device_info *rmi;
  19427. +
  19428. + rmi = &(rmi4_data->rmi4_mod_info);
  19429. +
  19430. + if (sscanf(buf, "%u", &input) != 1)
  19431. + return -EINVAL;
  19432. +
  19433. + input = input > 0 ? 1 : 0;
  19434. +
  19435. + if (rmi4_data->button_0d_enabled == input)
  19436. + return count;
  19437. +
  19438. + if (list_empty(&rmi->support_fn_list))
  19439. + return -ENODEV;
  19440. +
  19441. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  19442. + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
  19443. + ii = fhandler->intr_reg_num;
  19444. +
  19445. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19446. + rmi4_data->f01_ctrl_base_addr + 1 + ii,
  19447. + &intr_enable,
  19448. + sizeof(intr_enable));
  19449. + if (retval < 0)
  19450. + return retval;
  19451. +
  19452. + if (input == 1)
  19453. + intr_enable |= fhandler->intr_mask;
  19454. + else
  19455. + intr_enable &= ~fhandler->intr_mask;
  19456. +
  19457. + retval = synaptics_rmi4_reg_write(rmi4_data,
  19458. + rmi4_data->f01_ctrl_base_addr + 1 + ii,
  19459. + &intr_enable,
  19460. + sizeof(intr_enable));
  19461. + if (retval < 0)
  19462. + return retval;
  19463. + }
  19464. + }
  19465. +
  19466. + rmi4_data->button_0d_enabled = input;
  19467. +
  19468. + return count;
  19469. +}
  19470. +
  19471. +static ssize_t synaptics_rmi4_suspend_store(struct device *dev,
  19472. + struct device_attribute *attr, const char *buf, size_t count)
  19473. +{
  19474. + unsigned int input;
  19475. +
  19476. + if (sscanf(buf, "%u", &input) != 1)
  19477. + return -EINVAL;
  19478. +
  19479. + if (input == 1)
  19480. + synaptics_rmi4_suspend(dev);
  19481. + else if (input == 0)
  19482. + synaptics_rmi4_resume(dev);
  19483. + else
  19484. + return -EINVAL;
  19485. +
  19486. + return count;
  19487. +}
  19488. +
  19489. +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev,
  19490. + struct device_attribute *attr, char *buf)
  19491. +{
  19492. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19493. +
  19494. + return snprintf(buf, PAGE_SIZE, "%u\n",
  19495. + rmi4_data->enable_wakeup_gesture);
  19496. +}
  19497. +
  19498. +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev,
  19499. + struct device_attribute *attr, const char *buf, size_t count)
  19500. +{
  19501. + unsigned int input;
  19502. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19503. + const struct synaptics_dsx_board_data *bdata =
  19504. + rmi4_data->hw_if->board_data;
  19505. +
  19506. + if (sscanf(buf, "%u", &input) != 1)
  19507. + return -EINVAL;
  19508. +
  19509. + if (bdata->cut_off_power) {
  19510. + dev_err(rmi4_data->pdev->dev.parent,
  19511. + "%s: Unable to switch wakeup gesture mode\n", __func__);
  19512. + return count;
  19513. + }
  19514. +
  19515. + input = input > 0 ? 1 : 0;
  19516. +
  19517. + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture)
  19518. + rmi4_data->enable_wakeup_gesture = input;
  19519. +
  19520. + if (rmi4_data->suspend)
  19521. + synaptics_rmi4_wakeup_reconfigure(rmi4_data, (bool)input);
  19522. +
  19523. + return count;
  19524. +}
  19525. +
  19526. +static ssize_t synaptics_rmi4_irq_enable_show(struct device *dev,
  19527. + struct device_attribute *attr, char *buf)
  19528. +{
  19529. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19530. +
  19531. + return snprintf(buf, PAGE_SIZE, "%u\n",
  19532. + rmi4_data->irq_enabled);
  19533. +}
  19534. +
  19535. +static ssize_t synaptics_rmi4_irq_enable_store(struct device *dev,
  19536. + struct device_attribute *attr, const char *buf, size_t count)
  19537. +{
  19538. + unsigned int input;
  19539. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19540. +
  19541. + if (sscanf(buf, "%u", &input) != 1)
  19542. + return -EINVAL;
  19543. + if (input)
  19544. + enable_irq(rmi4_data->irq);
  19545. + else
  19546. + disable_irq(rmi4_data->irq);
  19547. +
  19548. + return count;
  19549. +}
  19550. +
  19551. +static ssize_t synaptics_rmi4_panel_color_show(struct device *dev,
  19552. + struct device_attribute *attr, char *buf)
  19553. +{
  19554. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19555. +
  19556. + return snprintf(buf, PAGE_SIZE, "%c\n",
  19557. + rmi4_data->lockdown_info[2]);
  19558. +}
  19559. +
  19560. +static ssize_t synaptics_rmi4_panel_vendor_show(struct device *dev,
  19561. + struct device_attribute *attr, char *buf)
  19562. +{
  19563. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  19564. +
  19565. + return snprintf(buf, PAGE_SIZE, "%c\n",
  19566. + rmi4_data->lockdown_info[0]);
  19567. +}
  19568. +
  19569. +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,
  19570. + struct kobj_attribute *attr, char *buf)
  19571. +{
  19572. + int ii;
  19573. + int cnt;
  19574. + int count = 0;
  19575. +
  19576. + for (ii = 0; ii < vir_button_map->nbuttons; ii++) {
  19577. + cnt = snprintf(buf, PAGE_SIZE - count, "0x01:%d:%d:%d:%d:%d\n",
  19578. + vir_button_map->map[ii * 5 + 0],
  19579. + vir_button_map->map[ii * 5 + 1],
  19580. + vir_button_map->map[ii * 5 + 2],
  19581. + vir_button_map->map[ii * 5 + 3],
  19582. + vir_button_map->map[ii * 5 + 4]);
  19583. + buf += cnt;
  19584. + count += cnt;
  19585. + }
  19586. +
  19587. + return count;
  19588. +}
  19589. +
  19590. +static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data,
  19591. + struct synaptics_rmi4_fn *fhandler)
  19592. +{
  19593. + int retval;
  19594. + unsigned char touch_count = 0; /* number of touch points */
  19595. + unsigned char reg_index;
  19596. + unsigned char finger;
  19597. + unsigned char fingers_supported;
  19598. + unsigned char num_of_finger_status_regs;
  19599. + unsigned char finger_shift;
  19600. + unsigned char finger_status;
  19601. + unsigned char finger_status_reg[3];
  19602. + unsigned char detected_gestures;
  19603. + unsigned short data_addr;
  19604. + unsigned short data_offset;
  19605. + int x;
  19606. + int y;
  19607. + int wx;
  19608. + int wy;
  19609. + int temp;
  19610. + struct synaptics_rmi4_f11_data_1_5 data;
  19611. + struct synaptics_rmi4_f11_extra_data *extra_data;
  19612. +
  19613. + /*
  19614. + * The number of finger status registers is determined by the
  19615. + * maximum number of fingers supported - 2 bits per finger. So
  19616. + * the number of finger status registers to read is:
  19617. + * register_count = ceil(max_num_of_fingers / 4)
  19618. + */
  19619. + fingers_supported = fhandler->num_of_data_points;
  19620. + num_of_finger_status_regs = (fingers_supported + 3) / 4;
  19621. + data_addr = fhandler->full_addr.data_base;
  19622. +
  19623. + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra;
  19624. +
  19625. + if (rmi4_data->suspend && rmi4_data->wakeup_en) {
  19626. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19627. + data_addr + extra_data->data38_offset,
  19628. + &detected_gestures,
  19629. + sizeof(detected_gestures));
  19630. + if (retval < 0)
  19631. + return 0;
  19632. +
  19633. + if (detected_gestures) {
  19634. + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1);
  19635. + input_sync(rmi4_data->input_dev);
  19636. + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0);
  19637. + input_sync(rmi4_data->input_dev);
  19638. + }
  19639. +
  19640. + return 0;
  19641. + }
  19642. +
  19643. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19644. + data_addr,
  19645. + finger_status_reg,
  19646. + num_of_finger_status_regs);
  19647. + if (retval < 0)
  19648. + return 0;
  19649. +
  19650. + mutex_lock(&(rmi4_data->rmi4_report_mutex));
  19651. +
  19652. + for (finger = 0; finger < fingers_supported; finger++) {
  19653. + reg_index = finger / 4;
  19654. + finger_shift = (finger % 4) * 2;
  19655. + finger_status = (finger_status_reg[reg_index] >> finger_shift)
  19656. + & MASK_2BIT;
  19657. +
  19658. + /*
  19659. + * Each 2-bit finger status field represents the following:
  19660. + * 00 = finger not present
  19661. + * 01 = finger present and data accurate
  19662. + * 10 = finger present but data may be inaccurate
  19663. + * 11 = reserved
  19664. + */
  19665. +#ifdef TYPE_B_PROTOCOL
  19666. + input_mt_slot(rmi4_data->input_dev, finger);
  19667. + input_mt_report_slot_state(rmi4_data->input_dev,
  19668. + MT_TOOL_FINGER, finger_status);
  19669. +#endif
  19670. +
  19671. + if (finger_status) {
  19672. + data_offset = data_addr +
  19673. + num_of_finger_status_regs +
  19674. + (finger * sizeof(data.data));
  19675. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19676. + data_offset,
  19677. + data.data,
  19678. + sizeof(data.data));
  19679. + if (retval < 0) {
  19680. + touch_count = 0;
  19681. + goto exit;
  19682. + }
  19683. +
  19684. + x = (data.x_position_11_4 << 4) | data.x_position_3_0;
  19685. + y = (data.y_position_11_4 << 4) | data.y_position_3_0;
  19686. + wx = data.wx;
  19687. + wy = data.wy;
  19688. +
  19689. + if (rmi4_data->hw_if->board_data->swap_axes) {
  19690. + temp = x;
  19691. + x = y;
  19692. + y = temp;
  19693. + temp = wx;
  19694. + wx = wy;
  19695. + wy = temp;
  19696. + }
  19697. +
  19698. + if (rmi4_data->hw_if->board_data->x_flip)
  19699. + x = rmi4_data->sensor_max_x - x;
  19700. + if (rmi4_data->hw_if->board_data->y_flip)
  19701. + y = rmi4_data->sensor_max_y - y;
  19702. +
  19703. + input_report_key(rmi4_data->input_dev,
  19704. + BTN_TOUCH, 1);
  19705. + input_report_key(rmi4_data->input_dev,
  19706. + BTN_TOOL_FINGER, 1);
  19707. + input_report_abs(rmi4_data->input_dev,
  19708. + ABS_MT_POSITION_X, x);
  19709. + input_report_abs(rmi4_data->input_dev,
  19710. + ABS_MT_POSITION_Y, y);
  19711. +#ifdef REPORT_2D_W
  19712. + input_report_abs(rmi4_data->input_dev,
  19713. + ABS_MT_TOUCH_MAJOR, max(wx, wy));
  19714. + input_report_abs(rmi4_data->input_dev,
  19715. + ABS_MT_TOUCH_MINOR, min(wx, wy));
  19716. +#endif
  19717. +#ifndef TYPE_B_PROTOCOL
  19718. + input_mt_sync(rmi4_data->input_dev);
  19719. +#endif
  19720. +
  19721. + dev_dbg(rmi4_data->pdev->dev.parent,
  19722. + "%s: Finger %d: "
  19723. + "status = 0x%02x, "
  19724. + "x = %d, "
  19725. + "y = %d, "
  19726. + "wx = %d, "
  19727. + "wy = %d\n",
  19728. + __func__, finger,
  19729. + finger_status,
  19730. + x, y, wx, wy);
  19731. +
  19732. + touch_count++;
  19733. + }
  19734. + }
  19735. +
  19736. + if (touch_count == 0) {
  19737. + input_report_key(rmi4_data->input_dev,
  19738. + BTN_TOUCH, 0);
  19739. + input_report_key(rmi4_data->input_dev,
  19740. + BTN_TOOL_FINGER, 0);
  19741. +#ifndef TYPE_B_PROTOCOL
  19742. + input_mt_sync(rmi4_data->input_dev);
  19743. +#endif
  19744. + }
  19745. +
  19746. + input_sync(rmi4_data->input_dev);
  19747. +
  19748. +exit:
  19749. + mutex_unlock(&(rmi4_data->rmi4_report_mutex));
  19750. +
  19751. + return touch_count;
  19752. +}
  19753. +
  19754. +static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
  19755. + struct synaptics_rmi4_fn *fhandler)
  19756. +{
  19757. + int retval;
  19758. + unsigned char touch_count = 0; /* number of touch points */
  19759. + unsigned char index;
  19760. + unsigned char finger;
  19761. + unsigned char fingers_to_process;
  19762. + unsigned char finger_status;
  19763. + unsigned char size_of_2d_data;
  19764. + unsigned char gesture_type;
  19765. + unsigned short data_addr;
  19766. + int x;
  19767. + int y;
  19768. + int wx;
  19769. + int wy;
  19770. + int temp;
  19771. +#if defined(REPORT_2D_PRESSURE) || defined(F51_DISCRETE_FORCE)
  19772. + int pressure;
  19773. +#endif
  19774. + int touchs;
  19775. +#ifdef REPORT_2D_PRESSURE
  19776. + unsigned char f_fingers;
  19777. + unsigned char f_lsb;
  19778. + unsigned char f_msb;
  19779. + unsigned char *f_data;
  19780. +#endif
  19781. +#ifdef F51_DISCRETE_FORCE
  19782. + unsigned char force_level;
  19783. +#endif
  19784. + struct synaptics_rmi4_f12_extra_data *extra_data;
  19785. + struct synaptics_rmi4_f12_finger_data *data;
  19786. + struct synaptics_rmi4_f12_finger_data *finger_data;
  19787. + static unsigned char finger_presence;
  19788. + static unsigned char stylus_presence;
  19789. +#ifdef F12_DATA_15_WORKAROUND
  19790. + static unsigned char objects_already_present;
  19791. +#endif
  19792. +
  19793. + if (rmi4_data->input_dev == NULL) {
  19794. + dev_err(rmi4_data->pdev->dev.parent, "input_dev is NULL, do not report data\n");
  19795. +
  19796. + return 0;
  19797. + }
  19798. +
  19799. + fingers_to_process = fhandler->num_of_data_points;
  19800. + data_addr = fhandler->full_addr.data_base;
  19801. + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
  19802. + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
  19803. +
  19804. + if (rmi4_data->suspend && rmi4_data->wakeup_en) {
  19805. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19806. + data_addr + extra_data->data4_offset,
  19807. + rmi4_data->gesture_detection,
  19808. + sizeof(rmi4_data->gesture_detection));
  19809. + if (retval < 0)
  19810. + return 0;
  19811. +
  19812. + gesture_type = rmi4_data->gesture_detection[0];
  19813. + if (gesture_type && gesture_type != F12_UDG_DETECT) {
  19814. + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1);
  19815. + input_sync(rmi4_data->input_dev);
  19816. + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0);
  19817. + input_sync(rmi4_data->input_dev);
  19818. + dev_err(rmi4_data->pdev->dev.parent, "double click send input event\n");
  19819. + }
  19820. +
  19821. + return 0;
  19822. + }
  19823. +
  19824. + /* Determine the total number of fingers to process */
  19825. + if (extra_data->data15_size) {
  19826. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19827. + data_addr + extra_data->data15_offset,
  19828. + extra_data->data15_data,
  19829. + extra_data->data15_size);
  19830. + if (retval < 0)
  19831. + return 0;
  19832. +
  19833. + /* Start checking from the highest bit */
  19834. + index = extra_data->data15_size - 1; /* Highest byte */
  19835. + finger = (fingers_to_process - 1) % 8; /* Highest bit */
  19836. + do {
  19837. + if (extra_data->data15_data[index] & (1 << finger))
  19838. + break;
  19839. +
  19840. + if (finger) {
  19841. + finger--;
  19842. + } else if (index > 0) {
  19843. + index--; /* Move to the next lower byte */
  19844. + finger = 7;
  19845. + }
  19846. +
  19847. + fingers_to_process--;
  19848. + } while (fingers_to_process);
  19849. +
  19850. + dev_dbg(rmi4_data->pdev->dev.parent,
  19851. + "%s: Number of fingers to process = %d\n",
  19852. + __func__, fingers_to_process);
  19853. + }
  19854. +
  19855. +#ifdef F12_DATA_15_WORKAROUND
  19856. + fingers_to_process = max(fingers_to_process, objects_already_present);
  19857. +#endif
  19858. +
  19859. + if (!fingers_to_process) {
  19860. + synaptics_rmi4_free_fingers(rmi4_data);
  19861. + finger_presence = 0;
  19862. + stylus_presence = 0;
  19863. + rmi4_data->touchs = 0;
  19864. + return 0;
  19865. + }
  19866. +
  19867. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19868. + data_addr + extra_data->data1_offset,
  19869. + (unsigned char *)fhandler->data,
  19870. + fingers_to_process * size_of_2d_data);
  19871. + if (retval < 0)
  19872. + return 0;
  19873. +
  19874. + data = (struct synaptics_rmi4_f12_finger_data *)fhandler->data;
  19875. +
  19876. +#ifdef REPORT_2D_PRESSURE
  19877. + if (rmi4_data->report_pressure) {
  19878. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19879. + data_addr + extra_data->data29_offset,
  19880. + extra_data->data29_data,
  19881. + extra_data->data29_size);
  19882. + if (retval < 0)
  19883. + return 0;
  19884. + }
  19885. +#endif
  19886. +
  19887. + mutex_lock(&(rmi4_data->rmi4_report_mutex));
  19888. +
  19889. + for (finger = 0; finger < fingers_to_process; finger++) {
  19890. + finger_data = data + finger;
  19891. + finger_status = finger_data->object_type_and_status;
  19892. +
  19893. +#ifdef F12_DATA_15_WORKAROUND
  19894. + objects_already_present = finger + 1;
  19895. +#endif
  19896. +
  19897. + x = (finger_data->x_msb << 8) | (finger_data->x_lsb);
  19898. + y = (finger_data->y_msb << 8) | (finger_data->y_lsb);
  19899. +#ifdef REPORT_2D_W
  19900. + wx = finger_data->wx;
  19901. + wy = finger_data->wy;
  19902. +#endif
  19903. +
  19904. + if (rmi4_data->hw_if->board_data->swap_axes) {
  19905. + temp = x;
  19906. + x = y;
  19907. + y = temp;
  19908. + temp = wx;
  19909. + wx = wy;
  19910. + wy = temp;
  19911. + }
  19912. +
  19913. + if (rmi4_data->hw_if->board_data->x_flip)
  19914. + x = rmi4_data->sensor_max_x - x;
  19915. + if (rmi4_data->hw_if->board_data->y_flip)
  19916. + y = rmi4_data->sensor_max_y - y;
  19917. +
  19918. + switch (finger_status) {
  19919. + case F12_FINGER_STATUS:
  19920. + case F12_GLOVED_FINGER_STATUS:
  19921. + if (stylus_presence) /* Stylus has priority over fingers */
  19922. + break;
  19923. +#ifdef TYPE_B_PROTOCOL
  19924. + input_mt_slot(rmi4_data->input_dev, finger);
  19925. + input_mt_report_slot_state(rmi4_data->input_dev,
  19926. + MT_TOOL_FINGER, 1);
  19927. +#endif
  19928. +
  19929. + input_report_key(rmi4_data->input_dev,
  19930. + BTN_TOUCH, 1);
  19931. + input_report_key(rmi4_data->input_dev,
  19932. + BTN_TOOL_FINGER, 1);
  19933. + input_report_abs(rmi4_data->input_dev,
  19934. + ABS_MT_POSITION_X, x);
  19935. + input_report_abs(rmi4_data->input_dev,
  19936. + ABS_MT_POSITION_Y, y);
  19937. +#ifdef REPORT_2D_W
  19938. + if (rmi4_data->wedge_sensor) {
  19939. + input_report_abs(rmi4_data->input_dev,
  19940. + ABS_MT_TOUCH_MAJOR, wx);
  19941. + input_report_abs(rmi4_data->input_dev,
  19942. + ABS_MT_TOUCH_MINOR, wx);
  19943. + } else {
  19944. + input_report_abs(rmi4_data->input_dev,
  19945. + ABS_MT_TOUCH_MAJOR,
  19946. + max(wx, wy));
  19947. + input_report_abs(rmi4_data->input_dev,
  19948. + ABS_MT_TOUCH_MINOR,
  19949. + min(wx, wy));
  19950. + }
  19951. +#endif
  19952. +#ifdef REPORT_2D_PRESSURE
  19953. + if (rmi4_data->report_pressure) {
  19954. + f_fingers = extra_data->data29_size / 2;
  19955. + f_data = extra_data->data29_data;
  19956. + if (finger + 1 > f_fingers) {
  19957. + pressure = 1;
  19958. + } else {
  19959. + f_lsb = finger * 2;
  19960. + f_msb = finger * 2 + 1;
  19961. + pressure = (int)f_data[f_lsb] << 0 |
  19962. + (int)f_data[f_msb] << 8;
  19963. + }
  19964. + pressure = pressure > 0 ? pressure : 1;
  19965. + if (pressure > rmi4_data->force_max)
  19966. + pressure = rmi4_data->force_max;
  19967. + input_report_abs(rmi4_data->input_dev,
  19968. + ABS_MT_PRESSURE, pressure);
  19969. + }
  19970. +#elif defined(F51_DISCRETE_FORCE)
  19971. + if (finger == 0) {
  19972. + retval = synaptics_rmi4_reg_read(rmi4_data,
  19973. + FORCE_LEVEL_ADDR,
  19974. + &force_level,
  19975. + sizeof(force_level));
  19976. + if (retval < 0)
  19977. + return 0;
  19978. + pressure = force_level > 0 ? force_level : 1;
  19979. + } else {
  19980. + pressure = 1;
  19981. + }
  19982. + input_report_abs(rmi4_data->input_dev,
  19983. + ABS_MT_PRESSURE, pressure);
  19984. +#endif
  19985. +#ifndef TYPE_B_PROTOCOL
  19986. + input_mt_sync(rmi4_data->input_dev);
  19987. +#endif
  19988. +
  19989. + dev_dbg(rmi4_data->pdev->dev.parent,
  19990. + "%s: Finger %d: "
  19991. + "status = 0x%02x, "
  19992. + "x = %d, "
  19993. + "y = %d, "
  19994. + "wx = %d, "
  19995. + "wy = %d\n",
  19996. + __func__, finger,
  19997. + finger_status,
  19998. + x, y, wx, wy);
  19999. +
  20000. + finger_presence = 1;
  20001. + touch_count++;
  20002. + touchs |= BIT(finger);
  20003. + rmi4_data->touchs |= BIT(finger);
  20004. + break;
  20005. + case F12_PALM_STATUS:
  20006. + dev_dbg(rmi4_data->pdev->dev.parent,
  20007. + "%s: Finger %d: "
  20008. + "x = %d, "
  20009. + "y = %d, "
  20010. + "wx = %d, "
  20011. + "wy = %d\n",
  20012. + __func__, finger,
  20013. + x, y, wx, wy);
  20014. + break;
  20015. + case F12_STYLUS_STATUS:
  20016. + case F12_ERASER_STATUS:
  20017. + if (finger_presence) { /* Stylus has priority over fingers */
  20018. + mutex_unlock(&(rmi4_data->rmi4_report_mutex));
  20019. + synaptics_rmi4_free_fingers(rmi4_data);
  20020. + mutex_lock(&(rmi4_data->rmi4_report_mutex));
  20021. + finger_presence = 0;
  20022. + }
  20023. + if (stylus_presence) {/* Allow one stylus at a timee */
  20024. + if (finger + 1 != stylus_presence)
  20025. + break;
  20026. + }
  20027. + input_report_key(rmi4_data->stylus_dev,
  20028. + BTN_TOUCH, 1);
  20029. + if (finger_status == F12_STYLUS_STATUS) {
  20030. + input_report_key(rmi4_data->stylus_dev,
  20031. + BTN_TOOL_PEN, 1);
  20032. + } else {
  20033. + input_report_key(rmi4_data->stylus_dev,
  20034. + BTN_TOOL_RUBBER, 1);
  20035. + }
  20036. + input_report_abs(rmi4_data->stylus_dev,
  20037. + ABS_X, x);
  20038. + input_report_abs(rmi4_data->stylus_dev,
  20039. + ABS_Y, y);
  20040. +
  20041. + stylus_presence = finger + 1;
  20042. + touch_count++;
  20043. + break;
  20044. + default:
  20045. +#ifdef TYPE_B_PROTOCOL
  20046. + input_mt_slot(rmi4_data->input_dev, finger);
  20047. + input_mt_report_slot_state(rmi4_data->input_dev,
  20048. + MT_TOOL_FINGER, 0);
  20049. +#endif
  20050. + rmi4_data->touchs &= ~BIT(finger);
  20051. + touchs &= ~BIT(finger);
  20052. + break;
  20053. + }
  20054. + }
  20055. +
  20056. + for (finger = 0; finger < fhandler->num_of_data_points; finger++) {
  20057. + if (BIT(finger) & (rmi4_data->touchs ^ touchs)) {
  20058. + input_mt_slot(rmi4_data->input_dev, finger);
  20059. + input_mt_report_slot_state(rmi4_data->input_dev,
  20060. + MT_TOOL_FINGER, 0);
  20061. + }
  20062. + }
  20063. +
  20064. + if (touch_count == 0) {
  20065. + finger_presence = 0;
  20066. +#ifdef F12_DATA_15_WORKAROUND
  20067. + objects_already_present = 0;
  20068. +#endif
  20069. + input_report_key(rmi4_data->input_dev,
  20070. + BTN_TOUCH, 0);
  20071. + input_report_key(rmi4_data->input_dev,
  20072. + BTN_TOOL_FINGER, 0);
  20073. +#ifndef TYPE_B_PROTOCOL
  20074. + input_mt_sync(rmi4_data->input_dev);
  20075. +#endif
  20076. +
  20077. + if (rmi4_data->stylus_enable) {
  20078. + stylus_presence = 0;
  20079. + input_report_key(rmi4_data->stylus_dev,
  20080. + BTN_TOUCH, 0);
  20081. + input_report_key(rmi4_data->stylus_dev,
  20082. + BTN_TOOL_PEN, 0);
  20083. + if (rmi4_data->eraser_enable) {
  20084. + input_report_key(rmi4_data->stylus_dev,
  20085. + BTN_TOOL_RUBBER, 0);
  20086. + }
  20087. + }
  20088. +
  20089. + rmi4_data->touchs = 0;
  20090. + }
  20091. +
  20092. + input_sync(rmi4_data->input_dev);
  20093. +
  20094. + mutex_unlock(&(rmi4_data->rmi4_report_mutex));
  20095. +
  20096. + return touch_count;
  20097. +}
  20098. +
  20099. +static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
  20100. + struct synaptics_rmi4_fn *fhandler)
  20101. +{
  20102. + int retval;
  20103. + unsigned char touch_count = 0;
  20104. + unsigned char button;
  20105. + unsigned char index;
  20106. + unsigned char shift;
  20107. + unsigned char status;
  20108. + unsigned char *data;
  20109. + unsigned short data_addr = fhandler->full_addr.data_base;
  20110. + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
  20111. + static unsigned char do_once = 1;
  20112. + static bool current_status[MAX_NUMBER_OF_BUTTONS];
  20113. +#ifdef NO_0D_WHILE_2D
  20114. + static bool before_2d_status[MAX_NUMBER_OF_BUTTONS];
  20115. + static bool while_2d_status[MAX_NUMBER_OF_BUTTONS];
  20116. +#endif
  20117. +
  20118. + if (do_once) {
  20119. + memset(current_status, 0, sizeof(current_status));
  20120. +#ifdef NO_0D_WHILE_2D
  20121. + memset(before_2d_status, 0, sizeof(before_2d_status));
  20122. + memset(while_2d_status, 0, sizeof(while_2d_status));
  20123. +#endif
  20124. + do_once = 0;
  20125. + }
  20126. +
  20127. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20128. + data_addr,
  20129. + f1a->button_data_buffer,
  20130. + f1a->button_bitmask_size);
  20131. + if (retval < 0) {
  20132. + dev_err(rmi4_data->pdev->dev.parent,
  20133. + "%s: Failed to read button data registers\n",
  20134. + __func__);
  20135. + return;
  20136. + }
  20137. +
  20138. + data = f1a->button_data_buffer;
  20139. +
  20140. + mutex_lock(&(rmi4_data->rmi4_report_mutex));
  20141. +
  20142. + for (button = 0; button < f1a->valid_button_count; button++) {
  20143. + index = button / 8;
  20144. + shift = button % 8;
  20145. + status = ((data[index] >> shift) & MASK_1BIT);
  20146. +
  20147. + if (current_status[button] == status) {
  20148. + if (!rmi4_data->suspend)
  20149. + continue;
  20150. + } else
  20151. + current_status[button] = status;
  20152. +
  20153. + dev_err(rmi4_data->pdev->dev.parent,
  20154. + "%s: Button %d (code %d) ->%d\n",
  20155. + __func__, button,
  20156. + f1a->button_map[button],
  20157. + status);
  20158. +#ifdef NO_0D_WHILE_2D
  20159. + if (rmi4_data->fingers_on_2d == false) {
  20160. + if (status == 1) {
  20161. + before_2d_status[button] = 1;
  20162. + } else {
  20163. + if (while_2d_status[button] == 1) {
  20164. + while_2d_status[button] = 0;
  20165. + continue;
  20166. + } else {
  20167. + before_2d_status[button] = 0;
  20168. + }
  20169. + }
  20170. +
  20171. + touch_count++;
  20172. + input_report_key(rmi4_data->input_dev,
  20173. + f1a->button_map[button],
  20174. + status);
  20175. + } else {
  20176. + if (before_2d_status[button] == 1) {
  20177. + before_2d_status[button] = 0;
  20178. + touch_count++;
  20179. + input_report_key(rmi4_data->input_dev,
  20180. + f1a->button_map[button],
  20181. + status);
  20182. + } else {
  20183. + if (status == 1)
  20184. + while_2d_status[button] = 1;
  20185. + else
  20186. + while_2d_status[button] = 0;
  20187. + }
  20188. + }
  20189. +#else
  20190. + touch_count++;
  20191. + input_report_key(rmi4_data->input_dev,
  20192. + f1a->button_map[button],
  20193. + status);
  20194. +#endif
  20195. + }
  20196. +
  20197. + if (touch_count)
  20198. + input_sync(rmi4_data->input_dev);
  20199. +
  20200. + mutex_unlock(&(rmi4_data->rmi4_report_mutex));
  20201. +
  20202. + return;
  20203. +}
  20204. +
  20205. +static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data,
  20206. + struct synaptics_rmi4_fn *fhandler)
  20207. +{
  20208. + unsigned char touch_count_2d;
  20209. +
  20210. + dev_dbg(rmi4_data->pdev->dev.parent,
  20211. + "%s: Function %02x reporting\n",
  20212. + __func__, fhandler->fn_number);
  20213. +
  20214. + switch (fhandler->fn_number) {
  20215. + case SYNAPTICS_RMI4_F11:
  20216. + touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data,
  20217. + fhandler);
  20218. +
  20219. + if (touch_count_2d)
  20220. + rmi4_data->fingers_on_2d = true;
  20221. + else
  20222. + rmi4_data->fingers_on_2d = false;
  20223. + break;
  20224. + case SYNAPTICS_RMI4_F12:
  20225. + touch_count_2d = synaptics_rmi4_f12_abs_report(rmi4_data,
  20226. + fhandler);
  20227. +
  20228. + if (touch_count_2d)
  20229. + rmi4_data->fingers_on_2d = true;
  20230. + else
  20231. + rmi4_data->fingers_on_2d = false;
  20232. + break;
  20233. + case SYNAPTICS_RMI4_F1A:
  20234. + synaptics_rmi4_f1a_report(rmi4_data, fhandler);
  20235. + break;
  20236. + default:
  20237. + break;
  20238. + }
  20239. +
  20240. + return;
  20241. +}
  20242. +
  20243. +static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data,
  20244. + bool report)
  20245. +{
  20246. + int retval;
  20247. + unsigned char data[MAX_INTR_REGISTERS + 1];
  20248. + unsigned char *intr = &data[1];
  20249. + bool was_in_bl_mode;
  20250. + struct synaptics_rmi4_f01_device_status status;
  20251. + struct synaptics_rmi4_fn *fhandler;
  20252. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  20253. + struct synaptics_rmi4_device_info *rmi;
  20254. +
  20255. + rmi = &(rmi4_data->rmi4_mod_info);
  20256. +
  20257. + /*
  20258. + * Get interrupt status information from F01 Data1 register to
  20259. + * determine the source(s) that are flagging the interrupt.
  20260. + */
  20261. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20262. + rmi4_data->f01_data_base_addr,
  20263. + data,
  20264. + rmi4_data->num_of_intr_regs + 1);
  20265. + if (retval < 0) {
  20266. + dev_err(rmi4_data->pdev->dev.parent,
  20267. + "%s: Failed to read interrupt status\n",
  20268. + __func__);
  20269. + return;
  20270. + }
  20271. +
  20272. + status.data[0] = data[0];
  20273. + if (status.status_code == STATUS_CRC_IN_PROGRESS) {
  20274. + retval = synaptics_rmi4_check_status(rmi4_data,
  20275. + &was_in_bl_mode);
  20276. + if (retval < 0) {
  20277. + dev_err(rmi4_data->pdev->dev.parent,
  20278. + "%s: Failed to check status\n",
  20279. + __func__);
  20280. + return;
  20281. + }
  20282. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20283. + rmi4_data->f01_data_base_addr,
  20284. + status.data,
  20285. + sizeof(status.data));
  20286. + if (retval < 0) {
  20287. + dev_err(rmi4_data->pdev->dev.parent,
  20288. + "%s: Failed to read device status\n",
  20289. + __func__);
  20290. + return;
  20291. + }
  20292. + }
  20293. + if (status.unconfigured && !status.flash_prog) {
  20294. + pr_notice("%s: spontaneous reset detected\n", __func__);
  20295. + retval = synaptics_rmi4_reinit_device(rmi4_data);
  20296. + if (retval < 0) {
  20297. + dev_err(rmi4_data->pdev->dev.parent,
  20298. + "%s: Failed to reinit device\n",
  20299. + __func__);
  20300. + }
  20301. + }
  20302. +
  20303. + if (!report)
  20304. + return;
  20305. +
  20306. + /*
  20307. + * Traverse the function handler list and service the source(s)
  20308. + * of the interrupt accordingly.
  20309. + */
  20310. + if (!list_empty(&rmi->support_fn_list)) {
  20311. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  20312. + if (fhandler->num_of_data_sources) {
  20313. + if (fhandler->intr_mask &
  20314. + intr[fhandler->intr_reg_num]) {
  20315. + synaptics_rmi4_report_touch(rmi4_data,
  20316. + fhandler);
  20317. + }
  20318. + }
  20319. + }
  20320. + }
  20321. +
  20322. + mutex_lock(&exp_data.mutex);
  20323. + if (!list_empty(&exp_data.list)) {
  20324. + list_for_each_entry(exp_fhandler, &exp_data.list, link) {
  20325. + if (!exp_fhandler->insert &&
  20326. + !exp_fhandler->remove &&
  20327. + (exp_fhandler->exp_fn->attn != NULL))
  20328. + exp_fhandler->exp_fn->attn(rmi4_data, intr[0]);
  20329. + }
  20330. + }
  20331. + mutex_unlock(&exp_data.mutex);
  20332. +
  20333. + return;
  20334. +}
  20335. +
  20336. +static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
  20337. +{
  20338. + struct synaptics_rmi4_data *rmi4_data = data;
  20339. + const struct synaptics_dsx_board_data *bdata =
  20340. + rmi4_data->hw_if->board_data;
  20341. +
  20342. + if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state)
  20343. + goto exit;
  20344. +
  20345. + if (IRQ_HANDLED == synaptics_filter_interrupt(data))
  20346. + return IRQ_HANDLED;
  20347. +
  20348. + synaptics_rmi4_sensor_report(rmi4_data, true);
  20349. +
  20350. +exit:
  20351. + return IRQ_HANDLED;
  20352. +}
  20353. +
  20354. +static int synaptics_rmi4_int_enable(struct synaptics_rmi4_data *rmi4_data,
  20355. + bool enable)
  20356. +{
  20357. + int retval = 0;
  20358. + unsigned char ii;
  20359. + unsigned char zero = 0x00;
  20360. + unsigned char *intr_mask;
  20361. + unsigned short intr_addr;
  20362. +
  20363. + intr_mask = rmi4_data->intr_mask;
  20364. +
  20365. + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) {
  20366. + if (intr_mask[ii] != 0x00) {
  20367. + intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii;
  20368. + if (enable) {
  20369. + retval = synaptics_rmi4_reg_write(rmi4_data,
  20370. + intr_addr,
  20371. + &(intr_mask[ii]),
  20372. + sizeof(intr_mask[ii]));
  20373. + if (retval < 0)
  20374. + return retval;
  20375. + } else {
  20376. + retval = synaptics_rmi4_reg_write(rmi4_data,
  20377. + intr_addr,
  20378. + &zero,
  20379. + sizeof(zero));
  20380. + if (retval < 0)
  20381. + return retval;
  20382. + }
  20383. + }
  20384. + }
  20385. +
  20386. + return retval;
  20387. +}
  20388. +
  20389. +static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
  20390. + bool enable, bool attn_only)
  20391. +{
  20392. + int retval = 0;
  20393. + const struct synaptics_dsx_board_data *bdata =
  20394. + rmi4_data->hw_if->board_data;
  20395. +
  20396. + if (attn_only) {
  20397. + retval = synaptics_rmi4_int_enable(rmi4_data, enable);
  20398. + return retval;
  20399. + }
  20400. +
  20401. + if (enable) {
  20402. + if (rmi4_data->irq_enabled)
  20403. + return retval;
  20404. +
  20405. + retval = synaptics_rmi4_int_enable(rmi4_data, false);
  20406. + if (retval < 0) {
  20407. + dev_err(rmi4_data->pdev->dev.parent,
  20408. + "%s: Failed to disable synaptics int\n",
  20409. + __func__);
  20410. + return retval;
  20411. + }
  20412. +
  20413. + /* Process and clear interrupts */
  20414. + synaptics_rmi4_sensor_report(rmi4_data, false);
  20415. +
  20416. + retval = request_threaded_irq(rmi4_data->irq, NULL,
  20417. + synaptics_rmi4_irq, bdata->irq_flags,
  20418. + PLATFORM_DRIVER_NAME, rmi4_data);
  20419. + if (retval < 0) {
  20420. + dev_err(rmi4_data->pdev->dev.parent,
  20421. + "%s: Failed to create irq thread\n",
  20422. + __func__);
  20423. + return retval;
  20424. + }
  20425. +
  20426. + retval = synaptics_rmi4_int_enable(rmi4_data, true);
  20427. + if (retval < 0) {
  20428. + dev_err(rmi4_data->pdev->dev.parent,
  20429. + "%s: Failed to enable synaptics int\n",
  20430. + __func__);
  20431. + return retval;
  20432. + }
  20433. +
  20434. + rmi4_data->irq_enabled = true;
  20435. + } else {
  20436. + if (rmi4_data->irq_enabled) {
  20437. + disable_irq(rmi4_data->irq);
  20438. + free_irq(rmi4_data->irq, rmi4_data);
  20439. + rmi4_data->irq_enabled = false;
  20440. + }
  20441. + }
  20442. +
  20443. + return retval;
  20444. +}
  20445. +
  20446. +static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
  20447. + struct synaptics_rmi4_fn_desc *fd,
  20448. + unsigned int intr_count)
  20449. +{
  20450. + unsigned char ii;
  20451. + unsigned char intr_offset;
  20452. +
  20453. + fhandler->intr_reg_num = (intr_count + 7) / 8;
  20454. + if (fhandler->intr_reg_num != 0)
  20455. + fhandler->intr_reg_num -= 1;
  20456. +
  20457. + /* Set an enable bit for each data source */
  20458. + intr_offset = intr_count % 8;
  20459. + fhandler->intr_mask = 0;
  20460. + for (ii = intr_offset;
  20461. + ii < (fd->intr_src_count + intr_offset);
  20462. + ii++)
  20463. + fhandler->intr_mask |= 1 << ii;
  20464. +
  20465. + return;
  20466. +}
  20467. +
  20468. +static int synaptics_rmi4_query_product_id(struct synaptics_rmi4_data *rmi4_data)
  20469. +{
  20470. + int retval;
  20471. + unsigned short lockdown_addr;
  20472. +
  20473. + /* Product ID addr starts from F01_RMI_QUERY11 */
  20474. + lockdown_addr = rmi4_data->f01_query_base_addr + F01_PROD_ID_OFFSET;
  20475. +
  20476. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20477. + lockdown_addr,
  20478. + rmi4_data->lockdown_info,
  20479. + LOCKDOWN_INFO_SIZE);
  20480. + if (retval < 0) {
  20481. + dev_err(rmi4_data->pdev->dev.parent,
  20482. + "Failed reading reg %d\n",
  20483. + lockdown_addr);
  20484. + return retval;
  20485. + }
  20486. +
  20487. + dev_info(rmi4_data->pdev->dev.parent,
  20488. + "Lockdown info: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
  20489. + rmi4_data->lockdown_info[0], rmi4_data->lockdown_info[1],
  20490. + rmi4_data->lockdown_info[2], rmi4_data->lockdown_info[3],
  20491. + rmi4_data->lockdown_info[4], rmi4_data->lockdown_info[5],
  20492. + rmi4_data->lockdown_info[6], rmi4_data->lockdown_info[7]);
  20493. +
  20494. + return 0;
  20495. +}
  20496. +
  20497. +static int synaptics_rmi4_query_chip_id(struct synaptics_rmi4_data *rmi4_data)
  20498. +{
  20499. + int retval, i;
  20500. + unsigned short chipdata_addr;
  20501. + unsigned char query_data[8] = {0};
  20502. +
  20503. + chipdata_addr = rmi4_data->f01_query_base_addr + F01_PROD_ID_OFFSET;
  20504. +
  20505. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20506. + chipdata_addr,
  20507. + query_data,
  20508. + 8);
  20509. + if (retval < 0) {
  20510. + dev_err(rmi4_data->pdev->dev.parent,
  20511. + "Failed reading reg %d\n",
  20512. + chipdata_addr);
  20513. + return retval;
  20514. + }
  20515. +
  20516. + dev_info(rmi4_data->pdev->dev.parent,
  20517. + "chip info: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
  20518. + query_data[0], query_data[1],
  20519. + query_data[2], query_data[3],
  20520. + query_data[4], query_data[5],
  20521. + query_data[6], query_data[7]);
  20522. +
  20523. + for (i = 0; i < rmi4_data->hw_if->board_data->config_array_size; i++) {
  20524. + if (!memcmp(rmi4_data->hw_if->board_data->config_array[i].chip_id_name,
  20525. + query_data,
  20526. + strlen(rmi4_data->hw_if->board_data->config_array[i].chip_id_name))) {
  20527. + rmi4_data->chip_id = rmi4_data->hw_if->board_data->config_array[i].chip_id;
  20528. + rmi4_data->chip_is_tddi = rmi4_data->hw_if->board_data->config_array[i].chip_is_tddi;
  20529. + rmi4_data->panel_power_seq = rmi4_data->hw_if->board_data->config_array[i].panel_power_seq;
  20530. + if (rmi4_data->chip_is_tddi)
  20531. + rmi4_data->hw_if->board_data->reset_gpio = -1;
  20532. + break;
  20533. + }
  20534. + }
  20535. +
  20536. + if (i >= rmi4_data->hw_if->board_data->config_array_size) {
  20537. + dev_err(rmi4_data->pdev->dev.parent, "failed to match the chip id\n");
  20538. + rmi4_data->chip_id = -1; /* Set chip_id -1 to ensure it won't do firmware upgrading */
  20539. + return -EINVAL;
  20540. + }
  20541. +
  20542. + return 0;
  20543. +}
  20544. +
  20545. +static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data,
  20546. + struct synaptics_rmi4_fn *fhandler,
  20547. + struct synaptics_rmi4_fn_desc *fd,
  20548. + unsigned int intr_count)
  20549. +{
  20550. + fhandler->fn_number = fd->fn_number;
  20551. + fhandler->num_of_data_sources = fd->intr_src_count;
  20552. + fhandler->data = NULL;
  20553. + fhandler->extra = NULL;
  20554. +
  20555. + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
  20556. +
  20557. + rmi4_data->f01_query_base_addr = fd->query_base_addr;
  20558. + rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr;
  20559. + rmi4_data->f01_data_base_addr = fd->data_base_addr;
  20560. + rmi4_data->f01_cmd_base_addr = fd->cmd_base_addr;
  20561. +
  20562. + if (rmi4_data->hw_if->board_data->lockdown_area == LOCKDOWN_AREA_PRODUCT_ID)
  20563. + synaptics_rmi4_query_product_id(rmi4_data);
  20564. +
  20565. + return 0;
  20566. +}
  20567. +
  20568. +static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
  20569. + struct synaptics_rmi4_fn *fhandler,
  20570. + struct synaptics_rmi4_fn_desc *fd,
  20571. + unsigned int intr_count)
  20572. +{
  20573. + int retval;
  20574. + int temp;
  20575. + unsigned char offset;
  20576. + unsigned char fingers_supported;
  20577. + struct synaptics_rmi4_f11_extra_data *extra_data;
  20578. + struct synaptics_rmi4_f11_query_0_5 query_0_5;
  20579. + struct synaptics_rmi4_f11_query_7_8 query_7_8;
  20580. + struct synaptics_rmi4_f11_query_9 query_9;
  20581. + struct synaptics_rmi4_f11_query_12 query_12;
  20582. + struct synaptics_rmi4_f11_query_27 query_27;
  20583. + struct synaptics_rmi4_f11_ctrl_6_9 control_6_9;
  20584. + const struct synaptics_dsx_board_data *bdata =
  20585. + rmi4_data->hw_if->board_data;
  20586. +
  20587. + fhandler->fn_number = fd->fn_number;
  20588. + fhandler->num_of_data_sources = fd->intr_src_count;
  20589. + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL);
  20590. + if (!fhandler->extra) {
  20591. + dev_err(rmi4_data->pdev->dev.parent,
  20592. + "%s: Failed to alloc mem for fhandler->extra\n",
  20593. + __func__);
  20594. + return -ENOMEM;
  20595. + }
  20596. + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra;
  20597. +
  20598. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20599. + fhandler->full_addr.query_base,
  20600. + query_0_5.data,
  20601. + sizeof(query_0_5.data));
  20602. + if (retval < 0)
  20603. + return retval;
  20604. +
  20605. + /* Maximum number of fingers supported */
  20606. + if (query_0_5.num_of_fingers <= 4)
  20607. + fhandler->num_of_data_points = query_0_5.num_of_fingers + 1;
  20608. + else if (query_0_5.num_of_fingers == 5)
  20609. + fhandler->num_of_data_points = 10;
  20610. +
  20611. + rmi4_data->num_of_fingers = fhandler->num_of_data_points;
  20612. +
  20613. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20614. + fhandler->full_addr.ctrl_base + 6,
  20615. + control_6_9.data,
  20616. + sizeof(control_6_9.data));
  20617. + if (retval < 0)
  20618. + return retval;
  20619. +
  20620. + /* Maximum x and y */
  20621. + rmi4_data->sensor_max_x = control_6_9.sensor_max_x_pos_7_0 |
  20622. + (control_6_9.sensor_max_x_pos_11_8 << 8);
  20623. + rmi4_data->sensor_max_y = control_6_9.sensor_max_y_pos_7_0 |
  20624. + (control_6_9.sensor_max_y_pos_11_8 << 8);
  20625. + dev_dbg(rmi4_data->pdev->dev.parent,
  20626. + "%s: Function %02x max x = %d max y = %d\n",
  20627. + __func__, fhandler->fn_number,
  20628. + rmi4_data->sensor_max_x,
  20629. + rmi4_data->sensor_max_y);
  20630. +
  20631. + rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH;
  20632. +
  20633. + if (bdata->swap_axes) {
  20634. + temp = rmi4_data->sensor_max_x;
  20635. + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y;
  20636. + rmi4_data->sensor_max_y = temp;
  20637. + }
  20638. +
  20639. + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
  20640. +
  20641. + fhandler->data = NULL;
  20642. +
  20643. + offset = sizeof(query_0_5.data);
  20644. +
  20645. + /* query 6 */
  20646. + if (query_0_5.has_rel)
  20647. + offset += 1;
  20648. +
  20649. + /* queries 7 8 */
  20650. + if (query_0_5.has_gestures) {
  20651. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20652. + fhandler->full_addr.query_base + offset,
  20653. + query_7_8.data,
  20654. + sizeof(query_7_8.data));
  20655. + if (retval < 0)
  20656. + return retval;
  20657. +
  20658. + offset += sizeof(query_7_8.data);
  20659. + }
  20660. +
  20661. + /* query 9 */
  20662. + if (query_0_5.has_query_9) {
  20663. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20664. + fhandler->full_addr.query_base + offset,
  20665. + query_9.data,
  20666. + sizeof(query_9.data));
  20667. + if (retval < 0)
  20668. + return retval;
  20669. +
  20670. + offset += sizeof(query_9.data);
  20671. + }
  20672. +
  20673. + /* query 10 */
  20674. + if (query_0_5.has_gestures && query_7_8.has_touch_shapes)
  20675. + offset += 1;
  20676. +
  20677. + /* query 11 */
  20678. + if (query_0_5.has_query_11)
  20679. + offset += 1;
  20680. +
  20681. + /* query 12 */
  20682. + if (query_0_5.has_query_12) {
  20683. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20684. + fhandler->full_addr.query_base + offset,
  20685. + query_12.data,
  20686. + sizeof(query_12.data));
  20687. + if (retval < 0)
  20688. + return retval;
  20689. +
  20690. + offset += sizeof(query_12.data);
  20691. + }
  20692. +
  20693. + /* query 13 */
  20694. + if (query_0_5.has_jitter_filter)
  20695. + offset += 1;
  20696. +
  20697. + /* query 14 */
  20698. + if (query_0_5.has_query_12 && query_12.has_general_information_2)
  20699. + offset += 1;
  20700. +
  20701. + /* queries 15 16 17 18 19 20 21 22 23 24 25 26*/
  20702. + if (query_0_5.has_query_12 && query_12.has_physical_properties)
  20703. + offset += 12;
  20704. +
  20705. + /* query 27 */
  20706. + if (query_0_5.has_query_27) {
  20707. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20708. + fhandler->full_addr.query_base + offset,
  20709. + query_27.data,
  20710. + sizeof(query_27.data));
  20711. + if (retval < 0)
  20712. + return retval;
  20713. +
  20714. + rmi4_data->f11_wakeup_gesture = query_27.has_wakeup_gesture;
  20715. + }
  20716. +
  20717. + if (!rmi4_data->f11_wakeup_gesture)
  20718. + return retval;
  20719. +
  20720. + /* data 0 */
  20721. + fingers_supported = fhandler->num_of_data_points;
  20722. + offset = (fingers_supported + 3) / 4;
  20723. +
  20724. + /* data 1 2 3 4 5 */
  20725. + offset += 5 * fingers_supported;
  20726. +
  20727. + /* data 6 7 */
  20728. + if (query_0_5.has_rel)
  20729. + offset += 2 * fingers_supported;
  20730. +
  20731. + /* data 8 */
  20732. + if (query_0_5.has_gestures && query_7_8.data[0])
  20733. + offset += 1;
  20734. +
  20735. + /* data 9 */
  20736. + if (query_0_5.has_gestures && (query_7_8.data[0] || query_7_8.data[1]))
  20737. + offset += 1;
  20738. +
  20739. + /* data 10 */
  20740. + if (query_0_5.has_gestures &&
  20741. + (query_7_8.has_pinch || query_7_8.has_flick))
  20742. + offset += 1;
  20743. +
  20744. + /* data 11 12 */
  20745. + if (query_0_5.has_gestures &&
  20746. + (query_7_8.has_flick || query_7_8.has_rotate))
  20747. + offset += 2;
  20748. +
  20749. + /* data 13 */
  20750. + if (query_0_5.has_gestures && query_7_8.has_touch_shapes)
  20751. + offset += (fingers_supported + 3) / 4;
  20752. +
  20753. + /* data 14 15 */
  20754. + if (query_0_5.has_gestures &&
  20755. + (query_7_8.has_scroll_zones ||
  20756. + query_7_8.has_multi_finger_scroll ||
  20757. + query_7_8.has_chiral_scroll))
  20758. + offset += 2;
  20759. +
  20760. + /* data 16 17 */
  20761. + if (query_0_5.has_gestures &&
  20762. + (query_7_8.has_scroll_zones &&
  20763. + query_7_8.individual_scroll_zones))
  20764. + offset += 2;
  20765. +
  20766. + /* data 18 19 20 21 22 23 24 25 26 27 */
  20767. + if (query_0_5.has_query_9 && query_9.has_contact_geometry)
  20768. + offset += 10 * fingers_supported;
  20769. +
  20770. + /* data 28 */
  20771. + if (query_0_5.has_bending_correction ||
  20772. + query_0_5.has_large_object_suppression)
  20773. + offset += 1;
  20774. +
  20775. + /* data 29 30 31 */
  20776. + if (query_0_5.has_query_9 && query_9.has_pen_hover_discrimination)
  20777. + offset += 3;
  20778. +
  20779. + /* data 32 */
  20780. + if (query_0_5.has_query_12 &&
  20781. + query_12.has_small_object_detection_tuning)
  20782. + offset += 1;
  20783. +
  20784. + /* data 33 34 */
  20785. + if (query_0_5.has_query_27 && query_27.f11_query27_b0)
  20786. + offset += 2;
  20787. +
  20788. + /* data 35 */
  20789. + if (query_0_5.has_query_12 && query_12.has_8bit_w)
  20790. + offset += fingers_supported;
  20791. +
  20792. + /* data 36 */
  20793. + if (query_0_5.has_bending_correction)
  20794. + offset += 1;
  20795. +
  20796. + /* data 37 */
  20797. + if (query_0_5.has_query_27 && query_27.has_data_37)
  20798. + offset += 1;
  20799. +
  20800. + /* data 38 */
  20801. + if (query_0_5.has_query_27 && query_27.has_wakeup_gesture)
  20802. + extra_data->data38_offset = offset;
  20803. +
  20804. + return retval;
  20805. +}
  20806. +
  20807. +static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data,
  20808. + unsigned short ctrl28)
  20809. +{
  20810. + int retval;
  20811. + static unsigned short ctrl_28_address;
  20812. +
  20813. + if (ctrl28)
  20814. + ctrl_28_address = ctrl28;
  20815. +
  20816. + retval = synaptics_rmi4_reg_write(rmi4_data,
  20817. + ctrl_28_address,
  20818. + &rmi4_data->report_enable,
  20819. + sizeof(rmi4_data->report_enable));
  20820. + if (retval < 0)
  20821. + return retval;
  20822. +
  20823. + return retval;
  20824. +}
  20825. +
  20826. +static int synaptics_rmi4_f12_find_sub(struct synaptics_rmi4_data *rmi4_data,
  20827. + struct synaptics_rmi4_fn *fhandler,
  20828. + unsigned char *presence, unsigned char presence_size,
  20829. + unsigned char structure_offset, unsigned char reg,
  20830. + unsigned char sub)
  20831. +{
  20832. + int retval;
  20833. + unsigned char cnt;
  20834. + unsigned char regnum;
  20835. + unsigned char bitnum;
  20836. + unsigned char p_index;
  20837. + unsigned char s_index;
  20838. + unsigned char offset;
  20839. + unsigned char max_reg;
  20840. + unsigned char *structure;
  20841. +
  20842. + max_reg = (presence_size - 1) * 8 - 1;
  20843. +
  20844. + if (reg > max_reg) {
  20845. + dev_err(rmi4_data->pdev->dev.parent,
  20846. + "%s: Register number (%d) over limit\n",
  20847. + __func__, reg);
  20848. + return -EINVAL;
  20849. + }
  20850. +
  20851. + p_index = reg / 8 + 1;
  20852. + bitnum = reg % 8;
  20853. + if ((presence[p_index] & (1 << bitnum)) == 0x00) {
  20854. + dev_err(rmi4_data->pdev->dev.parent,
  20855. + "%s: Register %d is not present\n",
  20856. + __func__, reg);
  20857. + return -EINVAL;
  20858. + }
  20859. +
  20860. + structure = kmalloc(presence[0], GFP_KERNEL);
  20861. + if (!structure) {
  20862. + dev_err(rmi4_data->pdev->dev.parent,
  20863. + "%s: Failed to alloc mem for structure register\n",
  20864. + __func__);
  20865. + return -ENOMEM;
  20866. + }
  20867. +
  20868. + retval = synaptics_rmi4_reg_read(rmi4_data,
  20869. + fhandler->full_addr.query_base + structure_offset,
  20870. + structure,
  20871. + presence[0]);
  20872. + if (retval < 0)
  20873. + goto exit;
  20874. +
  20875. + s_index = 0;
  20876. +
  20877. + for (regnum = 0; regnum < reg; regnum++) {
  20878. + p_index = regnum / 8 + 1;
  20879. + bitnum = regnum % 8;
  20880. + if ((presence[p_index] & (1 << bitnum)) == 0x00)
  20881. + continue;
  20882. +
  20883. + if (structure[s_index] == 0x00)
  20884. + s_index += 3;
  20885. + else
  20886. + s_index++;
  20887. +
  20888. + while (structure[s_index] & ~MASK_7BIT)
  20889. + s_index++;
  20890. +
  20891. + s_index++;
  20892. + }
  20893. +
  20894. + cnt = 0;
  20895. + s_index++;
  20896. + offset = sub / 7;
  20897. + bitnum = sub % 7;
  20898. +
  20899. + do {
  20900. + if (cnt == offset) {
  20901. + if (structure[s_index + cnt] & (1 << bitnum))
  20902. + retval = 1;
  20903. + else
  20904. + retval = 0;
  20905. + goto exit;
  20906. + }
  20907. + cnt++;
  20908. + } while (structure[s_index + cnt - 1] & ~MASK_7BIT);
  20909. +
  20910. + retval = 0;
  20911. +
  20912. +exit:
  20913. + kfree(structure);
  20914. +
  20915. + return retval;
  20916. +}
  20917. +
  20918. +static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
  20919. + struct synaptics_rmi4_fn *fhandler,
  20920. + struct synaptics_rmi4_fn_desc *fd,
  20921. + unsigned int intr_count)
  20922. +{
  20923. + int retval = 0;
  20924. + int temp;
  20925. + unsigned char subpacket;
  20926. + unsigned char ctrl_23_size;
  20927. + unsigned char size_of_2d_data;
  20928. + unsigned char size_of_query5;
  20929. + unsigned char size_of_query8;
  20930. + unsigned char ctrl_8_offset;
  20931. + unsigned char ctrl_20_offset;
  20932. + unsigned char ctrl_23_offset;
  20933. + unsigned char ctrl_26_offset;
  20934. + unsigned char ctrl_27_offset;
  20935. + unsigned char ctrl_28_offset;
  20936. + unsigned char ctrl_31_offset;
  20937. + unsigned char ctrl_47_offset;
  20938. + unsigned char ctrl_58_offset;
  20939. + unsigned char num_of_fingers;
  20940. + struct synaptics_rmi4_f12_extra_data *extra_data;
  20941. + struct synaptics_rmi4_f12_query_5 *query_5 = NULL;
  20942. + struct synaptics_rmi4_f12_query_8 *query_8 = NULL;
  20943. + struct synaptics_rmi4_f12_ctrl_8 *ctrl_8 = NULL;
  20944. + struct synaptics_rmi4_f12_ctrl_23 *ctrl_23 = NULL;
  20945. + struct synaptics_rmi4_f12_ctrl_31 *ctrl_31 = NULL;
  20946. + struct synaptics_rmi4_f12_ctrl_58 *ctrl_58 = NULL;
  20947. + const struct synaptics_dsx_board_data *bdata =
  20948. + rmi4_data->hw_if->board_data;
  20949. +
  20950. + fhandler->fn_number = fd->fn_number;
  20951. + fhandler->num_of_data_sources = fd->intr_src_count;
  20952. + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL);
  20953. + if (!fhandler->extra) {
  20954. + dev_err(rmi4_data->pdev->dev.parent,
  20955. + "%s: Failed to alloc mem for fhandler->extra\n",
  20956. + __func__);
  20957. + return -ENOMEM;
  20958. + }
  20959. + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
  20960. + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
  20961. +
  20962. + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL);
  20963. + if (!query_5) {
  20964. + dev_err(rmi4_data->pdev->dev.parent,
  20965. + "%s: Failed to alloc mem for query_5\n",
  20966. + __func__);
  20967. + retval = -ENOMEM;
  20968. + goto exit;
  20969. + }
  20970. +
  20971. + query_8 = kzalloc(sizeof(*query_8), GFP_KERNEL);
  20972. + if (!query_8) {
  20973. + dev_err(rmi4_data->pdev->dev.parent,
  20974. + "%s: Failed to alloc mem for query_8\n",
  20975. + __func__);
  20976. + retval = -ENOMEM;
  20977. + goto exit;
  20978. + }
  20979. +
  20980. + ctrl_8 = kzalloc(sizeof(*ctrl_8), GFP_KERNEL);
  20981. + if (!ctrl_8) {
  20982. + dev_err(rmi4_data->pdev->dev.parent,
  20983. + "%s: Failed to alloc mem for ctrl_8\n",
  20984. + __func__);
  20985. + retval = -ENOMEM;
  20986. + goto exit;
  20987. + }
  20988. +
  20989. + ctrl_23 = kzalloc(sizeof(*ctrl_23), GFP_KERNEL);
  20990. + if (!ctrl_23) {
  20991. + dev_err(rmi4_data->pdev->dev.parent,
  20992. + "%s: Failed to alloc mem for ctrl_23\n",
  20993. + __func__);
  20994. + retval = -ENOMEM;
  20995. + goto exit;
  20996. + }
  20997. +
  20998. + ctrl_31 = kzalloc(sizeof(*ctrl_31), GFP_KERNEL);
  20999. + if (!ctrl_31) {
  21000. + dev_err(rmi4_data->pdev->dev.parent,
  21001. + "%s: Failed to alloc mem for ctrl_31\n",
  21002. + __func__);
  21003. + retval = -ENOMEM;
  21004. + goto exit;
  21005. + }
  21006. +
  21007. + ctrl_58 = kzalloc(sizeof(*ctrl_58), GFP_KERNEL);
  21008. + if (!ctrl_58) {
  21009. + dev_err(rmi4_data->pdev->dev.parent,
  21010. + "%s: Failed to alloc mem for ctrl_58\n",
  21011. + __func__);
  21012. + retval = -ENOMEM;
  21013. + goto exit;
  21014. + }
  21015. +
  21016. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21017. + fhandler->full_addr.query_base + 4,
  21018. + &size_of_query5,
  21019. + sizeof(size_of_query5));
  21020. + if (retval < 0)
  21021. + goto exit;
  21022. +
  21023. + pr_err("%s %d: fhandler->full_addr.query_base = 0x%04x\n", __func__, __LINE__, fhandler->full_addr.query_base);
  21024. + pr_err("%s %d: fhandler->full_addr.ctrl_base = 0x%04x\n", __func__, __LINE__, fhandler->full_addr.ctrl_base);
  21025. + pr_err("%s %d: size_of_query5 = %d\n", __func__, __LINE__, size_of_query5);
  21026. +
  21027. + if (size_of_query5 > sizeof(query_5->data))
  21028. + size_of_query5 = sizeof(query_5->data);
  21029. + memset(query_5->data, 0x00, sizeof(query_5->data));
  21030. +
  21031. + pr_err("%s %d: size_of_query5 = %d\n", __func__, __LINE__, size_of_query5);
  21032. +
  21033. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21034. + fhandler->full_addr.query_base + 5,
  21035. + query_5->data,
  21036. + size_of_query5);
  21037. + if (retval < 0)
  21038. + goto exit;
  21039. +
  21040. + ctrl_8_offset = query_5->ctrl0_is_present +
  21041. + query_5->ctrl1_is_present +
  21042. + query_5->ctrl2_is_present +
  21043. + query_5->ctrl3_is_present +
  21044. + query_5->ctrl4_is_present +
  21045. + query_5->ctrl5_is_present +
  21046. + query_5->ctrl6_is_present +
  21047. + query_5->ctrl7_is_present;
  21048. +
  21049. + ctrl_20_offset = ctrl_8_offset +
  21050. + query_5->ctrl8_is_present +
  21051. + query_5->ctrl9_is_present +
  21052. + query_5->ctrl10_is_present +
  21053. + query_5->ctrl11_is_present +
  21054. + query_5->ctrl12_is_present +
  21055. + query_5->ctrl13_is_present +
  21056. + query_5->ctrl14_is_present +
  21057. + query_5->ctrl15_is_present +
  21058. + query_5->ctrl16_is_present +
  21059. + query_5->ctrl17_is_present +
  21060. + query_5->ctrl18_is_present +
  21061. + query_5->ctrl19_is_present;
  21062. +
  21063. + ctrl_23_offset = ctrl_20_offset +
  21064. + query_5->ctrl20_is_present +
  21065. + query_5->ctrl21_is_present +
  21066. + query_5->ctrl22_is_present;
  21067. +
  21068. +
  21069. + ctrl_26_offset = ctrl_23_offset +
  21070. + query_5->ctrl23_is_present +
  21071. + query_5->ctrl24_is_present +
  21072. + query_5->ctrl25_is_present;
  21073. +
  21074. + ctrl_27_offset = ctrl_26_offset +
  21075. + query_5->ctrl26_is_present;
  21076. +
  21077. + ctrl_28_offset = ctrl_27_offset +
  21078. + query_5->ctrl27_is_present;
  21079. +
  21080. + ctrl_31_offset = ctrl_28_offset +
  21081. + query_5->ctrl28_is_present +
  21082. + query_5->ctrl29_is_present +
  21083. + query_5->ctrl30_is_present;
  21084. +
  21085. + ctrl_47_offset = ctrl_31_offset +
  21086. + query_5->ctrl31_is_present +
  21087. + query_5->ctrl32_is_present +
  21088. + query_5->ctrl33_is_present +
  21089. + query_5->ctrl34_is_present +
  21090. + query_5->ctrl35_is_present +
  21091. + query_5->ctrl36_is_present +
  21092. + query_5->ctrl37_is_present +
  21093. + query_5->ctrl38_is_present +
  21094. + query_5->ctrl39_is_present +
  21095. + query_5->ctrl40_is_present +
  21096. + query_5->ctrl41_is_present +
  21097. + query_5->ctrl42_is_present +
  21098. + query_5->ctrl43_is_present +
  21099. + query_5->ctrl44_is_present +
  21100. + query_5->ctrl45_is_present +
  21101. + query_5->ctrl46_is_present;
  21102. + ctrl_58_offset = ctrl_47_offset +
  21103. + query_5->ctrl47_is_present +
  21104. + query_5->ctrl48_is_present +
  21105. + query_5->ctrl49_is_present +
  21106. + query_5->ctrl50_is_present +
  21107. + query_5->ctrl51_is_present +
  21108. + query_5->ctrl52_is_present +
  21109. + query_5->ctrl53_is_present +
  21110. + query_5->ctrl54_is_present +
  21111. + query_5->ctrl55_is_present +
  21112. + query_5->ctrl56_is_present +
  21113. + query_5->ctrl57_is_present;
  21114. +
  21115. + ctrl_23_size = 2;
  21116. + for (subpacket = 2; subpacket <= 4; subpacket++) {
  21117. + retval = synaptics_rmi4_f12_find_sub(rmi4_data,
  21118. + fhandler, query_5->data, sizeof(query_5->data),
  21119. + 6, 23, subpacket);
  21120. + if (retval == 1)
  21121. + ctrl_23_size++;
  21122. + else if (retval < 0)
  21123. + goto exit;
  21124. + }
  21125. +
  21126. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21127. + fhandler->full_addr.ctrl_base + ctrl_23_offset,
  21128. + ctrl_23->data,
  21129. + ctrl_23_size);
  21130. + if (retval < 0)
  21131. + goto exit;
  21132. +
  21133. + /* Maximum number of fingers supported */
  21134. + fhandler->num_of_data_points = min_t(unsigned char,
  21135. + ctrl_23->max_reported_objects,
  21136. + (unsigned char)F12_FINGERS_TO_SUPPORT);
  21137. +
  21138. + num_of_fingers = fhandler->num_of_data_points;
  21139. + rmi4_data->num_of_fingers = num_of_fingers;
  21140. +
  21141. + rmi4_data->stylus_enable = ctrl_23->stylus_enable;
  21142. + rmi4_data->eraser_enable = ctrl_23->eraser_enable;
  21143. +
  21144. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21145. + fhandler->full_addr.query_base + 7,
  21146. + &size_of_query8,
  21147. + sizeof(size_of_query8));
  21148. + if (retval < 0)
  21149. + goto exit;
  21150. +
  21151. + if (size_of_query8 > sizeof(query_8->data))
  21152. + size_of_query8 = sizeof(query_8->data);
  21153. + memset(query_8->data, 0x00, sizeof(query_8->data));
  21154. +
  21155. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21156. + fhandler->full_addr.query_base + 8,
  21157. + query_8->data,
  21158. + size_of_query8);
  21159. + if (retval < 0)
  21160. + goto exit;
  21161. +
  21162. + /* Determine the presence of the Data0 register */
  21163. + extra_data->data1_offset = query_8->data0_is_present;
  21164. +
  21165. + if ((size_of_query8 >= 3) && (query_8->data15_is_present)) {
  21166. + extra_data->data15_offset = query_8->data0_is_present +
  21167. + query_8->data1_is_present +
  21168. + query_8->data2_is_present +
  21169. + query_8->data3_is_present +
  21170. + query_8->data4_is_present +
  21171. + query_8->data5_is_present +
  21172. + query_8->data6_is_present +
  21173. + query_8->data7_is_present +
  21174. + query_8->data8_is_present +
  21175. + query_8->data9_is_present +
  21176. + query_8->data10_is_present +
  21177. + query_8->data11_is_present +
  21178. + query_8->data12_is_present +
  21179. + query_8->data13_is_present +
  21180. + query_8->data14_is_present;
  21181. + extra_data->data15_size = (num_of_fingers + 7) / 8;
  21182. + } else {
  21183. + extra_data->data15_size = 0;
  21184. + }
  21185. +
  21186. +#ifdef REPORT_2D_PRESSURE
  21187. + if ((size_of_query8 >= 5) && (query_8->data29_is_present)) {
  21188. + extra_data->data29_offset = query_8->data0_is_present +
  21189. + query_8->data1_is_present +
  21190. + query_8->data2_is_present +
  21191. + query_8->data3_is_present +
  21192. + query_8->data4_is_present +
  21193. + query_8->data5_is_present +
  21194. + query_8->data6_is_present +
  21195. + query_8->data7_is_present +
  21196. + query_8->data8_is_present +
  21197. + query_8->data9_is_present +
  21198. + query_8->data10_is_present +
  21199. + query_8->data11_is_present +
  21200. + query_8->data12_is_present +
  21201. + query_8->data13_is_present +
  21202. + query_8->data14_is_present +
  21203. + query_8->data15_is_present +
  21204. + query_8->data16_is_present +
  21205. + query_8->data17_is_present +
  21206. + query_8->data18_is_present +
  21207. + query_8->data19_is_present +
  21208. + query_8->data20_is_present +
  21209. + query_8->data21_is_present +
  21210. + query_8->data22_is_present +
  21211. + query_8->data23_is_present +
  21212. + query_8->data24_is_present +
  21213. + query_8->data25_is_present +
  21214. + query_8->data26_is_present +
  21215. + query_8->data27_is_present +
  21216. + query_8->data28_is_present;
  21217. + extra_data->data29_size = 0;
  21218. + for (subpacket = 0; subpacket <= num_of_fingers; subpacket++) {
  21219. + retval = synaptics_rmi4_f12_find_sub(rmi4_data,
  21220. + fhandler, query_8->data,
  21221. + sizeof(query_8->data),
  21222. + 9, 29, subpacket);
  21223. + if (retval == 1)
  21224. + extra_data->data29_size += 2;
  21225. + else if (retval < 0)
  21226. + goto exit;
  21227. + }
  21228. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21229. + fhandler->full_addr.ctrl_base + ctrl_58_offset,
  21230. + ctrl_58->data,
  21231. + sizeof(ctrl_58->data));
  21232. + if (retval < 0)
  21233. + goto exit;
  21234. +
  21235. + pr_err("%s %d: extra_data->data29_offset = %d\n", __func__, __LINE__, extra_data->data29_offset);
  21236. + pr_err("%s %d: extra_data->data29_size = %d\n", __func__, __LINE__, extra_data->data29_size);
  21237. + pr_err("%s %d: ctrl_58_offset = %d\n", __func__, __LINE__, ctrl_58_offset);
  21238. +
  21239. + rmi4_data->force_min =
  21240. + (int)(ctrl_58->min_force_lsb << 0) |
  21241. + (int)(ctrl_58->min_force_msb << 8);
  21242. + rmi4_data->force_max =
  21243. + (int)(ctrl_58->max_force_lsb << 0) |
  21244. + (int)(ctrl_58->max_force_msb << 8);
  21245. +
  21246. + pr_err("%s %d: rmi4_data->force_min = %d\n", __func__, __LINE__, rmi4_data->force_min);
  21247. + pr_err("%s %d: rmi4_data->force_max = %d\n", __func__, __LINE__, rmi4_data->force_max);
  21248. +
  21249. + rmi4_data->report_pressure = true;
  21250. + } else {
  21251. + extra_data->data29_size = 0;
  21252. + rmi4_data->report_pressure = false;
  21253. + }
  21254. +#endif
  21255. +
  21256. + rmi4_data->report_enable = RPT_DEFAULT;
  21257. +#ifdef REPORT_2D_Z
  21258. + rmi4_data->report_enable |= RPT_Z;
  21259. +#endif
  21260. +#ifdef REPORT_2D_W
  21261. + rmi4_data->report_enable |= (RPT_WX | RPT_WY);
  21262. +#endif
  21263. +
  21264. + retval = synaptics_rmi4_f12_set_enables(rmi4_data,
  21265. + fhandler->full_addr.ctrl_base + ctrl_28_offset);
  21266. + if (retval < 0)
  21267. + goto exit;
  21268. +
  21269. + if (query_5->ctrl8_is_present) {
  21270. + rmi4_data->wedge_sensor = false;
  21271. +
  21272. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21273. + fhandler->full_addr.ctrl_base + ctrl_8_offset,
  21274. + ctrl_8->data,
  21275. + sizeof(ctrl_8->data));
  21276. + if (retval < 0)
  21277. + goto exit;
  21278. +
  21279. + /* Maximum x and y */
  21280. + rmi4_data->sensor_max_x =
  21281. + ((unsigned int)ctrl_8->max_x_coord_lsb << 0) |
  21282. + ((unsigned int)ctrl_8->max_x_coord_msb << 8);
  21283. + rmi4_data->sensor_max_y =
  21284. + ((unsigned int)ctrl_8->max_y_coord_lsb << 0) |
  21285. + ((unsigned int)ctrl_8->max_y_coord_msb << 8);
  21286. +
  21287. + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH;
  21288. + } else {
  21289. + rmi4_data->wedge_sensor = true;
  21290. +
  21291. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21292. + fhandler->full_addr.ctrl_base + ctrl_31_offset,
  21293. + ctrl_31->data,
  21294. + sizeof(ctrl_31->data));
  21295. + if (retval < 0)
  21296. + goto exit;
  21297. +
  21298. + /* Maximum x and y */
  21299. + rmi4_data->sensor_max_x =
  21300. + ((unsigned int)ctrl_31->max_x_coord_lsb << 0) |
  21301. + ((unsigned int)ctrl_31->max_x_coord_msb << 8);
  21302. + rmi4_data->sensor_max_y =
  21303. + ((unsigned int)ctrl_31->max_y_coord_lsb << 0) |
  21304. + ((unsigned int)ctrl_31->max_y_coord_msb << 8);
  21305. +
  21306. + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH;
  21307. + }
  21308. +
  21309. + dev_dbg(rmi4_data->pdev->dev.parent,
  21310. + "%s: Function %02x max x = %d max y = %d\n",
  21311. + __func__, fhandler->fn_number,
  21312. + rmi4_data->sensor_max_x,
  21313. + rmi4_data->sensor_max_y);
  21314. +
  21315. + if (bdata->swap_axes) {
  21316. + temp = rmi4_data->sensor_max_x;
  21317. + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y;
  21318. + rmi4_data->sensor_max_y = temp;
  21319. + }
  21320. +
  21321. + rmi4_data->f12_wakeup_gesture = query_5->ctrl27_is_present;
  21322. + if (rmi4_data->f12_wakeup_gesture) {
  21323. + extra_data->ctrl20_offset = ctrl_20_offset;
  21324. + extra_data->data4_offset = query_8->data0_is_present +
  21325. + query_8->data1_is_present +
  21326. + query_8->data2_is_present +
  21327. + query_8->data3_is_present;
  21328. + }
  21329. +
  21330. + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
  21331. +
  21332. + extra_data->ctrl26_offset = ctrl_26_offset;
  21333. + extra_data->ctrl27_offset = ctrl_27_offset;
  21334. +
  21335. + /* Allocate memory for finger data storage space */
  21336. + fhandler->data_size = num_of_fingers * size_of_2d_data;
  21337. + fhandler->data = kmalloc(fhandler->data_size, GFP_KERNEL);
  21338. + if (!fhandler->data) {
  21339. + dev_err(rmi4_data->pdev->dev.parent,
  21340. + "%s: Failed to alloc mem for fhandler->data\n",
  21341. + __func__);
  21342. + retval = -ENOMEM;
  21343. + goto exit;
  21344. + }
  21345. +
  21346. +exit:
  21347. + kfree(query_5);
  21348. + kfree(query_8);
  21349. + kfree(ctrl_8);
  21350. + kfree(ctrl_23);
  21351. + kfree(ctrl_31);
  21352. + kfree(ctrl_58);
  21353. +
  21354. + return retval;
  21355. +}
  21356. +
  21357. +static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data,
  21358. + struct synaptics_rmi4_fn *fhandler)
  21359. +{
  21360. + int retval;
  21361. + struct synaptics_rmi4_f1a_handle *f1a;
  21362. +
  21363. + f1a = kzalloc(sizeof(*f1a), GFP_KERNEL);
  21364. + if (!f1a) {
  21365. + dev_err(rmi4_data->pdev->dev.parent,
  21366. + "%s: Failed to alloc mem for function handle\n",
  21367. + __func__);
  21368. + return -ENOMEM;
  21369. + }
  21370. +
  21371. + fhandler->data = (void *)f1a;
  21372. + fhandler->extra = NULL;
  21373. +
  21374. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21375. + fhandler->full_addr.query_base,
  21376. + f1a->button_query.data,
  21377. + sizeof(f1a->button_query.data));
  21378. + if (retval < 0) {
  21379. + dev_err(rmi4_data->pdev->dev.parent,
  21380. + "%s: Failed to read query registers\n",
  21381. + __func__);
  21382. + return retval;
  21383. + }
  21384. +
  21385. + f1a->max_count = f1a->button_query.max_button_count + 1;
  21386. +
  21387. + f1a->button_control.txrx_map = kzalloc(f1a->max_count * 2, GFP_KERNEL);
  21388. + if (!f1a->button_control.txrx_map) {
  21389. + dev_err(rmi4_data->pdev->dev.parent,
  21390. + "%s: Failed to alloc mem for tx rx mapping\n",
  21391. + __func__);
  21392. + return -ENOMEM;
  21393. + }
  21394. +
  21395. + f1a->button_bitmask_size = (f1a->max_count + 7) / 8;
  21396. +
  21397. + f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size,
  21398. + sizeof(*(f1a->button_data_buffer)), GFP_KERNEL);
  21399. + if (!f1a->button_data_buffer) {
  21400. + dev_err(rmi4_data->pdev->dev.parent,
  21401. + "%s: Failed to alloc mem for data buffer\n",
  21402. + __func__);
  21403. + return -ENOMEM;
  21404. + }
  21405. +
  21406. + f1a->button_map = kcalloc(f1a->max_count,
  21407. + sizeof(*(f1a->button_map)), GFP_KERNEL);
  21408. + if (!f1a->button_map) {
  21409. + dev_err(rmi4_data->pdev->dev.parent,
  21410. + "%s: Failed to alloc mem for button map\n",
  21411. + __func__);
  21412. + return -ENOMEM;
  21413. + }
  21414. +
  21415. + return 0;
  21416. +}
  21417. +
  21418. +static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data,
  21419. + struct synaptics_rmi4_fn *fhandler)
  21420. +{
  21421. + int retval;
  21422. + unsigned char ii;
  21423. + unsigned char offset = 0;
  21424. + struct synaptics_rmi4_f1a_query_4 query_4;
  21425. + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
  21426. + const struct synaptics_dsx_board_data *bdata =
  21427. + rmi4_data->hw_if->board_data;
  21428. +
  21429. + offset = f1a->button_query.has_general_control +
  21430. + f1a->button_query.has_interrupt_enable +
  21431. + f1a->button_query.has_multibutton_select;
  21432. +
  21433. + if (f1a->button_query.has_tx_rx_map) {
  21434. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21435. + fhandler->full_addr.ctrl_base + offset,
  21436. + f1a->button_control.txrx_map,
  21437. + f1a->max_count * 2);
  21438. + if (retval < 0) {
  21439. + dev_err(rmi4_data->pdev->dev.parent,
  21440. + "%s: Failed to read tx rx mapping\n",
  21441. + __func__);
  21442. + return retval;
  21443. + }
  21444. +
  21445. + rmi4_data->button_txrx_mapping = f1a->button_control.txrx_map;
  21446. + }
  21447. +
  21448. + if (f1a->button_query.has_query4) {
  21449. + offset = 2 + f1a->button_query.has_query2 +
  21450. + f1a->button_query.has_query3;
  21451. +
  21452. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21453. + fhandler->full_addr.query_base + offset,
  21454. + query_4.data,
  21455. + sizeof(query_4.data));
  21456. + if (retval < 0) {
  21457. + dev_err(rmi4_data->pdev->dev.parent,
  21458. + "%s: Failed to read button features 4\n",
  21459. + __func__);
  21460. + return retval;
  21461. + }
  21462. +
  21463. + if (query_4.has_ctrl24)
  21464. + rmi4_data->external_afe_buttons = true;
  21465. + else
  21466. + rmi4_data->external_afe_buttons = false;
  21467. + }
  21468. +
  21469. + if (!bdata->cap_button_map) {
  21470. + dev_err(rmi4_data->pdev->dev.parent,
  21471. + "%s: cap_button_map is NULL in board file\n",
  21472. + __func__);
  21473. + return -ENODEV;
  21474. + } else if (!bdata->cap_button_map->map) {
  21475. + dev_err(rmi4_data->pdev->dev.parent,
  21476. + "%s: Button map is missing in board file\n",
  21477. + __func__);
  21478. + return -ENODEV;
  21479. + } else {
  21480. + if (bdata->cap_button_map->nbuttons != f1a->max_count) {
  21481. + f1a->valid_button_count = min(f1a->max_count,
  21482. + bdata->cap_button_map->nbuttons);
  21483. + } else {
  21484. + f1a->valid_button_count = f1a->max_count;
  21485. + }
  21486. +
  21487. + for (ii = 0; ii < f1a->valid_button_count; ii++)
  21488. + f1a->button_map[ii] = bdata->cap_button_map->map[ii];
  21489. + }
  21490. +
  21491. + return 0;
  21492. +}
  21493. +
  21494. +static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler)
  21495. +{
  21496. + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
  21497. +
  21498. + if (f1a) {
  21499. + kfree(f1a->button_control.txrx_map);
  21500. + kfree(f1a->button_data_buffer);
  21501. + kfree(f1a->button_map);
  21502. + kfree(f1a);
  21503. + fhandler->data = NULL;
  21504. + }
  21505. +
  21506. + return;
  21507. +}
  21508. +
  21509. +static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
  21510. + struct synaptics_rmi4_fn *fhandler,
  21511. + struct synaptics_rmi4_fn_desc *fd,
  21512. + unsigned int intr_count)
  21513. +{
  21514. + int retval;
  21515. +
  21516. + fhandler->fn_number = fd->fn_number;
  21517. + fhandler->num_of_data_sources = fd->intr_src_count;
  21518. +
  21519. + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
  21520. +
  21521. + retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler);
  21522. + if (retval < 0)
  21523. + goto error_exit;
  21524. +
  21525. + retval = synaptics_rmi4_f1a_button_map(rmi4_data, fhandler);
  21526. + if (retval < 0)
  21527. + goto error_exit;
  21528. +
  21529. + rmi4_data->button_0d_enabled = 1;
  21530. +
  21531. + return 0;
  21532. +
  21533. +error_exit:
  21534. + synaptics_rmi4_f1a_kfree(fhandler);
  21535. +
  21536. + return retval;
  21537. +}
  21538. +
  21539. +static void synaptics_rmi4_empty_fn_list(struct synaptics_rmi4_data *rmi4_data)
  21540. +{
  21541. + struct synaptics_rmi4_fn *fhandler;
  21542. + struct synaptics_rmi4_fn *fhandler_temp;
  21543. + struct synaptics_rmi4_device_info *rmi;
  21544. +
  21545. + rmi = &(rmi4_data->rmi4_mod_info);
  21546. +
  21547. + if (!list_empty(&rmi->support_fn_list)) {
  21548. + list_for_each_entry_safe(fhandler,
  21549. + fhandler_temp,
  21550. + &rmi->support_fn_list,
  21551. + link) {
  21552. + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
  21553. + synaptics_rmi4_f1a_kfree(fhandler);
  21554. + } else {
  21555. + kfree(fhandler->extra);
  21556. + kfree(fhandler->data);
  21557. + }
  21558. + list_del(&fhandler->link);
  21559. + kfree(fhandler);
  21560. + }
  21561. + }
  21562. + INIT_LIST_HEAD(&rmi->support_fn_list);
  21563. +
  21564. + return;
  21565. +}
  21566. +
  21567. +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data,
  21568. + bool *was_in_bl_mode)
  21569. +{
  21570. + int retval;
  21571. + int timeout = CHECK_STATUS_TIMEOUT_MS;
  21572. + struct synaptics_rmi4_f01_device_status status;
  21573. +
  21574. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21575. + rmi4_data->f01_data_base_addr,
  21576. + status.data,
  21577. + sizeof(status.data));
  21578. + if (retval < 0)
  21579. + return retval;
  21580. +
  21581. + while (status.status_code == STATUS_CRC_IN_PROGRESS) {
  21582. + if (timeout > 0)
  21583. + msleep(20);
  21584. + else
  21585. + return -EINVAL;
  21586. +
  21587. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21588. + rmi4_data->f01_data_base_addr,
  21589. + status.data,
  21590. + sizeof(status.data));
  21591. + if (retval < 0)
  21592. + return retval;
  21593. +
  21594. + timeout -= 20;
  21595. + }
  21596. +
  21597. + if (timeout != CHECK_STATUS_TIMEOUT_MS)
  21598. + *was_in_bl_mode = true;
  21599. +
  21600. + if (status.flash_prog == 1) {
  21601. + rmi4_data->flash_prog_mode = true;
  21602. + pr_notice("%s: In flash prog mode, status = 0x%02x\n",
  21603. + __func__,
  21604. + status.status_code);
  21605. + } else {
  21606. + rmi4_data->flash_prog_mode = false;
  21607. + }
  21608. +
  21609. + return 0;
  21610. +}
  21611. +
  21612. +static void synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data)
  21613. +{
  21614. + int retval;
  21615. + unsigned char device_ctrl;
  21616. +
  21617. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21618. + rmi4_data->f01_ctrl_base_addr,
  21619. + &device_ctrl,
  21620. + sizeof(device_ctrl));
  21621. + if (retval < 0) {
  21622. + dev_err(rmi4_data->pdev->dev.parent,
  21623. + "%s: Failed to set configured\n",
  21624. + __func__);
  21625. + return;
  21626. + }
  21627. +
  21628. + rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON;
  21629. + device_ctrl |= CONFIGURED;
  21630. +
  21631. + retval = synaptics_rmi4_reg_write(rmi4_data,
  21632. + rmi4_data->f01_ctrl_base_addr,
  21633. + &device_ctrl,
  21634. + sizeof(device_ctrl));
  21635. + if (retval < 0) {
  21636. + dev_err(rmi4_data->pdev->dev.parent,
  21637. + "%s: Failed to set configured\n",
  21638. + __func__);
  21639. + }
  21640. +
  21641. + return;
  21642. +}
  21643. +
  21644. +static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
  21645. + struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
  21646. +{
  21647. + *fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL);
  21648. + if (!(*fhandler))
  21649. + return -ENOMEM;
  21650. +
  21651. + (*fhandler)->full_addr.data_base =
  21652. + (rmi_fd->data_base_addr |
  21653. + (page_number << 8));
  21654. + (*fhandler)->full_addr.ctrl_base =
  21655. + (rmi_fd->ctrl_base_addr |
  21656. + (page_number << 8));
  21657. + (*fhandler)->full_addr.cmd_base =
  21658. + (rmi_fd->cmd_base_addr |
  21659. + (page_number << 8));
  21660. + (*fhandler)->full_addr.query_base =
  21661. + (rmi_fd->query_base_addr |
  21662. + (page_number << 8));
  21663. +
  21664. + return 0;
  21665. +}
  21666. +
  21667. +static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
  21668. +{
  21669. + int retval;
  21670. + unsigned char page_number;
  21671. + unsigned char intr_count;
  21672. + unsigned char f01_query[F01_STD_QUERY_LEN];
  21673. + unsigned short pdt_entry_addr;
  21674. + bool f01found;
  21675. + bool f35found;
  21676. + bool was_in_bl_mode;
  21677. + struct synaptics_rmi4_fn_desc rmi_fd;
  21678. + struct synaptics_rmi4_fn *fhandler;
  21679. + struct synaptics_rmi4_device_info *rmi;
  21680. +
  21681. + rmi = &(rmi4_data->rmi4_mod_info);
  21682. +
  21683. +rescan_pdt:
  21684. + f01found = false;
  21685. + f35found = false;
  21686. + was_in_bl_mode = false;
  21687. + intr_count = 0;
  21688. + INIT_LIST_HEAD(&rmi->support_fn_list);
  21689. +
  21690. + /* Scan the page description tables of the pages to service */
  21691. + for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
  21692. + for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
  21693. + pdt_entry_addr -= PDT_ENTRY_SIZE) {
  21694. + pdt_entry_addr |= (page_number << 8);
  21695. +
  21696. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21697. + pdt_entry_addr,
  21698. + (unsigned char *)&rmi_fd,
  21699. + sizeof(rmi_fd));
  21700. + if (retval < 0)
  21701. + return retval;
  21702. +
  21703. + pdt_entry_addr &= ~(MASK_8BIT << 8);
  21704. +
  21705. + fhandler = NULL;
  21706. +
  21707. + if (rmi_fd.fn_number == 0) {
  21708. + dev_dbg(rmi4_data->pdev->dev.parent,
  21709. + "%s: Reached end of PDT\n",
  21710. + __func__);
  21711. + break;
  21712. + }
  21713. +
  21714. + dev_dbg(rmi4_data->pdev->dev.parent,
  21715. + "%s: F%02x found (page %d)\n",
  21716. + __func__, rmi_fd.fn_number,
  21717. + page_number);
  21718. +
  21719. + switch (rmi_fd.fn_number) {
  21720. + case SYNAPTICS_RMI4_F01:
  21721. + if (rmi_fd.intr_src_count == 0)
  21722. + break;
  21723. +
  21724. + f01found = true;
  21725. +
  21726. + retval = synaptics_rmi4_alloc_fh(&fhandler,
  21727. + &rmi_fd, page_number);
  21728. + if (retval < 0) {
  21729. + dev_err(rmi4_data->pdev->dev.parent,
  21730. + "%s: Failed to alloc for F%d\n",
  21731. + __func__,
  21732. + rmi_fd.fn_number);
  21733. + return retval;
  21734. + }
  21735. +
  21736. + retval = synaptics_rmi4_f01_init(rmi4_data,
  21737. + fhandler, &rmi_fd, intr_count);
  21738. + if (retval < 0)
  21739. + return retval;
  21740. +
  21741. + retval = synaptics_rmi4_check_status(rmi4_data,
  21742. + &was_in_bl_mode);
  21743. + if (retval < 0) {
  21744. + dev_err(rmi4_data->pdev->dev.parent,
  21745. + "%s: Failed to check status\n",
  21746. + __func__);
  21747. + return retval;
  21748. + }
  21749. +
  21750. + if (was_in_bl_mode) {
  21751. + kfree(fhandler);
  21752. + fhandler = NULL;
  21753. + goto rescan_pdt;
  21754. + }
  21755. +
  21756. + if (rmi4_data->flash_prog_mode)
  21757. + goto flash_prog_mode;
  21758. +
  21759. + break;
  21760. + case SYNAPTICS_RMI4_F11:
  21761. + if (rmi_fd.intr_src_count == 0)
  21762. + break;
  21763. +
  21764. + retval = synaptics_rmi4_alloc_fh(&fhandler,
  21765. + &rmi_fd, page_number);
  21766. + if (retval < 0) {
  21767. + dev_err(rmi4_data->pdev->dev.parent,
  21768. + "%s: Failed to alloc for F%d\n",
  21769. + __func__,
  21770. + rmi_fd.fn_number);
  21771. + return retval;
  21772. + }
  21773. +
  21774. + retval = synaptics_rmi4_f11_init(rmi4_data,
  21775. + fhandler, &rmi_fd, intr_count);
  21776. + if (retval < 0)
  21777. + return retval;
  21778. + break;
  21779. + case SYNAPTICS_RMI4_F12:
  21780. + if (rmi_fd.intr_src_count == 0)
  21781. + break;
  21782. +
  21783. + retval = synaptics_rmi4_alloc_fh(&fhandler,
  21784. + &rmi_fd, page_number);
  21785. + if (retval < 0) {
  21786. + dev_err(rmi4_data->pdev->dev.parent,
  21787. + "%s: Failed to alloc for F%d\n",
  21788. + __func__,
  21789. + rmi_fd.fn_number);
  21790. + return retval;
  21791. + }
  21792. +
  21793. + retval = synaptics_rmi4_f12_init(rmi4_data,
  21794. + fhandler, &rmi_fd, intr_count);
  21795. + if (retval < 0)
  21796. + return retval;
  21797. + break;
  21798. + case SYNAPTICS_RMI4_F1A:
  21799. + if (rmi_fd.intr_src_count == 0)
  21800. + break;
  21801. +
  21802. + retval = synaptics_rmi4_alloc_fh(&fhandler,
  21803. + &rmi_fd, page_number);
  21804. + if (retval < 0) {
  21805. + dev_err(rmi4_data->pdev->dev.parent,
  21806. + "%s: Failed to alloc for F%d\n",
  21807. + __func__,
  21808. + rmi_fd.fn_number);
  21809. + return retval;
  21810. + }
  21811. +
  21812. + retval = synaptics_rmi4_f1a_init(rmi4_data,
  21813. + fhandler, &rmi_fd, intr_count);
  21814. + if (retval < 0) {
  21815. +#ifdef IGNORE_FN_INIT_FAILURE
  21816. + kfree(fhandler);
  21817. + fhandler = NULL;
  21818. +#else
  21819. + return retval;
  21820. +#endif
  21821. + }
  21822. + break;
  21823. + case SYNAPTICS_RMI4_F35:
  21824. + f35found = true;
  21825. + break;
  21826. +#ifdef F51_DISCRETE_FORCE
  21827. + case SYNAPTICS_RMI4_F51:
  21828. + rmi4_data->f51_query_base_addr =
  21829. + rmi_fd.query_base_addr |
  21830. + (page_number << 8);
  21831. + break;
  21832. +#endif
  21833. + }
  21834. +
  21835. + /* Accumulate the interrupt count */
  21836. + intr_count += rmi_fd.intr_src_count;
  21837. +
  21838. + if (fhandler && rmi_fd.intr_src_count) {
  21839. + list_add_tail(&fhandler->link,
  21840. + &rmi->support_fn_list);
  21841. + }
  21842. + }
  21843. + }
  21844. +
  21845. + if (!f01found) {
  21846. + dev_err(rmi4_data->pdev->dev.parent,
  21847. + "%s: Failed to find F01\n",
  21848. + __func__);
  21849. + if (!f35found) {
  21850. + dev_err(rmi4_data->pdev->dev.parent,
  21851. + "%s: Failed to find F35\n",
  21852. + __func__);
  21853. + return -EINVAL;
  21854. + } else {
  21855. + pr_notice("%s: In microbootloader mode\n",
  21856. + __func__);
  21857. + return 0;
  21858. + }
  21859. + }
  21860. +
  21861. +flash_prog_mode:
  21862. + rmi4_data->num_of_intr_regs = (intr_count + 7) / 8;
  21863. + dev_dbg(rmi4_data->pdev->dev.parent,
  21864. + "%s: Number of interrupt registers = %d\n",
  21865. + __func__, rmi4_data->num_of_intr_regs);
  21866. +
  21867. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21868. + rmi4_data->f01_query_base_addr,
  21869. + f01_query,
  21870. + sizeof(f01_query));
  21871. + if (retval < 0)
  21872. + return retval;
  21873. +
  21874. + /* RMI Version 4.0 currently supported */
  21875. + rmi->version_major = 4;
  21876. + rmi->version_minor = 0;
  21877. +
  21878. + rmi->manufacturer_id = f01_query[0];
  21879. + rmi->product_props = f01_query[1];
  21880. + rmi->product_info[0] = f01_query[2];
  21881. + rmi->product_info[1] = f01_query[3];
  21882. + retval = secure_memcpy(rmi->product_id_string,
  21883. + sizeof(rmi->product_id_string),
  21884. + &f01_query[11],
  21885. + sizeof(f01_query) - 11,
  21886. + PRODUCT_ID_SIZE);
  21887. + if (retval < 0) {
  21888. + dev_err(rmi4_data->pdev->dev.parent,
  21889. + "%s: Failed to copy product ID string\n",
  21890. + __func__);
  21891. + }
  21892. +
  21893. + if (rmi->manufacturer_id != 1) {
  21894. + dev_err(rmi4_data->pdev->dev.parent,
  21895. + "%s: Non-Synaptics device found, manufacturer ID = %d\n",
  21896. + __func__, rmi->manufacturer_id);
  21897. + }
  21898. +
  21899. + retval = synaptics_rmi4_reg_read(rmi4_data,
  21900. + rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
  21901. + rmi->build_id,
  21902. + sizeof(rmi->build_id));
  21903. + if (retval < 0)
  21904. + return retval;
  21905. +
  21906. + rmi4_data->firmware_id = (unsigned int)rmi->build_id[0] +
  21907. + (unsigned int)rmi->build_id[1] * 0x100 +
  21908. + (unsigned int)rmi->build_id[2] * 0x10000;
  21909. +
  21910. + memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask));
  21911. +
  21912. + /*
  21913. + * Map out the interrupt bit masks for the interrupt sources
  21914. + * from the registered function handlers.
  21915. + */
  21916. + if (!list_empty(&rmi->support_fn_list)) {
  21917. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  21918. + if (fhandler->num_of_data_sources) {
  21919. + rmi4_data->intr_mask[fhandler->intr_reg_num] |=
  21920. + fhandler->intr_mask;
  21921. + }
  21922. + }
  21923. + }
  21924. +
  21925. + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture)
  21926. + rmi4_data->enable_wakeup_gesture = WAKEUP_GESTURE;
  21927. + else
  21928. + rmi4_data->enable_wakeup_gesture = false;
  21929. +
  21930. + synaptics_rmi4_set_configured(rmi4_data);
  21931. +
  21932. + return 0;
  21933. +}
  21934. +
  21935. +static int synaptics_rmi4_gpio_setup(int gpio, bool config, int dir, int state, const char *label)
  21936. +{
  21937. + int retval = 0;
  21938. +
  21939. + if (config) {
  21940. + retval = gpio_request(gpio, label);
  21941. + if (retval) {
  21942. + pr_err("%s: Failed to get gpio %d (code: %d)",
  21943. + __func__, gpio, retval);
  21944. + return retval;
  21945. + }
  21946. +
  21947. + if (dir == 0)
  21948. + retval = gpio_direction_input(gpio);
  21949. + else
  21950. + retval = gpio_direction_output(gpio, state);
  21951. + if (retval) {
  21952. + pr_err("%s: Failed to set gpio %d direction",
  21953. + __func__, gpio);
  21954. + return retval;
  21955. + }
  21956. + } else {
  21957. + gpio_free(gpio);
  21958. + }
  21959. +
  21960. + return retval;
  21961. +}
  21962. +
  21963. +static int synaptics_rmi4_pinctrl_init(struct synaptics_rmi4_data *rmi4_data)
  21964. +{
  21965. + int retval;
  21966. +
  21967. + /* Get pinctrl if target uses pinctrl */
  21968. + rmi4_data->ts_pinctrl = devm_pinctrl_get((rmi4_data->pdev->dev.parent));
  21969. + if (IS_ERR_OR_NULL(rmi4_data->ts_pinctrl)) {
  21970. + retval = PTR_ERR(rmi4_data->ts_pinctrl);
  21971. + dev_dbg(rmi4_data->pdev->dev.parent,
  21972. + "Target does not use pinctrl %d\n", retval);
  21973. + goto err_pinctrl_get;
  21974. + }
  21975. +
  21976. + rmi4_data->pinctrl_state_active
  21977. + = pinctrl_lookup_state(rmi4_data->ts_pinctrl, PINCTRL_STATE_ACTIVE);
  21978. + if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_active)) {
  21979. + retval = PTR_ERR(rmi4_data->pinctrl_state_active);
  21980. + dev_err(rmi4_data->pdev->dev.parent,
  21981. + "Can not lookup %s pinstate %d\n",
  21982. + PINCTRL_STATE_ACTIVE, retval);
  21983. + goto err_pinctrl_lookup;
  21984. + }
  21985. +
  21986. + rmi4_data->pinctrl_state_suspend
  21987. + = pinctrl_lookup_state(rmi4_data->ts_pinctrl, PINCTRL_STATE_SUSPEND);
  21988. + if (IS_ERR_OR_NULL(rmi4_data->pinctrl_state_suspend)) {
  21989. + retval = PTR_ERR(rmi4_data->pinctrl_state_suspend);
  21990. + dev_dbg(rmi4_data->pdev->dev.parent,
  21991. + "Can not lookup %s pinstate %d\n",
  21992. + PINCTRL_STATE_SUSPEND, retval);
  21993. + goto err_pinctrl_lookup;
  21994. + }
  21995. +
  21996. + return 0;
  21997. +
  21998. +err_pinctrl_lookup:
  21999. + devm_pinctrl_put(rmi4_data->ts_pinctrl);
  22000. +err_pinctrl_get:
  22001. + rmi4_data->ts_pinctrl = NULL;
  22002. + return retval;
  22003. +}
  22004. +
  22005. +static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data)
  22006. +{
  22007. + unsigned char ii;
  22008. + struct synaptics_rmi4_f1a_handle *f1a;
  22009. + struct synaptics_rmi4_fn *fhandler;
  22010. + struct synaptics_rmi4_device_info *rmi;
  22011. +
  22012. + rmi = &(rmi4_data->rmi4_mod_info);
  22013. +
  22014. + input_set_abs_params(rmi4_data->input_dev,
  22015. + ABS_MT_POSITION_X, 0,
  22016. + rmi4_data->sensor_max_x, 0, 0);
  22017. + input_set_abs_params(rmi4_data->input_dev,
  22018. + ABS_MT_POSITION_Y, 0,
  22019. + rmi4_data->sensor_max_y, 0, 0);
  22020. +#ifdef REPORT_2D_W
  22021. + input_set_abs_params(rmi4_data->input_dev,
  22022. + ABS_MT_TOUCH_MAJOR, 0,
  22023. + rmi4_data->max_touch_width, 0, 0);
  22024. + input_set_abs_params(rmi4_data->input_dev,
  22025. + ABS_MT_TOUCH_MINOR, 0,
  22026. + rmi4_data->max_touch_width, 0, 0);
  22027. +#endif
  22028. +
  22029. +#ifdef REPORT_2D_PRESSURE
  22030. + if (rmi4_data->report_pressure) {
  22031. + input_set_abs_params(rmi4_data->input_dev,
  22032. + ABS_MT_PRESSURE, rmi4_data->force_min,
  22033. + rmi4_data->force_max, 0, 0);
  22034. + }
  22035. +#elif defined(F51_DISCRETE_FORCE)
  22036. + input_set_abs_params(rmi4_data->input_dev,
  22037. + ABS_MT_PRESSURE, 0,
  22038. + FORCE_LEVEL_MAX, 0, 0);
  22039. +#endif
  22040. +
  22041. +#ifdef TYPE_B_PROTOCOL
  22042. +#ifdef KERNEL_ABOVE_3_6
  22043. + input_mt_init_slots(rmi4_data->input_dev,
  22044. + rmi4_data->num_of_fingers, INPUT_MT_DIRECT);
  22045. +#else
  22046. + input_mt_init_slots(rmi4_data->input_dev,
  22047. + rmi4_data->num_of_fingers);
  22048. +#endif
  22049. +#endif
  22050. +
  22051. + f1a = NULL;
  22052. + if (!list_empty(&rmi->support_fn_list)) {
  22053. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  22054. + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
  22055. + f1a = fhandler->data;
  22056. + }
  22057. + }
  22058. +
  22059. + if (f1a) {
  22060. + for (ii = 0; ii < f1a->valid_button_count; ii++) {
  22061. + set_bit(f1a->button_map[ii],
  22062. + rmi4_data->input_dev->keybit);
  22063. + input_set_capability(rmi4_data->input_dev,
  22064. + EV_KEY, f1a->button_map[ii]);
  22065. + }
  22066. + }
  22067. +
  22068. + if (vir_button_map->nbuttons) {
  22069. + for (ii = 0; ii < vir_button_map->nbuttons; ii++) {
  22070. + set_bit(vir_button_map->map[ii * 5],
  22071. + rmi4_data->input_dev->keybit);
  22072. + input_set_capability(rmi4_data->input_dev,
  22073. + EV_KEY, vir_button_map->map[ii * 5]);
  22074. + }
  22075. + }
  22076. +
  22077. + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) {
  22078. + set_bit(KEY_WAKEUP, rmi4_data->input_dev->keybit);
  22079. + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP);
  22080. + }
  22081. +
  22082. + return;
  22083. +}
  22084. +
  22085. +/* Re-configure touch settings when wakeup gesture mode is switched in suspend */
  22086. +static void synaptics_rmi4_wakeup_reconfigure(struct synaptics_rmi4_data *rmi4_data,
  22087. + bool enable)
  22088. +{
  22089. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  22090. +
  22091. + synaptics_rmi4_sleep_enable(rmi4_data, !enable);
  22092. +
  22093. + if (enable) {
  22094. + mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, true);
  22095. + mdss_reset_ctrl(rmi4_data->hw_if->board_data, true);
  22096. + }
  22097. +
  22098. + synaptics_rmi4_wakeup_gesture(rmi4_data, enable);
  22099. +
  22100. + if (!enable) {
  22101. + mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, false);
  22102. + mdss_reset_ctrl(rmi4_data->hw_if->board_data, false);
  22103. + }
  22104. +
  22105. + synaptics_rmi4_irq_enable(rmi4_data, enable, false);
  22106. +
  22107. + mutex_lock(&exp_data.mutex);
  22108. + if (!list_empty(&exp_data.list)) {
  22109. + list_for_each_entry(exp_fhandler, &exp_data.list, link) {
  22110. + if (enable) {
  22111. + if (exp_fhandler->exp_fn->resume != NULL)
  22112. + exp_fhandler->exp_fn->resume(rmi4_data);
  22113. + } else {
  22114. + if (exp_fhandler->exp_fn->suspend != NULL)
  22115. + exp_fhandler->exp_fn->suspend(rmi4_data);
  22116. + }
  22117. + }
  22118. + }
  22119. + mutex_unlock(&exp_data.mutex);
  22120. +}
  22121. +
  22122. +static void synaptics_key_ctrl(struct synaptics_rmi4_data *rmi4_data, bool enable)
  22123. +{
  22124. + int retval;
  22125. + unsigned char ii;
  22126. + unsigned char intr_enable;
  22127. + struct synaptics_rmi4_fn *fhandler;
  22128. + struct synaptics_rmi4_device_info *rmi;
  22129. +
  22130. + rmi = &(rmi4_data->rmi4_mod_info);
  22131. +
  22132. + if (list_empty(&rmi->support_fn_list))
  22133. + return ;
  22134. +
  22135. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  22136. + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
  22137. + ii = fhandler->intr_reg_num;
  22138. +
  22139. + retval = synaptics_rmi4_reg_read(rmi4_data,
  22140. + rmi4_data->f01_ctrl_base_addr + 1 + ii,
  22141. + &intr_enable,
  22142. + sizeof(intr_enable));
  22143. + if (retval < 0)
  22144. + return ;
  22145. +
  22146. + if (enable == true)
  22147. + intr_enable |= fhandler->intr_mask;
  22148. + else
  22149. + intr_enable &= ~fhandler->intr_mask;
  22150. +
  22151. + retval = synaptics_rmi4_reg_write(rmi4_data,
  22152. + rmi4_data->f01_ctrl_base_addr + 1 + ii,
  22153. + &intr_enable,
  22154. + sizeof(intr_enable));
  22155. + if (retval < 0)
  22156. + return ;
  22157. + }
  22158. + }
  22159. +
  22160. + return ;
  22161. +}
  22162. +
  22163. +static void cover_mode_set(struct synaptics_rmi4_data *rmi4_data, int enable)
  22164. +{
  22165. + struct synaptics_rmi4_f12_extra_data *extra_data;
  22166. + struct synaptics_rmi4_fn *fhandler;
  22167. + struct synaptics_rmi4_device_info *rmi;
  22168. + int retval;
  22169. + unsigned char ctrl26_value;
  22170. +
  22171. + mutex_lock(&rmi4_data->rmi4_cover_mutex);
  22172. +
  22173. + if (rmi4_data->suspend)
  22174. + goto end;
  22175. +
  22176. + rmi = &(rmi4_data->rmi4_mod_info);
  22177. +
  22178. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  22179. + if (fhandler->fn_number == SYNAPTICS_RMI4_F12)
  22180. + break;
  22181. + }
  22182. +
  22183. + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
  22184. +
  22185. + if (enable == 0) {
  22186. + retval = synaptics_rmi4_reg_read(rmi4_data,
  22187. + fhandler->full_addr.ctrl_base + extra_data->ctrl26_offset,
  22188. + &ctrl26_value,
  22189. + 1);
  22190. + if (retval < 0) {
  22191. + dev_err(rmi4_data->pdev->dev.parent,
  22192. + "%s: Failed to read ctrl26 reg\n",
  22193. + __func__);
  22194. + goto end;
  22195. + }
  22196. +
  22197. + ctrl26_value &= 0xfc;
  22198. +
  22199. + retval = synaptics_rmi4_reg_write(rmi4_data,
  22200. + fhandler->full_addr.ctrl_base + extra_data->ctrl26_offset,
  22201. + &ctrl26_value,
  22202. + 1);
  22203. + if (retval < 0) {
  22204. + dev_err(rmi4_data->pdev->dev.parent,
  22205. + "%s: Failed to close cover mode\n",
  22206. + __func__);
  22207. + goto end;
  22208. + }
  22209. +
  22210. + synaptics_key_ctrl(rmi4_data, true);
  22211. + } else {
  22212. + retval = synaptics_rmi4_reg_read(rmi4_data,
  22213. + fhandler->full_addr.ctrl_base + extra_data->ctrl26_offset,
  22214. + &ctrl26_value,
  22215. + 1);
  22216. + if (retval < 0) {
  22217. + dev_err(rmi4_data->pdev->dev.parent,
  22218. + "%s: Failed to read ctrl26 reg\n",
  22219. + __func__);
  22220. + goto end;
  22221. + }
  22222. +
  22223. + ctrl26_value |= 0x03;
  22224. + retval = synaptics_rmi4_reg_write(rmi4_data,
  22225. + fhandler->full_addr.ctrl_base + extra_data->ctrl26_offset,
  22226. + &ctrl26_value,
  22227. + 1);
  22228. + if (retval < 0) {
  22229. + dev_err(rmi4_data->pdev->dev.parent,
  22230. + "%s: Failed to change cover mode\n",
  22231. + __func__);
  22232. + goto end;
  22233. + }
  22234. +
  22235. + synaptics_key_ctrl(rmi4_data, false);
  22236. + };
  22237. +end:
  22238. + mutex_unlock(&rmi4_data->rmi4_cover_mutex);
  22239. +}
  22240. +
  22241. +static void synaptics_rmi4_switch_mode_work(struct work_struct *work)
  22242. +{
  22243. + struct synaptics_rmi4_mode_switch *ms = container_of(work, struct synaptics_rmi4_mode_switch, switch_mode_work);
  22244. + struct synaptics_rmi4_data *rmi4_data = ms->data;
  22245. + const struct synaptics_dsx_board_data *bdata = rmi4_data->hw_if->board_data;
  22246. + unsigned char value = ms->mode;
  22247. +
  22248. + if (value >= INPUT_EVENT_WAKUP_MODE_OFF && value <= INPUT_EVENT_WAKUP_MODE_ON) {
  22249. + if (bdata->cut_off_power) {
  22250. + dev_err(rmi4_data->pdev->dev.parent,
  22251. + "%s: Unable to switch wakeup gesture mode\n", __func__);
  22252. + return;
  22253. + }
  22254. +
  22255. + rmi4_data->enable_wakeup_gesture = value - INPUT_EVENT_WAKUP_MODE_OFF;
  22256. + } else if (value >= INPUT_EVENT_COVER_MODE_OFF && value <= INPUT_EVENT_COVER_MODE_ON) {
  22257. + rmi4_data->enable_cover_mode = value - INPUT_EVENT_COVER_MODE_OFF;
  22258. + cover_mode_set(rmi4_data, rmi4_data->enable_cover_mode);
  22259. + } else {
  22260. + dev_err(rmi4_data->pdev->dev.parent,
  22261. + "Does not support touch mode %d\n", value);
  22262. + }
  22263. +
  22264. + if (ms != NULL) {
  22265. + kfree(ms);
  22266. + ms = NULL;
  22267. + }
  22268. +}
  22269. +
  22270. +static int synaptics_rmi4_input_event(struct input_dev *dev,
  22271. + unsigned int type, unsigned int code, int value)
  22272. +{
  22273. + struct synaptics_rmi4_data *rmi4_data = input_get_drvdata(dev);
  22274. + struct synaptics_rmi4_mode_switch *ms;
  22275. +
  22276. + if (type == EV_SYN && code == SYN_CONFIG) {
  22277. + dev_info(rmi4_data->pdev->dev.parent,
  22278. + "Set input event value = %d\n", value);
  22279. +
  22280. + if (value >= INPUT_EVENT_START && value <= INPUT_EVENT_END) {
  22281. + ms = (struct synaptics_rmi4_mode_switch *)kmalloc(sizeof(struct synaptics_rmi4_mode_switch),
  22282. + GFP_ATOMIC);
  22283. + if (ms != NULL) {
  22284. + ms->data = rmi4_data;
  22285. + ms->mode = (unsigned char)value;
  22286. + INIT_WORK(&ms->switch_mode_work, synaptics_rmi4_switch_mode_work);
  22287. + schedule_work(&ms->switch_mode_work);
  22288. + } else {
  22289. + dev_err(rmi4_data->pdev->dev.parent,
  22290. + "Failed in allocating memory for switching mode!\n");
  22291. + return -ENOMEM;
  22292. + }
  22293. + } else {
  22294. + dev_err(rmi4_data->pdev->dev.parent,
  22295. + "Invalid event value %d\n", value);
  22296. + return -EINVAL;
  22297. + }
  22298. + }
  22299. +
  22300. + return 0;
  22301. +}
  22302. +
  22303. +static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data)
  22304. +{
  22305. + int retval;
  22306. + const struct synaptics_dsx_board_data *bdata =
  22307. + rmi4_data->hw_if->board_data;
  22308. +
  22309. + rmi4_data->input_dev = input_allocate_device();
  22310. + if (rmi4_data->input_dev == NULL) {
  22311. + dev_err(rmi4_data->pdev->dev.parent,
  22312. + "%s: Failed to allocate input device\n",
  22313. + __func__);
  22314. + retval = -ENOMEM;
  22315. + goto err_input_device;
  22316. + }
  22317. +
  22318. + retval = synaptics_rmi4_query_device(rmi4_data);
  22319. + if (retval < 0) {
  22320. + dev_err(rmi4_data->pdev->dev.parent,
  22321. + "%s: Failed to query device\n",
  22322. + __func__);
  22323. + goto err_query_device;
  22324. + }
  22325. +
  22326. + rmi4_data->input_dev->name = PLATFORM_DRIVER_NAME;
  22327. + rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
  22328. + rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
  22329. + rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION;
  22330. + rmi4_data->input_dev->dev.parent = rmi4_data->pdev->dev.parent;
  22331. + rmi4_data->input_dev->event = synaptics_rmi4_input_event;
  22332. + input_set_drvdata(rmi4_data->input_dev, rmi4_data);
  22333. +
  22334. + set_bit(EV_SYN, rmi4_data->input_dev->evbit);
  22335. + set_bit(EV_KEY, rmi4_data->input_dev->evbit);
  22336. + set_bit(EV_ABS, rmi4_data->input_dev->evbit);
  22337. + set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit);
  22338. + set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit);
  22339. +#ifdef INPUT_PROP_DIRECT
  22340. + set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit);
  22341. +#endif
  22342. +
  22343. + if (bdata->max_y_for_2d >= 0)
  22344. + rmi4_data->sensor_max_y = bdata->max_y_for_2d;
  22345. +
  22346. + synaptics_rmi4_set_params(rmi4_data);
  22347. +
  22348. + retval = input_register_device(rmi4_data->input_dev);
  22349. + if (retval) {
  22350. + dev_err(rmi4_data->pdev->dev.parent,
  22351. + "%s: Failed to register input device\n",
  22352. + __func__);
  22353. + goto err_register_input;
  22354. + }
  22355. +
  22356. + if (!rmi4_data->stylus_enable)
  22357. + return 0;
  22358. +
  22359. + rmi4_data->stylus_dev = input_allocate_device();
  22360. + if (rmi4_data->stylus_dev == NULL) {
  22361. + dev_err(rmi4_data->pdev->dev.parent,
  22362. + "%s: Failed to allocate stylus device\n",
  22363. + __func__);
  22364. + retval = -ENOMEM;
  22365. + goto err_stylus_device;
  22366. + }
  22367. +
  22368. + rmi4_data->stylus_dev->name = STYLUS_DRIVER_NAME;
  22369. + rmi4_data->stylus_dev->phys = STYLUS_PHYS_NAME;
  22370. + rmi4_data->stylus_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
  22371. + rmi4_data->stylus_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION;
  22372. + rmi4_data->stylus_dev->dev.parent = rmi4_data->pdev->dev.parent;
  22373. + input_set_drvdata(rmi4_data->stylus_dev, rmi4_data);
  22374. +
  22375. + set_bit(EV_KEY, rmi4_data->stylus_dev->evbit);
  22376. + set_bit(EV_ABS, rmi4_data->stylus_dev->evbit);
  22377. + set_bit(BTN_TOUCH, rmi4_data->stylus_dev->keybit);
  22378. + set_bit(BTN_TOOL_PEN, rmi4_data->stylus_dev->keybit);
  22379. + if (rmi4_data->eraser_enable)
  22380. + set_bit(BTN_TOOL_RUBBER, rmi4_data->stylus_dev->keybit);
  22381. +#ifdef INPUT_PROP_DIRECT
  22382. + set_bit(INPUT_PROP_DIRECT, rmi4_data->stylus_dev->propbit);
  22383. +#endif
  22384. +
  22385. + input_set_abs_params(rmi4_data->stylus_dev, ABS_X, 0,
  22386. + rmi4_data->sensor_max_x, 0, 0);
  22387. + input_set_abs_params(rmi4_data->stylus_dev, ABS_Y, 0,
  22388. + rmi4_data->sensor_max_y, 0, 0);
  22389. +
  22390. + retval = input_register_device(rmi4_data->stylus_dev);
  22391. + if (retval) {
  22392. + dev_err(rmi4_data->pdev->dev.parent,
  22393. + "%s: Failed to register stylus device\n",
  22394. + __func__);
  22395. + goto err_register_stylus;
  22396. + }
  22397. +
  22398. + return 0;
  22399. +
  22400. +err_register_stylus:
  22401. + rmi4_data->stylus_dev = NULL;
  22402. +
  22403. +err_stylus_device:
  22404. + input_unregister_device(rmi4_data->input_dev);
  22405. + rmi4_data->input_dev = NULL;
  22406. +
  22407. +err_register_input:
  22408. +err_query_device:
  22409. + synaptics_rmi4_empty_fn_list(rmi4_data);
  22410. + input_free_device(rmi4_data->input_dev);
  22411. +
  22412. +err_input_device:
  22413. + return retval;
  22414. +}
  22415. +
  22416. +static int synaptics_rmi4_set_gpio(struct synaptics_rmi4_data *rmi4_data)
  22417. +{
  22418. + int retval;
  22419. + const struct synaptics_dsx_board_data *bdata =
  22420. + rmi4_data->hw_if->board_data;
  22421. +
  22422. + retval = synaptics_rmi4_gpio_setup(
  22423. + bdata->irq_gpio,
  22424. + true, 0, 0, bdata->irq_gpio_name);
  22425. + if (retval < 0) {
  22426. + dev_err(rmi4_data->pdev->dev.parent,
  22427. + "%s: Failed to configure attention GPIO\n",
  22428. + __func__);
  22429. + goto err_gpio_irq;
  22430. + }
  22431. +
  22432. + if (bdata->power_gpio >= 0) {
  22433. + retval = synaptics_rmi4_gpio_setup(
  22434. + bdata->power_gpio,
  22435. + true, 1, !bdata->power_on_state, bdata->power_gpio_name);
  22436. + if (retval < 0) {
  22437. + dev_err(rmi4_data->pdev->dev.parent,
  22438. + "%s: Failed to configure power GPIO\n",
  22439. + __func__);
  22440. + goto err_gpio_power;
  22441. + }
  22442. + }
  22443. +
  22444. + if (bdata->reset_gpio >= 0) {
  22445. + retval = synaptics_rmi4_gpio_setup(
  22446. + bdata->reset_gpio,
  22447. + true, 1, !bdata->reset_on_state, bdata->reset_gpio_name);
  22448. + if (retval < 0) {
  22449. + dev_err(rmi4_data->pdev->dev.parent,
  22450. + "%s: Failed to configure reset GPIO\n",
  22451. + __func__);
  22452. + goto err_gpio_reset;
  22453. + }
  22454. + }
  22455. +
  22456. + if (bdata->power_gpio >= 0) {
  22457. + gpio_set_value(bdata->power_gpio, bdata->power_on_state);
  22458. + msleep(bdata->power_delay_ms);
  22459. + }
  22460. +
  22461. + if (bdata->reset_gpio >= 0) {
  22462. + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
  22463. + msleep(bdata->reset_active_ms);
  22464. + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
  22465. + msleep(bdata->reset_delay_ms);
  22466. + }
  22467. +
  22468. + return 0;
  22469. +
  22470. +err_gpio_reset:
  22471. + if (bdata->power_gpio >= 0)
  22472. + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0, NULL);
  22473. +
  22474. +err_gpio_power:
  22475. + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0, NULL);
  22476. +
  22477. +err_gpio_irq:
  22478. + return retval;
  22479. +}
  22480. +
  22481. +static int synaptics_rmi4_get_reg(struct synaptics_rmi4_data *rmi4_data,
  22482. + bool get)
  22483. +{
  22484. + int retval;
  22485. + const struct synaptics_dsx_board_data *bdata =
  22486. + rmi4_data->hw_if->board_data;
  22487. +
  22488. + if (!get) {
  22489. + retval = 0;
  22490. + goto regulator_put;
  22491. + }
  22492. +
  22493. + if ((bdata->pwr_reg_name != NULL) && (*bdata->pwr_reg_name != 0)) {
  22494. + rmi4_data->pwr_reg = regulator_get(rmi4_data->pdev->dev.parent,
  22495. + bdata->pwr_reg_name);
  22496. + if (IS_ERR(rmi4_data->pwr_reg)) {
  22497. + dev_err(rmi4_data->pdev->dev.parent,
  22498. + "%s: Failed to get power regulator\n",
  22499. + __func__);
  22500. + retval = PTR_ERR(rmi4_data->pwr_reg);
  22501. + goto regulator_put;
  22502. + }
  22503. + }
  22504. +
  22505. + if ((bdata->lab_reg_name != NULL) && (*bdata->lab_reg_name != 0)) {
  22506. + rmi4_data->lab_reg = regulator_get(rmi4_data->pdev->dev.parent,
  22507. + bdata->lab_reg_name);
  22508. + if (IS_ERR(rmi4_data->lab_reg)) {
  22509. + dev_err(rmi4_data->pdev->dev.parent,
  22510. + "%s: Failed to get lab regulator\n",
  22511. + __func__);
  22512. + retval = PTR_ERR(rmi4_data->lab_reg);
  22513. + goto regulator_put;
  22514. + }
  22515. + }
  22516. +
  22517. + if ((bdata->ibb_reg_name != NULL) && (*bdata->ibb_reg_name != 0)) {
  22518. + rmi4_data->ibb_reg = regulator_get(rmi4_data->pdev->dev.parent,
  22519. + bdata->ibb_reg_name);
  22520. + if (IS_ERR(rmi4_data->ibb_reg)) {
  22521. + dev_err(rmi4_data->pdev->dev.parent,
  22522. + "%s: Failed to get ibb regulator\n",
  22523. + __func__);
  22524. + retval = PTR_ERR(rmi4_data->ibb_reg);
  22525. + goto regulator_put;
  22526. + }
  22527. + }
  22528. +
  22529. + if ((bdata->disp_reg_name != NULL) && (*bdata->disp_reg_name != 0)) {
  22530. + rmi4_data->disp_reg = regulator_get(rmi4_data->pdev->dev.parent,
  22531. + bdata->disp_reg_name);
  22532. + if (IS_ERR(rmi4_data->disp_reg)) {
  22533. + dev_err(rmi4_data->pdev->dev.parent,
  22534. + "%s: Failed to get vddio regulator\n",
  22535. + __func__);
  22536. + retval = PTR_ERR(rmi4_data->disp_reg);
  22537. + goto regulator_put;
  22538. + }
  22539. + }
  22540. +
  22541. + if ((bdata->bus_reg_name != NULL) && (*bdata->bus_reg_name != 0)) {
  22542. + rmi4_data->bus_reg = regulator_get(rmi4_data->pdev->dev.parent,
  22543. + bdata->bus_reg_name);
  22544. + if (IS_ERR(rmi4_data->bus_reg)) {
  22545. + dev_err(rmi4_data->pdev->dev.parent,
  22546. + "%s: Failed to get bus pullup regulator\n",
  22547. + __func__);
  22548. + retval = PTR_ERR(rmi4_data->bus_reg);
  22549. + goto regulator_put;
  22550. + }
  22551. + }
  22552. +
  22553. + return 0;
  22554. +
  22555. +regulator_put:
  22556. + if (rmi4_data->pwr_reg) {
  22557. + regulator_put(rmi4_data->pwr_reg);
  22558. + rmi4_data->pwr_reg = NULL;
  22559. + }
  22560. +
  22561. + if (rmi4_data->lab_reg) {
  22562. + regulator_put(rmi4_data->lab_reg);
  22563. + rmi4_data->lab_reg = NULL;
  22564. + }
  22565. + if (rmi4_data->ibb_reg) {
  22566. + regulator_put(rmi4_data->ibb_reg);
  22567. + rmi4_data->ibb_reg = NULL;
  22568. + }
  22569. + if (rmi4_data->disp_reg) {
  22570. + regulator_put(rmi4_data->disp_reg);
  22571. + rmi4_data->disp_reg = NULL;
  22572. + }
  22573. +
  22574. + if (rmi4_data->bus_reg) {
  22575. + regulator_put(rmi4_data->bus_reg);
  22576. + rmi4_data->bus_reg = NULL;
  22577. + }
  22578. +
  22579. + return retval;
  22580. +}
  22581. +
  22582. +static int synaptics_rmi4_enable_reg(struct synaptics_rmi4_data *rmi4_data,
  22583. + bool enable)
  22584. +{
  22585. + int retval;
  22586. + const struct synaptics_dsx_board_data *bdata =
  22587. + rmi4_data->hw_if->board_data;
  22588. +
  22589. + if (!enable) {
  22590. + retval = 0;
  22591. + goto disable_pwr_reg;
  22592. + }
  22593. +
  22594. + if (rmi4_data->bus_reg) {
  22595. + retval = regulator_enable(rmi4_data->bus_reg);
  22596. + if (retval < 0) {
  22597. + dev_err(rmi4_data->pdev->dev.parent,
  22598. + "%s: Failed to enable bus pullup regulator\n",
  22599. + __func__);
  22600. + goto exit;
  22601. + }
  22602. + }
  22603. +
  22604. + if (rmi4_data->pwr_reg) {
  22605. + retval = regulator_enable(rmi4_data->pwr_reg);
  22606. + if (retval < 0) {
  22607. + dev_err(rmi4_data->pdev->dev.parent,
  22608. + "%s: Failed to enable power regulator\n",
  22609. + __func__);
  22610. + goto disable_bus_reg;
  22611. + }
  22612. + msleep(bdata->power_delay_ms);
  22613. + }
  22614. +
  22615. + return 0;
  22616. +
  22617. +disable_pwr_reg:
  22618. + if (rmi4_data->pwr_reg)
  22619. + regulator_disable(rmi4_data->pwr_reg);
  22620. +
  22621. +disable_bus_reg:
  22622. + if (rmi4_data->bus_reg)
  22623. + regulator_disable(rmi4_data->bus_reg);
  22624. +
  22625. +exit:
  22626. + return retval;
  22627. +}
  22628. +
  22629. +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data)
  22630. +{
  22631. + unsigned char ii;
  22632. +
  22633. + mutex_lock(&(rmi4_data->rmi4_report_mutex));
  22634. +
  22635. +#ifdef TYPE_B_PROTOCOL
  22636. + for (ii = 0; ii < rmi4_data->num_of_fingers; ii++) {
  22637. + input_mt_slot(rmi4_data->input_dev, ii);
  22638. + input_mt_report_slot_state(rmi4_data->input_dev,
  22639. + MT_TOOL_FINGER, 0);
  22640. + }
  22641. +#endif
  22642. + input_report_key(rmi4_data->input_dev,
  22643. + BTN_TOUCH, 0);
  22644. + input_report_key(rmi4_data->input_dev,
  22645. + BTN_TOOL_FINGER, 0);
  22646. +#ifndef TYPE_B_PROTOCOL
  22647. + input_mt_sync(rmi4_data->input_dev);
  22648. +#endif
  22649. + input_sync(rmi4_data->input_dev);
  22650. +
  22651. + if (rmi4_data->stylus_enable) {
  22652. + input_report_key(rmi4_data->stylus_dev,
  22653. + BTN_TOUCH, 0);
  22654. + input_report_key(rmi4_data->stylus_dev,
  22655. + BTN_TOOL_PEN, 0);
  22656. + if (rmi4_data->eraser_enable) {
  22657. + input_report_key(rmi4_data->stylus_dev,
  22658. + BTN_TOOL_RUBBER, 0);
  22659. + }
  22660. + input_sync(rmi4_data->stylus_dev);
  22661. + }
  22662. +
  22663. + rmi4_data->touchs = 0;
  22664. +
  22665. + mutex_unlock(&(rmi4_data->rmi4_report_mutex));
  22666. +
  22667. + rmi4_data->fingers_on_2d = false;
  22668. +
  22669. + return 0;
  22670. +}
  22671. +
  22672. +static int synaptics_rmi4_sw_reset(struct synaptics_rmi4_data *rmi4_data)
  22673. +{
  22674. + int retval;
  22675. + unsigned char command = 0x01;
  22676. +
  22677. + retval = synaptics_rmi4_reg_write(rmi4_data,
  22678. + rmi4_data->f01_cmd_base_addr,
  22679. + &command,
  22680. + sizeof(command));
  22681. + if (retval < 0)
  22682. + return retval;
  22683. +
  22684. + msleep(rmi4_data->hw_if->board_data->reset_delay_ms);
  22685. +
  22686. + if (rmi4_data->hw_if->ui_hw_init) {
  22687. + retval = rmi4_data->hw_if->ui_hw_init(rmi4_data);
  22688. + if (retval < 0)
  22689. + return retval;
  22690. + }
  22691. +
  22692. + return 0;
  22693. +}
  22694. +
  22695. +static void synaptics_rmi4_rebuild_work(struct work_struct *work)
  22696. +{
  22697. + int retval;
  22698. + unsigned char attr_count;
  22699. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  22700. + struct delayed_work *delayed_work =
  22701. + container_of(work, struct delayed_work, work);
  22702. + struct synaptics_rmi4_data *rmi4_data =
  22703. + container_of(delayed_work, struct synaptics_rmi4_data,
  22704. + rb_work);
  22705. +
  22706. + mutex_lock(&(rmi4_data->rmi4_reset_mutex));
  22707. +
  22708. + mutex_lock(&exp_data.mutex);
  22709. +
  22710. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  22711. +
  22712. + if (!list_empty(&exp_data.list)) {
  22713. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  22714. + if (exp_fhandler->exp_fn->remove != NULL)
  22715. + exp_fhandler->exp_fn->remove(rmi4_data);
  22716. + }
  22717. +
  22718. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  22719. + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
  22720. + &attrs[attr_count].attr);
  22721. + }
  22722. +
  22723. + synaptics_rmi4_free_fingers(rmi4_data);
  22724. + synaptics_rmi4_empty_fn_list(rmi4_data);
  22725. + input_unregister_device(rmi4_data->input_dev);
  22726. + rmi4_data->input_dev = NULL;
  22727. + if (rmi4_data->stylus_enable) {
  22728. + input_unregister_device(rmi4_data->stylus_dev);
  22729. + rmi4_data->stylus_dev = NULL;
  22730. + }
  22731. +
  22732. + retval = synaptics_rmi4_sw_reset(rmi4_data);
  22733. + if (retval < 0) {
  22734. + dev_err(rmi4_data->pdev->dev.parent,
  22735. + "%s: Failed to issue reset command\n",
  22736. + __func__);
  22737. + goto exit;
  22738. + }
  22739. +
  22740. + retval = synaptics_rmi4_set_input_dev(rmi4_data);
  22741. + if (retval < 0) {
  22742. + dev_err(rmi4_data->pdev->dev.parent,
  22743. + "%s: Failed to set up input device\n",
  22744. + __func__);
  22745. + goto exit;
  22746. + }
  22747. +
  22748. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  22749. + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
  22750. + &attrs[attr_count].attr);
  22751. + if (retval < 0) {
  22752. + dev_err(rmi4_data->pdev->dev.parent,
  22753. + "%s: Failed to create sysfs attributes\n",
  22754. + __func__);
  22755. + goto exit;
  22756. + }
  22757. + }
  22758. +
  22759. + if (!list_empty(&exp_data.list)) {
  22760. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  22761. + if (exp_fhandler->exp_fn->init != NULL)
  22762. + exp_fhandler->exp_fn->init(rmi4_data);
  22763. + }
  22764. +
  22765. + retval = 0;
  22766. +
  22767. +exit:
  22768. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  22769. +
  22770. + mutex_unlock(&exp_data.mutex);
  22771. +
  22772. + mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
  22773. +
  22774. + return;
  22775. +}
  22776. +
  22777. +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data)
  22778. +{
  22779. + int retval;
  22780. + struct synaptics_rmi4_fn *fhandler;
  22781. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  22782. + struct synaptics_rmi4_device_info *rmi;
  22783. +
  22784. + rmi = &(rmi4_data->rmi4_mod_info);
  22785. +
  22786. + mutex_lock(&(rmi4_data->rmi4_reset_mutex));
  22787. +
  22788. + synaptics_rmi4_free_fingers(rmi4_data);
  22789. +
  22790. + if (!list_empty(&rmi->support_fn_list)) {
  22791. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  22792. + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) {
  22793. + synaptics_rmi4_f12_set_enables(rmi4_data, 0);
  22794. + break;
  22795. + }
  22796. + }
  22797. + }
  22798. +
  22799. + retval = synaptics_rmi4_int_enable(rmi4_data, true);
  22800. + if (retval < 0)
  22801. + goto exit;
  22802. +
  22803. + mutex_lock(&exp_data.mutex);
  22804. + if (!list_empty(&exp_data.list)) {
  22805. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  22806. + if (exp_fhandler->exp_fn->reinit != NULL)
  22807. + exp_fhandler->exp_fn->reinit(rmi4_data);
  22808. + }
  22809. + mutex_unlock(&exp_data.mutex);
  22810. +
  22811. + synaptics_rmi4_set_configured(rmi4_data);
  22812. +
  22813. + retval = 0;
  22814. +
  22815. +exit:
  22816. + mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
  22817. + return retval;
  22818. +}
  22819. +
  22820. +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data,
  22821. + bool rebuild)
  22822. +{
  22823. + int retval;
  22824. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  22825. +
  22826. + if (rebuild) {
  22827. + queue_delayed_work(rmi4_data->rb_workqueue,
  22828. + &rmi4_data->rb_work,
  22829. + msecs_to_jiffies(REBUILD_WORK_DELAY_MS));
  22830. + return 0;
  22831. + }
  22832. +
  22833. + mutex_lock(&(rmi4_data->rmi4_reset_mutex));
  22834. +
  22835. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  22836. +
  22837. + retval = synaptics_rmi4_sw_reset(rmi4_data);
  22838. + if (retval < 0) {
  22839. + dev_err(rmi4_data->pdev->dev.parent,
  22840. + "%s: Failed to issue reset command\n",
  22841. + __func__);
  22842. + goto exit;
  22843. + }
  22844. +
  22845. + synaptics_rmi4_free_fingers(rmi4_data);
  22846. +
  22847. + synaptics_rmi4_empty_fn_list(rmi4_data);
  22848. +
  22849. + retval = synaptics_rmi4_query_device(rmi4_data);
  22850. + if (retval < 0) {
  22851. + dev_err(rmi4_data->pdev->dev.parent,
  22852. + "%s: Failed to query device\n",
  22853. + __func__);
  22854. + goto exit;
  22855. + }
  22856. +
  22857. + mutex_lock(&exp_data.mutex);
  22858. + if (!list_empty(&exp_data.list)) {
  22859. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  22860. + if (exp_fhandler->exp_fn->reset != NULL)
  22861. + exp_fhandler->exp_fn->reset(rmi4_data);
  22862. + }
  22863. + mutex_unlock(&exp_data.mutex);
  22864. +
  22865. + retval = 0;
  22866. +
  22867. +exit:
  22868. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  22869. +
  22870. + mutex_unlock(&(rmi4_data->rmi4_reset_mutex));
  22871. +
  22872. + return retval;
  22873. +}
  22874. +
  22875. +#ifdef FB_READY_RESET
  22876. +static void synaptics_rmi4_reset_work(struct work_struct *work)
  22877. +{
  22878. + int retval;
  22879. + unsigned int timeout;
  22880. + struct synaptics_rmi4_data *rmi4_data =
  22881. + container_of(work, struct synaptics_rmi4_data,
  22882. + reset_work);
  22883. +
  22884. + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1;
  22885. +
  22886. + while (!rmi4_data->fb_ready) {
  22887. + msleep(FB_READY_WAIT_MS);
  22888. + timeout--;
  22889. + if (timeout == 0) {
  22890. + dev_err(rmi4_data->pdev->dev.parent,
  22891. + "%s: Timed out waiting for FB ready\n",
  22892. + __func__);
  22893. + return;
  22894. + }
  22895. + }
  22896. +
  22897. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  22898. +
  22899. + retval = synaptics_rmi4_reset_device(rmi4_data, false);
  22900. + if (retval < 0) {
  22901. + dev_err(rmi4_data->pdev->dev.parent,
  22902. + "%s: Failed to issue reset command\n",
  22903. + __func__);
  22904. + }
  22905. +
  22906. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  22907. +
  22908. + return;
  22909. +}
  22910. +#endif
  22911. +
  22912. +static void synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data,
  22913. + bool enable)
  22914. +{
  22915. + int retval;
  22916. + unsigned char device_ctrl;
  22917. + unsigned char no_sleep_setting = rmi4_data->no_sleep_setting;
  22918. +
  22919. + retval = synaptics_rmi4_reg_read(rmi4_data,
  22920. + rmi4_data->f01_ctrl_base_addr,
  22921. + &device_ctrl,
  22922. + sizeof(device_ctrl));
  22923. + if (retval < 0) {
  22924. + dev_err(rmi4_data->pdev->dev.parent,
  22925. + "%s: Failed to read device control\n",
  22926. + __func__);
  22927. + return;
  22928. + }
  22929. +
  22930. + device_ctrl = device_ctrl & ~MASK_3BIT;
  22931. + if (enable)
  22932. + device_ctrl = device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP;
  22933. + else
  22934. + device_ctrl = device_ctrl | no_sleep_setting | NORMAL_OPERATION;
  22935. +
  22936. + retval = synaptics_rmi4_reg_write(rmi4_data,
  22937. + rmi4_data->f01_ctrl_base_addr,
  22938. + &device_ctrl,
  22939. + sizeof(device_ctrl));
  22940. + if (retval < 0) {
  22941. + dev_err(rmi4_data->pdev->dev.parent,
  22942. + "%s: Failed to write device control\n",
  22943. + __func__);
  22944. + return;
  22945. + }
  22946. +
  22947. + rmi4_data->sensor_sleep = enable;
  22948. +
  22949. + return;
  22950. +}
  22951. +
  22952. +static void synaptics_rmi4_exp_fn_work(struct work_struct *work)
  22953. +{
  22954. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  22955. + struct synaptics_rmi4_exp_fhandler *exp_fhandler_temp;
  22956. + struct synaptics_rmi4_data *rmi4_data = exp_data.rmi4_data;
  22957. +
  22958. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  22959. + mutex_lock(&rmi4_data->rmi4_reset_mutex);
  22960. + mutex_lock(&exp_data.mutex);
  22961. + if (!list_empty(&exp_data.list)) {
  22962. + list_for_each_entry_safe(exp_fhandler,
  22963. + exp_fhandler_temp,
  22964. + &exp_data.list,
  22965. + link) {
  22966. + if ((exp_fhandler->exp_fn->init != NULL) &&
  22967. + exp_fhandler->insert) {
  22968. + exp_fhandler->exp_fn->init(rmi4_data);
  22969. + exp_fhandler->insert = false;
  22970. + } else if ((exp_fhandler->exp_fn->remove != NULL) &&
  22971. + exp_fhandler->remove) {
  22972. + exp_fhandler->exp_fn->remove(rmi4_data);
  22973. + list_del(&exp_fhandler->link);
  22974. + kfree(exp_fhandler);
  22975. + }
  22976. + }
  22977. + }
  22978. + mutex_unlock(&exp_data.mutex);
  22979. + mutex_unlock(&rmi4_data->rmi4_reset_mutex);
  22980. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  22981. +
  22982. + return;
  22983. +}
  22984. +
  22985. +void synaptics_rmi4_new_function_force(struct synaptics_rmi4_exp_fn *exp_fn,
  22986. + bool insert)
  22987. +{
  22988. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  22989. +
  22990. + if (!exp_data.initialized) {
  22991. + mutex_init(&exp_data.mutex);
  22992. + INIT_LIST_HEAD(&exp_data.list);
  22993. + exp_data.initialized = true;
  22994. + }
  22995. +
  22996. + mutex_lock(&exp_data.mutex);
  22997. + if (insert) {
  22998. + exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL);
  22999. + if (!exp_fhandler) {
  23000. + pr_err("%s: Failed to alloc mem for expansion function\n",
  23001. + __func__);
  23002. + goto exit;
  23003. + }
  23004. + exp_fhandler->exp_fn = exp_fn;
  23005. + exp_fhandler->insert = true;
  23006. + exp_fhandler->remove = false;
  23007. + list_add_tail(&exp_fhandler->link, &exp_data.list);
  23008. + } else if (!list_empty(&exp_data.list)) {
  23009. + list_for_each_entry(exp_fhandler, &exp_data.list, link) {
  23010. + if (exp_fhandler->exp_fn->fn_type == exp_fn->fn_type) {
  23011. + exp_fhandler->insert = false;
  23012. + exp_fhandler->remove = true;
  23013. + goto exit;
  23014. + }
  23015. + }
  23016. + }
  23017. +
  23018. +exit:
  23019. + mutex_unlock(&exp_data.mutex);
  23020. +
  23021. + if (exp_data.queue_work) {
  23022. + queue_delayed_work(exp_data.workqueue,
  23023. + &exp_data.work,
  23024. + msecs_to_jiffies(EXP_FN_WORK_DELAY_MS));
  23025. + }
  23026. +
  23027. + return;
  23028. +}
  23029. +
  23030. +#ifdef CONFIG_TOUCH_DEBUG_FS
  23031. +static int synaptics_tpdbg_suspend(struct synaptics_rmi4_data *rmi4_data)
  23032. +{
  23033. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  23034. +
  23035. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  23036. + if (!rmi4_data->enable_wakeup_gesture)
  23037. + synaptics_rmi4_sleep_enable(rmi4_data, true);
  23038. +
  23039. + if (rmi4_data->enable_wakeup_gesture) {
  23040. + msleep(300);
  23041. + synaptics_rmi4_wakeup_gesture(rmi4_data, true);
  23042. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  23043. + goto exit;
  23044. + }
  23045. +
  23046. + mutex_lock(&exp_data.mutex);
  23047. + if (!list_empty(&exp_data.list)) {
  23048. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  23049. + if (exp_fhandler->exp_fn->suspend != NULL)
  23050. + exp_fhandler->exp_fn->suspend(rmi4_data);
  23051. + }
  23052. + mutex_unlock(&exp_data.mutex);
  23053. +
  23054. +exit:
  23055. + return 0;
  23056. +}
  23057. +
  23058. +static int synaptics_tpdbg_resume(struct synaptics_rmi4_data *rmi4_data)
  23059. +{
  23060. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  23061. + const struct synaptics_dsx_board_data *bdata =
  23062. + rmi4_data->hw_if->board_data;
  23063. +
  23064. + if (rmi4_data->enable_wakeup_gesture) {
  23065. + synaptics_rmi4_wakeup_gesture(rmi4_data, false);
  23066. + if (bdata->reset_gpio >= 0) {
  23067. + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
  23068. + msleep(bdata->reset_active_ms);
  23069. + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
  23070. + msleep(bdata->reset_delay_ms);
  23071. + }
  23072. + } else {
  23073. + rmi4_data->current_page = MASK_8BIT;
  23074. + if (bdata->reset_gpio >= 0) {
  23075. + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
  23076. + msleep(bdata->reset_active_ms);
  23077. + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
  23078. + msleep(bdata->reset_delay_ms);
  23079. + }
  23080. +
  23081. + synaptics_rmi4_sleep_enable(rmi4_data, false);
  23082. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  23083. +
  23084. + mutex_lock(&exp_data.mutex);
  23085. + if (!list_empty(&exp_data.list)) {
  23086. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  23087. + if (exp_fhandler->exp_fn->resume != NULL)
  23088. + exp_fhandler->exp_fn->resume(rmi4_data);
  23089. + }
  23090. + mutex_unlock(&exp_data.mutex);
  23091. + }
  23092. +
  23093. + return 0;
  23094. +}
  23095. +
  23096. +static void tpdbg_shutdown(struct synaptics_rmi4_data *rmi4_data, bool sleep)
  23097. +{
  23098. + synaptics_rmi4_sleep_enable(rmi4_data, sleep);
  23099. +}
  23100. +
  23101. +static void tpdbg_suspend(struct synaptics_rmi4_data *rmi4_data, bool enable)
  23102. +{
  23103. + if (enable)
  23104. + synaptics_tpdbg_suspend(rmi4_data);
  23105. + else
  23106. + synaptics_tpdbg_resume(rmi4_data);
  23107. +}
  23108. +
  23109. +static int tpdbg_open(struct inode *inode, struct file *file)
  23110. +{
  23111. + file->private_data = inode->i_private;
  23112. +
  23113. + return 0;
  23114. +}
  23115. +
  23116. +ssize_t tpdbg_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
  23117. +{
  23118. + const char *str = "cmd support as below:\n \
  23119. + \necho \"irq-disable\" or \"irq-enable\" to ctrl irq\n \
  23120. + \necho \"tp-sd-en\" of \"tp-sd-off\" to ctrl panel in or off sleep mode\n \
  23121. + \necho \"tp-suspend-en\" or \"tp-suspend-off\" to ctrl panel in or off suspend status\n";
  23122. +
  23123. + loff_t pos = *ppos;
  23124. + int len = strlen(str);
  23125. +
  23126. + if (pos < 0)
  23127. + return -EINVAL;
  23128. + if (pos >= len)
  23129. + return 0;
  23130. +
  23131. + if (copy_to_user(buf, str, len))
  23132. + return -EFAULT;
  23133. +
  23134. + *ppos = pos + len;
  23135. +
  23136. + return len;
  23137. +}
  23138. +
  23139. +ssize_t tpdbg_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
  23140. +{
  23141. + struct synaptics_rmi4_data *rmi4_data = file->private_data;
  23142. + char *cmd = kzalloc(size + 1, GFP_KERNEL);
  23143. + int ret = size;
  23144. +
  23145. + if (!cmd)
  23146. + return -ENOMEM;
  23147. +
  23148. + if (copy_from_user(cmd, buf, size)) {
  23149. + ret = -EFAULT;
  23150. + goto out;
  23151. + }
  23152. +
  23153. + cmd[size] = '\0';
  23154. +
  23155. + if (!strncmp(cmd, "irq-disable", 11))
  23156. + disable_irq(rmi4_data->irq);
  23157. + else if (!strncmp(cmd, "irq-enable", 10))
  23158. + enable_irq(rmi4_data->irq);
  23159. + else if (!strncmp(cmd, "tp-sd-en", 8))
  23160. + tpdbg_shutdown(rmi4_data, true);
  23161. + else if (!strncmp(cmd, "tp-sd-off", 9))
  23162. + tpdbg_shutdown(rmi4_data, false);
  23163. + else if (!strncmp(cmd, "tp-suspend-en", 13))
  23164. + tpdbg_suspend(rmi4_data, true);
  23165. + else if (!strncmp(cmd, "tp-suspend-off", 14))
  23166. + tpdbg_suspend(rmi4_data, false);
  23167. +out:
  23168. + kfree(cmd);
  23169. +
  23170. + return ret;
  23171. +}
  23172. +
  23173. +int tpdbg_release (struct inode *inode, struct file *file)
  23174. +{
  23175. + file->private_data = NULL;
  23176. +
  23177. + return 0;
  23178. +}
  23179. +
  23180. +static const struct file_operations tpdbg_operations = {
  23181. + .owner = THIS_MODULE,
  23182. + .open = tpdbg_open,
  23183. + .read = tpdbg_read,
  23184. + .write = tpdbg_write,
  23185. + .release = tpdbg_release,
  23186. +};
  23187. +#endif
  23188. +
  23189. +extern unsigned int get_hw_version_major(void);
  23190. +
  23191. +static int synaptics_rmi4_probe(struct platform_device *pdev)
  23192. +{
  23193. + int retval;
  23194. + unsigned char attr_count;
  23195. + struct synaptics_rmi4_data *rmi4_data;
  23196. + const struct synaptics_dsx_hw_interface *hw_if;
  23197. + const struct synaptics_dsx_board_data *bdata;
  23198. +
  23199. + hw_if = pdev->dev.platform_data;
  23200. + if (!hw_if) {
  23201. + dev_err(&pdev->dev,
  23202. + "%s: No hardware interface found\n",
  23203. + __func__);
  23204. + return -EINVAL;
  23205. + }
  23206. +
  23207. + bdata = hw_if->board_data;
  23208. + if (!bdata) {
  23209. + dev_err(&pdev->dev,
  23210. + "%s: No board data found\n",
  23211. + __func__);
  23212. + return -EINVAL;
  23213. + }
  23214. +
  23215. + rmi4_data = kzalloc(sizeof(*rmi4_data), GFP_KERNEL);
  23216. + if (!rmi4_data) {
  23217. + dev_err(&pdev->dev,
  23218. + "%s: Failed to alloc mem for rmi4_data\n",
  23219. + __func__);
  23220. + return -ENOMEM;
  23221. + }
  23222. +
  23223. + rmi4_data->pdev = pdev;
  23224. + rmi4_data->current_page = MASK_8BIT;
  23225. + rmi4_data->hw_if = hw_if;
  23226. + rmi4_data->suspend = false;
  23227. + rmi4_data->irq_enabled = false;
  23228. + rmi4_data->fingers_on_2d = false;
  23229. + rmi4_data->wakeup_en = false;
  23230. +
  23231. + rmi4_data->reset_device = synaptics_rmi4_reset_device;
  23232. + rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
  23233. + rmi4_data->sleep_enable = synaptics_rmi4_sleep_enable;
  23234. +// rmi4_data->hw_version = get_hw_version_major();
  23235. +
  23236. + mutex_init(&(rmi4_data->rmi4_reset_mutex));
  23237. + mutex_init(&(rmi4_data->rmi4_report_mutex));
  23238. + mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
  23239. + mutex_init(&(rmi4_data->rmi4_exp_init_mutex));
  23240. + mutex_init(&(rmi4_data->rmi4_irq_enable_mutex));
  23241. + mutex_init(&(rmi4_data->rmi4_cover_mutex));
  23242. +
  23243. + init_completion(&rmi4_data->dump_completion);
  23244. +
  23245. + platform_set_drvdata(pdev, rmi4_data);
  23246. +
  23247. + vir_button_map = bdata->vir_button_map;
  23248. +
  23249. + retval = synaptics_rmi4_get_reg(rmi4_data, true);
  23250. + if (retval < 0) {
  23251. + dev_err(&pdev->dev,
  23252. + "%s: Failed to get regulators\n",
  23253. + __func__);
  23254. + goto err_get_reg;
  23255. + }
  23256. +
  23257. + retval = synaptics_rmi4_enable_reg(rmi4_data, true);
  23258. + if (retval < 0) {
  23259. + dev_err(&pdev->dev,
  23260. + "%s: Failed to enable regulators\n",
  23261. + __func__);
  23262. + goto err_enable_reg;
  23263. + }
  23264. +
  23265. + retval = synaptics_rmi4_set_gpio(rmi4_data);
  23266. + if (retval < 0) {
  23267. + dev_err(&pdev->dev,
  23268. + "%s: Failed to set up GPIO's\n",
  23269. + __func__);
  23270. + goto err_set_gpio;
  23271. + }
  23272. +
  23273. + retval = synaptics_rmi4_pinctrl_init(rmi4_data);
  23274. + if (!retval && rmi4_data->ts_pinctrl) {
  23275. + retval = pinctrl_select_state(rmi4_data->ts_pinctrl,
  23276. + rmi4_data->pinctrl_state_active);
  23277. + if (retval < 0) {
  23278. + dev_err(&pdev->dev,
  23279. + "%s: Failed to select %s pinstate %d\n",
  23280. + __func__, PINCTRL_STATE_ACTIVE, retval);
  23281. + goto err_pinctrl_init;
  23282. + }
  23283. + } else {
  23284. + dev_err(&pdev->dev,
  23285. + "%s: Failed to init pinctrl\n",
  23286. + __func__);
  23287. + goto err_pinctrl_init;
  23288. + }
  23289. +
  23290. + if (hw_if->ui_hw_init) {
  23291. + retval = hw_if->ui_hw_init(rmi4_data);
  23292. + if (retval < 0) {
  23293. + dev_err(&pdev->dev,
  23294. + "%s: Failed to initialize hardware interface\n",
  23295. + __func__);
  23296. + goto err_ui_hw_init;
  23297. + }
  23298. + }
  23299. +
  23300. + retval = synaptics_rmi4_set_input_dev(rmi4_data);
  23301. + if (retval < 0) {
  23302. + dev_err(&pdev->dev,
  23303. + "%s: Failed to set up input device\n",
  23304. + __func__);
  23305. + goto err_set_input_dev;
  23306. + }
  23307. +
  23308. + synaptics_rmi4_query_chip_id(rmi4_data);
  23309. +
  23310. +#ifdef CONFIG_FB
  23311. + if (!rmi4_data->chip_is_tddi)
  23312. + rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb;
  23313. + else
  23314. + rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb_tddi;
  23315. + retval = fb_register_client(&rmi4_data->fb_notifier);
  23316. + if (retval < 0) {
  23317. + dev_err(&pdev->dev,
  23318. + "%s: Failed to register fb notifier client\n",
  23319. + __func__);
  23320. + }
  23321. +#endif
  23322. +
  23323. +#ifdef USE_EARLYSUSPEND
  23324. + rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
  23325. + rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend;
  23326. + rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume;
  23327. + register_early_suspend(&rmi4_data->early_suspend);
  23328. +#endif
  23329. +
  23330. + if (!exp_data.initialized) {
  23331. + mutex_init(&exp_data.mutex);
  23332. + INIT_LIST_HEAD(&exp_data.list);
  23333. + exp_data.initialized = true;
  23334. + }
  23335. +
  23336. + rmi4_data->irq = gpio_to_irq(bdata->irq_gpio);
  23337. +
  23338. + retval = synaptics_rmi4_irq_enable(rmi4_data, true, false);
  23339. + if (retval < 0) {
  23340. + dev_err(&pdev->dev,
  23341. + "%s: Failed to enable attention interrupt\n",
  23342. + __func__);
  23343. + goto err_enable_irq;
  23344. + }
  23345. +
  23346. + if (vir_button_map->nbuttons) {
  23347. + rmi4_data->board_prop_dir = kobject_create_and_add(
  23348. + "board_properties", NULL);
  23349. + if (!rmi4_data->board_prop_dir) {
  23350. + dev_err(&pdev->dev,
  23351. + "%s: Failed to create board_properties directory\n",
  23352. + __func__);
  23353. + goto err_virtual_buttons;
  23354. + } else {
  23355. + retval = sysfs_create_file(rmi4_data->board_prop_dir,
  23356. + &virtual_key_map_attr.attr);
  23357. + if (retval < 0) {
  23358. + dev_err(&pdev->dev,
  23359. + "%s: Failed to create virtual key map file\n",
  23360. + __func__);
  23361. + goto err_virtual_buttons;
  23362. + }
  23363. + }
  23364. + }
  23365. +
  23366. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  23367. + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
  23368. + &attrs[attr_count].attr);
  23369. + if (retval < 0) {
  23370. + dev_err(&pdev->dev,
  23371. + "%s: Failed to create sysfs attributes\n",
  23372. + __func__);
  23373. + goto err_sysfs;
  23374. + }
  23375. + }
  23376. +
  23377. + retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_color.attr);
  23378. +
  23379. + if (retval < 0) {
  23380. + dev_err(&pdev->dev,
  23381. + "%s: Failed to create sysfs attributes\n",
  23382. + __func__);
  23383. + goto err_sysfs;
  23384. + }
  23385. +
  23386. +#if defined(CONFIG_SECURE_TOUCH)
  23387. + retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch.attr);
  23388. +
  23389. + if (retval < 0) {
  23390. + dev_err(&pdev->dev,
  23391. + "%s: Failed to create sysfs attributes\n",
  23392. + __func__);
  23393. + goto err_sysfs_secure;
  23394. + }
  23395. +
  23396. + retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch_enable.attr);
  23397. +
  23398. + if (retval < 0) {
  23399. + dev_err(&pdev->dev,
  23400. + "%s: Failed to create sysfs attributes\n",
  23401. + __func__);
  23402. + goto err_sysfs_secure_enable;
  23403. + }
  23404. +#endif
  23405. +
  23406. + retval = sysfs_create_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_vendor.attr);
  23407. +
  23408. + if (retval < 0) {
  23409. + dev_err(&pdev->dev,
  23410. + "%s: Failed to create sysfs attributes\n",
  23411. + __func__);
  23412. + goto err_sysfs_panel_vendor;
  23413. + }
  23414. +
  23415. +#ifdef CONFIG_TOUCH_DEBUG_FS
  23416. + rmi4_data->debugfs = debugfs_create_dir("tp_debug", NULL);
  23417. + if (rmi4_data->debugfs) {
  23418. + debugfs_create_file("switch_state", 0660, rmi4_data->debugfs, rmi4_data, &tpdbg_operations);
  23419. + }
  23420. +#endif
  23421. +
  23422. + dev_set_drvdata(rmi4_data->pdev->dev.parent, rmi4_data);
  23423. +
  23424. + rmi4_data->rb_workqueue =
  23425. + create_singlethread_workqueue("dsx_rebuild_workqueue");
  23426. + INIT_DELAYED_WORK(&rmi4_data->rb_work, synaptics_rmi4_rebuild_work);
  23427. +
  23428. + exp_data.workqueue = create_singlethread_workqueue("dsx_exp_workqueue");
  23429. + INIT_DELAYED_WORK(&exp_data.work, synaptics_rmi4_exp_fn_work);
  23430. + exp_data.rmi4_data = rmi4_data;
  23431. + exp_data.queue_work = true;
  23432. + queue_delayed_work(exp_data.workqueue,
  23433. + &exp_data.work,
  23434. + 0);
  23435. +
  23436. +#ifdef FB_READY_RESET
  23437. + rmi4_data->reset_workqueue =
  23438. + create_singlethread_workqueue("dsx_reset_workqueue");
  23439. + INIT_WORK(&rmi4_data->reset_work, synaptics_rmi4_reset_work);
  23440. + queue_work(rmi4_data->reset_workqueue, &rmi4_data->reset_work);
  23441. +#endif
  23442. +
  23443. + device_init_wakeup(&pdev->dev, 1);
  23444. +
  23445. + synaptics_secure_touch_init(rmi4_data);
  23446. + synaptics_secure_touch_stop(rmi4_data, 1);
  23447. +
  23448. + return retval;
  23449. +
  23450. +
  23451. +err_sysfs_panel_vendor:
  23452. +#if defined(CONFIG_SECURE_TOUCH)
  23453. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch_enable.attr);
  23454. +err_sysfs_secure_enable:
  23455. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch.attr);
  23456. +err_sysfs_secure:
  23457. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_color.attr);
  23458. +#endif
  23459. +err_sysfs:
  23460. + for (attr_count--; attr_count >= 0; attr_count--) {
  23461. + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
  23462. + &attrs[attr_count].attr);
  23463. + }
  23464. +
  23465. +err_virtual_buttons:
  23466. + if (rmi4_data->board_prop_dir) {
  23467. + sysfs_remove_file(rmi4_data->board_prop_dir,
  23468. + &virtual_key_map_attr.attr);
  23469. + kobject_put(rmi4_data->board_prop_dir);
  23470. + }
  23471. +
  23472. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  23473. +
  23474. +err_enable_irq:
  23475. +#ifdef CONFIG_FB
  23476. + fb_unregister_client(&rmi4_data->fb_notifier);
  23477. +#endif
  23478. +
  23479. +#ifdef USE_EARLYSUSPEND
  23480. + unregister_early_suspend(&rmi4_data->early_suspend);
  23481. +#endif
  23482. +
  23483. + synaptics_rmi4_empty_fn_list(rmi4_data);
  23484. + input_unregister_device(rmi4_data->input_dev);
  23485. + rmi4_data->input_dev = NULL;
  23486. + if (rmi4_data->stylus_enable) {
  23487. + input_unregister_device(rmi4_data->stylus_dev);
  23488. + rmi4_data->stylus_dev = NULL;
  23489. + }
  23490. +
  23491. +err_set_input_dev:
  23492. + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0, NULL);
  23493. +
  23494. + if (bdata->reset_gpio >= 0)
  23495. + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0, NULL);
  23496. +
  23497. + if (bdata->power_gpio >= 0)
  23498. + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0, NULL);
  23499. +
  23500. +err_ui_hw_init:
  23501. +err_pinctrl_init:
  23502. + if (rmi4_data->ts_pinctrl) {
  23503. + devm_pinctrl_put(rmi4_data->ts_pinctrl);
  23504. + rmi4_data->ts_pinctrl = NULL;
  23505. + }
  23506. +
  23507. +err_set_gpio:
  23508. + synaptics_rmi4_enable_reg(rmi4_data, false);
  23509. +
  23510. +err_enable_reg:
  23511. + synaptics_rmi4_get_reg(rmi4_data, false);
  23512. +
  23513. +err_get_reg:
  23514. + kfree(rmi4_data);
  23515. +
  23516. + return retval;
  23517. +}
  23518. +
  23519. +static int synaptics_rmi4_remove(struct platform_device *pdev)
  23520. +{
  23521. + unsigned char attr_count;
  23522. + struct synaptics_rmi4_data *rmi4_data = platform_get_drvdata(pdev);
  23523. + const struct synaptics_dsx_board_data *bdata =
  23524. + rmi4_data->hw_if->board_data;
  23525. +
  23526. +#ifdef FB_READY_RESET
  23527. + cancel_work_sync(&rmi4_data->reset_work);
  23528. + flush_workqueue(rmi4_data->reset_workqueue);
  23529. + destroy_workqueue(rmi4_data->reset_workqueue);
  23530. +#endif
  23531. +
  23532. + cancel_delayed_work_sync(&exp_data.work);
  23533. + flush_workqueue(exp_data.workqueue);
  23534. + destroy_workqueue(exp_data.workqueue);
  23535. +
  23536. + cancel_delayed_work_sync(&rmi4_data->rb_work);
  23537. + flush_workqueue(rmi4_data->rb_workqueue);
  23538. + destroy_workqueue(rmi4_data->rb_workqueue);
  23539. +
  23540. +#ifdef CONFIG_TOUCH_DEBUG_FS
  23541. + debugfs_remove_recursive(rmi4_data->debugfs);
  23542. +#endif
  23543. +
  23544. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_vendor.attr);
  23545. +#if defined(CONFIG_SECURE_TOUCH)
  23546. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch_enable.attr);
  23547. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_secure_touch.attr);
  23548. +#endif
  23549. + sysfs_remove_file(&rmi4_data->pdev->dev.parent->kobj, &dev_attr_panel_color.attr);
  23550. +
  23551. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  23552. + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
  23553. + &attrs[attr_count].attr);
  23554. + }
  23555. +
  23556. + if (rmi4_data->board_prop_dir) {
  23557. + sysfs_remove_file(rmi4_data->board_prop_dir,
  23558. + &virtual_key_map_attr.attr);
  23559. + kobject_put(rmi4_data->board_prop_dir);
  23560. + }
  23561. +
  23562. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  23563. +
  23564. +#ifdef CONFIG_FB
  23565. + fb_unregister_client(&rmi4_data->fb_notifier);
  23566. +#endif
  23567. +
  23568. +#ifdef USE_EARLYSUSPEND
  23569. + unregister_early_suspend(&rmi4_data->early_suspend);
  23570. +#endif
  23571. +
  23572. + synaptics_rmi4_empty_fn_list(rmi4_data);
  23573. + input_unregister_device(rmi4_data->input_dev);
  23574. + rmi4_data->input_dev = NULL;
  23575. + if (rmi4_data->stylus_enable) {
  23576. + input_unregister_device(rmi4_data->stylus_dev);
  23577. + rmi4_data->stylus_dev = NULL;
  23578. + }
  23579. +
  23580. + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0, NULL);
  23581. +
  23582. + if (bdata->reset_gpio >= 0)
  23583. + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0, NULL);
  23584. +
  23585. + if (bdata->power_gpio >= 0)
  23586. + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0, NULL);
  23587. +
  23588. + synaptics_rmi4_enable_reg(rmi4_data, false);
  23589. + synaptics_rmi4_get_reg(rmi4_data, false);
  23590. +
  23591. + kfree(rmi4_data);
  23592. +
  23593. + return 0;
  23594. +}
  23595. +
  23596. +static void synaptics_rmi4_f11_wg(struct synaptics_rmi4_data *rmi4_data,
  23597. + bool enable)
  23598. +{
  23599. + int retval;
  23600. + unsigned char reporting_control;
  23601. + struct synaptics_rmi4_fn *fhandler;
  23602. + struct synaptics_rmi4_device_info *rmi;
  23603. +
  23604. + rmi = &(rmi4_data->rmi4_mod_info);
  23605. +
  23606. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  23607. + if (fhandler->fn_number == SYNAPTICS_RMI4_F11)
  23608. + break;
  23609. + }
  23610. +
  23611. + retval = synaptics_rmi4_reg_read(rmi4_data,
  23612. + fhandler->full_addr.ctrl_base,
  23613. + &reporting_control,
  23614. + sizeof(reporting_control));
  23615. + if (retval < 0) {
  23616. + dev_err(rmi4_data->pdev->dev.parent,
  23617. + "%s: Failed to change reporting mode\n",
  23618. + __func__);
  23619. + return;
  23620. + }
  23621. +
  23622. + reporting_control = (reporting_control & ~MASK_3BIT);
  23623. + if (enable)
  23624. + reporting_control |= F11_WAKEUP_GESTURE_MODE;
  23625. + else
  23626. + reporting_control |= F11_CONTINUOUS_MODE;
  23627. +
  23628. + retval = synaptics_rmi4_reg_write(rmi4_data,
  23629. + fhandler->full_addr.ctrl_base,
  23630. + &reporting_control,
  23631. + sizeof(reporting_control));
  23632. + if (retval < 0) {
  23633. + dev_err(rmi4_data->pdev->dev.parent,
  23634. + "%s: Failed to change reporting mode\n",
  23635. + __func__);
  23636. + return;
  23637. + }
  23638. +
  23639. + return;
  23640. +}
  23641. +
  23642. +static void mdss_regulator_ctrl(struct synaptics_rmi4_data *rmi4_data, unsigned int flag, bool enable)
  23643. +{
  23644. + int retval = 0;
  23645. + static unsigned int status = 0;
  23646. +
  23647. + if (rmi4_data == NULL)
  23648. + return;
  23649. + if (!rmi4_data->hw_if->board_data->panel_is_incell)
  23650. + return;
  23651. +
  23652. + if (enable) {
  23653. + if (rmi4_data->disp_reg && (flag & DISP_REG_VDD) && !(status & DISP_REG_VDD)) {
  23654. + retval = regulator_enable(rmi4_data->disp_reg);
  23655. + if (retval < 0) {
  23656. + dev_err(rmi4_data->pdev->dev.parent,
  23657. + "%s: Failed to enable disp regulator\n",
  23658. + __func__);
  23659. + return;
  23660. + }
  23661. +
  23662. + status |= DISP_REG_VDD;
  23663. + }
  23664. +
  23665. + if (rmi4_data->lab_reg && (flag & DISP_REG_LAB) && !(status & DISP_REG_LAB)) {
  23666. + retval = regulator_enable(rmi4_data->lab_reg);
  23667. + if (retval < 0) {
  23668. + dev_err(rmi4_data->pdev->dev.parent,
  23669. + "%s: Failed to enable lab regulator\n",
  23670. + __func__);
  23671. + return;
  23672. + }
  23673. +
  23674. + status |= DISP_REG_LAB;
  23675. + }
  23676. +
  23677. + if (rmi4_data->ibb_reg && (flag & DISP_REG_IBB) && !(status & DISP_REG_IBB)) {
  23678. + retval = regulator_enable(rmi4_data->ibb_reg);
  23679. + if (retval < 0) {
  23680. + dev_err(rmi4_data->pdev->dev.parent,
  23681. + "%s: Failed to enable ibb regulator\n",
  23682. + __func__);
  23683. + return;
  23684. + }
  23685. +
  23686. + status |= DISP_REG_IBB;
  23687. + }
  23688. + } else {
  23689. + if (rmi4_data->ibb_reg && (flag & DISP_REG_IBB) && (status & DISP_REG_IBB)) {
  23690. + retval = regulator_disable(rmi4_data->ibb_reg);
  23691. + if (retval < 0) {
  23692. + dev_err(rmi4_data->pdev->dev.parent,
  23693. + "%s: Failed to disable ibb regulator\n",
  23694. + __func__);
  23695. + return;
  23696. + }
  23697. +
  23698. + status &= ~DISP_REG_IBB;
  23699. + }
  23700. +
  23701. + if (rmi4_data->lab_reg && (flag & DISP_REG_LAB) && (status & DISP_REG_LAB)) {
  23702. + retval = regulator_disable(rmi4_data->lab_reg);
  23703. + if (retval < 0) {
  23704. + dev_err(rmi4_data->pdev->dev.parent,
  23705. + "%s: Failed to disable lab regulator\n",
  23706. + __func__);
  23707. + return;
  23708. + }
  23709. +
  23710. + status &= ~DISP_REG_LAB;
  23711. + }
  23712. +
  23713. + if (rmi4_data->disp_reg && (flag & DISP_REG_VDD) && (status & DISP_REG_VDD)) {
  23714. + retval = regulator_disable(rmi4_data->disp_reg);
  23715. + if (retval < 0) {
  23716. + dev_err(rmi4_data->pdev->dev.parent,
  23717. + "%s: Failed to disable disp regulator\n",
  23718. + __func__);
  23719. + return;
  23720. + }
  23721. +
  23722. + status &= ~DISP_REG_VDD;
  23723. + }
  23724. + }
  23725. +}
  23726. +
  23727. +static void mdss_reset_ctrl(const struct synaptics_dsx_board_data *bdata, bool on)
  23728. +{
  23729. + if (!bdata->panel_is_incell)
  23730. + return;
  23731. +
  23732. + if (bdata->mdss_reset > 0) {
  23733. + if (on)
  23734. + gpio_set_value(bdata->mdss_reset, bdata->mdss_reset_state);
  23735. + else
  23736. + gpio_set_value(bdata->mdss_reset, !bdata->mdss_reset_state);
  23737. + }
  23738. +}
  23739. +
  23740. +#if 0
  23741. +static void mdss_panel_poweron(struct synaptics_rmi4_data *rmi4_data, bool enable)
  23742. +{
  23743. + if (!rmi4_data->hw_if->board_data->panel_is_incell)
  23744. + return;
  23745. +
  23746. + if (enable) {
  23747. +#if 0
  23748. + /*disp regulator always on, so do not control this regulator*/
  23749. + if (rmi4_data->panel_power_seq.disp_pre_on_sleep)
  23750. + msleep(rmi4_data->panel_power_seq.disp_pre_on_sleep);
  23751. + mdss_regulator_ctrl(rmi4_data, DISP_REG_VDD, true);
  23752. + if (rmi4_data->panel_power_seq.disp_post_on_sleep)
  23753. + msleep(rmi4_data->panel_power_seq.disp_post_on_sleep);
  23754. +#endif
  23755. + if (rmi4_data->panel_power_seq.lab_pre_on_sleep)
  23756. + msleep(rmi4_data->panel_power_seq.lab_pre_on_sleep);
  23757. + mdss_regulator_ctrl(rmi4_data, DISP_REG_LAB, true);
  23758. + if (rmi4_data->panel_power_seq.lab_post_on_sleep)
  23759. + msleep(rmi4_data->panel_power_seq.lab_post_on_sleep);
  23760. +
  23761. + if (rmi4_data->panel_power_seq.ibb_pre_on_sleep)
  23762. + msleep(rmi4_data->panel_power_seq.ibb_pre_on_sleep);
  23763. + mdss_regulator_ctrl(rmi4_data, DISP_REG_IBB, true);
  23764. + if (rmi4_data->panel_power_seq.ibb_post_on_sleep)
  23765. + msleep(rmi4_data->panel_power_seq.ibb_post_on_sleep);
  23766. + } else {
  23767. + if (rmi4_data->panel_power_seq.ibb_pre_off_sleep)
  23768. + msleep(rmi4_data->panel_power_seq.ibb_pre_off_sleep);
  23769. + mdss_regulator_ctrl(rmi4_data, DISP_REG_IBB, false);
  23770. + if (rmi4_data->panel_power_seq.ibb_post_off_sleep)
  23771. + msleep(rmi4_data->panel_power_seq.ibb_post_off_sleep);
  23772. +
  23773. + if (rmi4_data->panel_power_seq.lab_pre_off_sleep)
  23774. + msleep(rmi4_data->panel_power_seq.lab_pre_off_sleep);
  23775. + mdss_regulator_ctrl(rmi4_data, DISP_REG_LAB, false);
  23776. + if (rmi4_data->panel_power_seq.lab_post_off_sleep)
  23777. + msleep(rmi4_data->panel_power_seq.lab_post_off_sleep);
  23778. +#if 0
  23779. + /*disp regulator always on, so do not control this regulator*/
  23780. + if (rmi4_data->panel_power_seq.disp_pre_off_sleep)
  23781. + msleep(rmi4_data->panel_power_seq.disp_pre_off_sleep);
  23782. + mdss_regulator_ctrl(rmi4_data, DISP_REG_VDD, false);
  23783. + if (rmi4_data->panel_power_seq.disp_post_off_sleep)
  23784. + msleep(rmi4_data->panel_power_seq.disp_post_off_sleep);
  23785. +#endif
  23786. + }
  23787. + pr_debug("power %s seq:\n", enable ? "on" : "off");
  23788. +#if 0
  23789. + /*disp regulator always on, so do not control this regulator*/
  23790. + pr_debug("IOVDD: preonsleep=%d,postonsleep=%d,preoffsleep=%d,postoffsleep=%d\n",
  23791. + rmi4_data->panel_power_seq.disp_pre_on_sleep,
  23792. + rmi4_data->panel_power_seq.disp_post_on_sleep,
  23793. + rmi4_data->panel_power_seq.disp_pre_off_sleep,
  23794. + rmi4_data->panel_power_seq.disp_post_off_sleep);
  23795. +#endif
  23796. + pr_debug("LAB: preonsleep=%d,postonsleep=%d,preoffsleep=%d,postoffsleep=%d\n",
  23797. + rmi4_data->panel_power_seq.lab_pre_on_sleep,
  23798. + rmi4_data->panel_power_seq.lab_post_on_sleep,
  23799. + rmi4_data->panel_power_seq.lab_pre_off_sleep,
  23800. + rmi4_data->panel_power_seq.lab_post_off_sleep);
  23801. + pr_debug("IBB: preonsleep=%d,postonsleep=%d,preoffsleep=%d,postoffsleep=%d\n",
  23802. + rmi4_data->panel_power_seq.ibb_pre_on_sleep,
  23803. + rmi4_data->panel_power_seq.ibb_post_on_sleep,
  23804. + rmi4_data->panel_power_seq.ibb_pre_off_sleep,
  23805. + rmi4_data->panel_power_seq.ibb_post_off_sleep);
  23806. +}
  23807. +#endif
  23808. +
  23809. +static void mdss_reset_action(const struct synaptics_dsx_board_data *bdata)
  23810. +{
  23811. + if (bdata->mdss_reset > 0) {
  23812. + gpio_set_value(bdata->mdss_reset, !bdata->mdss_reset_state);
  23813. + msleep(10);
  23814. + gpio_set_value(bdata->mdss_reset, bdata->mdss_reset_state);
  23815. + msleep(10);
  23816. + }
  23817. +}
  23818. +
  23819. +static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data,
  23820. + bool enable)
  23821. +{
  23822. + int retval;
  23823. + unsigned char offset;
  23824. + unsigned char reporting_control[3];
  23825. + struct synaptics_rmi4_f12_extra_data *extra_data;
  23826. + struct synaptics_rmi4_fn *fhandler;
  23827. + struct synaptics_rmi4_device_info *rmi;
  23828. +
  23829. + rmi = &(rmi4_data->rmi4_mod_info);
  23830. +
  23831. + list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
  23832. + if (fhandler->fn_number == SYNAPTICS_RMI4_F12)
  23833. + break;
  23834. + }
  23835. +
  23836. + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
  23837. + offset = extra_data->ctrl20_offset;
  23838. +
  23839. + retval = synaptics_rmi4_reg_read(rmi4_data,
  23840. + fhandler->full_addr.ctrl_base + offset,
  23841. + reporting_control,
  23842. + sizeof(reporting_control));
  23843. + if (retval < 0) {
  23844. + dev_err(rmi4_data->pdev->dev.parent,
  23845. + "%s: Failed to change reporting mode\n",
  23846. + __func__);
  23847. + return;
  23848. + }
  23849. +
  23850. + if (enable)
  23851. + reporting_control[2] = F12_WAKEUP_GESTURE_MODE;
  23852. + else
  23853. + reporting_control[2] = F12_CONTINUOUS_MODE;
  23854. +
  23855. + retval = synaptics_rmi4_reg_write(rmi4_data,
  23856. + fhandler->full_addr.ctrl_base + offset,
  23857. + reporting_control,
  23858. + sizeof(reporting_control));
  23859. +
  23860. + if (retval < 0) {
  23861. + dev_err(rmi4_data->pdev->dev.parent,
  23862. + "%s: Failed to change reporting mode\n",
  23863. + __func__);
  23864. + return;
  23865. + }
  23866. +
  23867. + return;
  23868. +}
  23869. +
  23870. +static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data,
  23871. + bool enable)
  23872. +{
  23873. + if (rmi4_data->f11_wakeup_gesture)
  23874. + synaptics_rmi4_f11_wg(rmi4_data, enable);
  23875. + else if (rmi4_data->f12_wakeup_gesture)
  23876. + synaptics_rmi4_f12_wg(rmi4_data, enable);
  23877. +
  23878. + return;
  23879. +}
  23880. +
  23881. +#ifdef CONFIG_FB
  23882. +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self,
  23883. + unsigned long event, void *data)
  23884. +{
  23885. + int *transition;
  23886. + struct fb_event *evdata = data;
  23887. + struct synaptics_rmi4_data *rmi4_data =
  23888. + container_of(self, struct synaptics_rmi4_data,
  23889. + fb_notifier);
  23890. +
  23891. + const struct synaptics_dsx_board_data *bdata = NULL;
  23892. +
  23893. + if (rmi4_data->hw_if->board_data)
  23894. + bdata = rmi4_data->hw_if->board_data;
  23895. + else
  23896. + return 0;
  23897. +
  23898. + /* Receive notifications from primary panel only */
  23899. + if (evdata && evdata->data && rmi4_data && mdss_panel_is_prim(evdata->info)) {
  23900. + if (event == FB_EVENT_BLANK) {
  23901. + transition = evdata->data;
  23902. + if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
  23903. + synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
  23904. + rmi4_data->fb_ready = false;
  23905. + } else if ((*transition == FB_BLANK_UNBLANK) || (*transition == FB_BLANK_NORMAL)) {
  23906. + synaptics_rmi4_resume(&rmi4_data->pdev->dev);
  23907. + rmi4_data->fb_ready = true;
  23908. + if (rmi4_data->wakeup_en) {
  23909. + mdss_panel_reset_skip_enable(false);
  23910. + mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, false);
  23911. + rmi4_data->wakeup_en = false;
  23912. + }
  23913. +
  23914. + rmi4_data->disable_data_dump = false;
  23915. + }
  23916. + } else if (event == FB_EARLY_EVENT_BLANK) {
  23917. + transition = evdata->data;
  23918. + if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
  23919. + rmi4_data->disable_data_dump = true;
  23920. + if (rmi4_data->dump_flags) {
  23921. + reinit_completion(&rmi4_data->dump_completion);
  23922. + wait_for_completion_timeout(&rmi4_data->dump_completion, 4 * HZ);
  23923. + }
  23924. +
  23925. + if (rmi4_data->enable_wakeup_gesture) {
  23926. + rmi4_data->wakeup_en = true;
  23927. + mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, true);
  23928. + mdss_panel_reset_skip_enable(true);
  23929. + }
  23930. + } else if ((*transition == FB_BLANK_UNBLANK) || (*transition == FB_BLANK_NORMAL)) {
  23931. + if (bdata->reset_gpio >= 0 && rmi4_data->suspend) {
  23932. + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
  23933. + msleep(bdata->reset_active_ms);
  23934. + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
  23935. + }
  23936. + if (rmi4_data->wakeup_en) {
  23937. + mdss_reset_action(bdata);
  23938. + }
  23939. + }
  23940. + }
  23941. + }
  23942. +
  23943. + return 0;
  23944. +}
  23945. +
  23946. +static int synaptics_rmi4_fb_notifier_cb_tddi(struct notifier_block *self,
  23947. + unsigned long event, void *data)
  23948. +{
  23949. + int *transition;
  23950. + struct fb_event *evdata = data;
  23951. + struct synaptics_rmi4_data *rmi4_data =
  23952. + container_of(self, struct synaptics_rmi4_data,
  23953. + fb_notifier);
  23954. +
  23955. + if (mdss_prim_panel_is_dead())
  23956. + return 0;
  23957. +
  23958. + /* Receive notifications from primary panel only */
  23959. + if (evdata && evdata->data && rmi4_data && mdss_panel_is_prim(evdata->info)) {
  23960. + if (event == FB_EVENT_BLANK) {
  23961. + transition = evdata->data;
  23962. + if ((*transition == FB_BLANK_UNBLANK) || (*transition == FB_BLANK_NORMAL)) {
  23963. + if (rmi4_data->wakeup_en) {
  23964. + mdss_panel_reset_skip_enable(false);
  23965. + mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, false);
  23966. + rmi4_data->wakeup_en = false;
  23967. + } else {
  23968. + synaptics_rmi4_resume(&rmi4_data->pdev->dev);
  23969. + rmi4_data->fb_ready = true;
  23970. + }
  23971. +
  23972. + rmi4_data->disable_data_dump = false;
  23973. + } else if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
  23974. + if (rmi4_data->wakeup_en) {
  23975. + synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
  23976. + rmi4_data->fb_ready = true;
  23977. + }
  23978. + }
  23979. + } else if (event == FB_EARLY_EVENT_BLANK) {
  23980. + transition = evdata->data;
  23981. + if (*transition == FB_BLANK_UNBLANK) {
  23982. + if (rmi4_data->wakeup_en) {
  23983. + synaptics_rmi4_resume(&rmi4_data->pdev->dev);
  23984. + rmi4_data->fb_ready = true;
  23985. + msleep(30);
  23986. + }
  23987. + } else if ((*transition == FB_BLANK_POWERDOWN) || (*transition == FB_BLANK_NORMAL)) {
  23988. + rmi4_data->disable_data_dump = true;
  23989. + if (rmi4_data->dump_flags) {
  23990. + reinit_completion(&rmi4_data->dump_completion);
  23991. + wait_for_completion_timeout(&rmi4_data->dump_completion, 4 * HZ);
  23992. + }
  23993. +
  23994. + if (rmi4_data->enable_wakeup_gesture) {
  23995. + rmi4_data->wakeup_en = true;
  23996. + mdss_panel_reset_skip_enable(true);
  23997. + mdss_regulator_ctrl(rmi4_data, DISP_REG_ALL, true);
  23998. + }
  23999. +
  24000. + if (!rmi4_data->wakeup_en) {
  24001. + synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
  24002. + rmi4_data->fb_ready = false;
  24003. + }
  24004. + }
  24005. + }
  24006. + }
  24007. +
  24008. + return 0;
  24009. +}
  24010. +#endif
  24011. +
  24012. +#ifdef USE_EARLYSUSPEND
  24013. +static void synaptics_rmi4_early_suspend(struct early_suspend *h)
  24014. +{
  24015. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  24016. + struct synaptics_rmi4_data *rmi4_data =
  24017. + container_of(h, struct synaptics_rmi4_data,
  24018. + early_suspend);
  24019. +
  24020. + if (rmi4_data->stay_awake)
  24021. + return;
  24022. +
  24023. + if (rmi4_data->enable_wakeup_gesture) {
  24024. + synaptics_rmi4_wakeup_gesture(rmi4_data, true);
  24025. + enable_irq_wake(rmi4_data->irq);
  24026. + goto exit;
  24027. + }
  24028. +
  24029. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  24030. + synaptics_rmi4_sleep_enable(rmi4_data, true);
  24031. + synaptics_rmi4_free_fingers(rmi4_data);
  24032. +
  24033. +exit:
  24034. + mutex_lock(&exp_data.mutex);
  24035. + if (!list_empty(&exp_data.list)) {
  24036. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  24037. + if (exp_fhandler->exp_fn->early_suspend != NULL)
  24038. + exp_fhandler->exp_fn->early_suspend(rmi4_data);
  24039. + }
  24040. + mutex_unlock(&exp_data.mutex);
  24041. +
  24042. + rmi4_data->suspend = true;
  24043. +
  24044. + return;
  24045. +}
  24046. +
  24047. +static void synaptics_rmi4_late_resume(struct early_suspend *h)
  24048. +{
  24049. +#ifdef FB_READY_RESET
  24050. + int retval;
  24051. +#endif
  24052. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  24053. + struct synaptics_rmi4_data *rmi4_data =
  24054. + container_of(h, struct synaptics_rmi4_data,
  24055. + early_suspend);
  24056. +
  24057. + if (rmi4_data->stay_awake)
  24058. + return;
  24059. +
  24060. + if (rmi4_data->enable_wakeup_gesture) {
  24061. + synaptics_rmi4_wakeup_gesture(rmi4_data, false);
  24062. + disable_irq_wake(rmi4_data->irq);
  24063. + goto exit;
  24064. + }
  24065. +
  24066. + rmi4_data->current_page = MASK_8BIT;
  24067. +
  24068. + if (rmi4_data->suspend) {
  24069. + synaptics_rmi4_sleep_enable(rmi4_data, false);
  24070. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  24071. + }
  24072. +
  24073. +exit:
  24074. +#ifdef FB_READY_RESET
  24075. + if (rmi4_data->suspend) {
  24076. + retval = synaptics_rmi4_reset_device(rmi4_data, false);
  24077. + if (retval < 0) {
  24078. + dev_err(rmi4_data->pdev->dev.parent,
  24079. + "%s: Failed to issue reset command\n",
  24080. + __func__);
  24081. + }
  24082. + }
  24083. +#endif
  24084. + mutex_lock(&exp_data.mutex);
  24085. + if (!list_empty(&exp_data.list)) {
  24086. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  24087. + if (exp_fhandler->exp_fn->late_resume != NULL)
  24088. + exp_fhandler->exp_fn->late_resume(rmi4_data);
  24089. + }
  24090. + mutex_unlock(&exp_data.mutex);
  24091. +
  24092. + rmi4_data->suspend = false;
  24093. +
  24094. + return;
  24095. +}
  24096. +#endif
  24097. +
  24098. +static int synaptics_rmi4_suspend(struct device *dev)
  24099. +{
  24100. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  24101. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  24102. + const struct synaptics_dsx_board_data *bdata =
  24103. + rmi4_data->hw_if->board_data;
  24104. +
  24105. + if (rmi4_data->stay_awake || rmi4_data->suspend)
  24106. + return 0;
  24107. +
  24108. + if (bdata->cut_off_power || (rmi4_data->chip_is_tddi && !rmi4_data->wakeup_en)) {
  24109. + if (rmi4_data->fw_updating)
  24110. + return 0;
  24111. +
  24112. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  24113. +
  24114. + if (bdata->power_gpio >= 0)
  24115. + gpio_set_value(bdata->power_gpio,
  24116. + !bdata->power_on_state);
  24117. +
  24118. + if (bdata->reset_gpio >= 0) {
  24119. + gpio_set_value(bdata->reset_gpio,
  24120. + bdata->reset_on_state);
  24121. + mdelay(bdata->reset_active_ms);
  24122. + }
  24123. +
  24124. + synaptics_rmi4_enable_reg(rmi4_data, false);
  24125. + } else {
  24126. + synaptics_secure_touch_stop(rmi4_data, 1);
  24127. +
  24128. + synaptics_rmi4_irq_enable(rmi4_data, false, false);
  24129. +
  24130. + if (!rmi4_data->wakeup_en)
  24131. + synaptics_rmi4_sleep_enable(rmi4_data, true);
  24132. + else {
  24133. + if (!rmi4_data->chip_is_tddi)
  24134. + msleep(300);
  24135. + else
  24136. + msleep(120);
  24137. + synaptics_rmi4_wakeup_gesture(rmi4_data, true);
  24138. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  24139. + goto exit;
  24140. + }
  24141. +
  24142. + mutex_lock(&exp_data.mutex);
  24143. + if (!list_empty(&exp_data.list)) {
  24144. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  24145. + if (exp_fhandler->exp_fn->suspend != NULL)
  24146. + exp_fhandler->exp_fn->suspend(rmi4_data);
  24147. + }
  24148. + mutex_unlock(&exp_data.mutex);
  24149. + }
  24150. +
  24151. +exit:
  24152. + synaptics_rmi4_free_fingers(rmi4_data);
  24153. +
  24154. + rmi4_data->suspend = true;
  24155. +
  24156. + return 0;
  24157. +}
  24158. +
  24159. +static int synaptics_rmi4_resume(struct device *dev)
  24160. +{
  24161. +#ifdef FB_READY_RESET
  24162. + int retval;
  24163. +#endif
  24164. + struct synaptics_rmi4_exp_fhandler *exp_fhandler;
  24165. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  24166. + const struct synaptics_dsx_board_data *bdata =
  24167. + rmi4_data->hw_if->board_data;
  24168. +
  24169. +#ifdef CONFIG_FB
  24170. + static int skip = 0;
  24171. +
  24172. + if (skip == 0) {
  24173. + skip = 1;
  24174. + return 0;
  24175. + }
  24176. +#endif
  24177. +
  24178. + if (rmi4_data->stay_awake || !rmi4_data->suspend)
  24179. + return 0;
  24180. +
  24181. + if (bdata->cut_off_power || (rmi4_data->chip_is_tddi && !rmi4_data->wakeup_en)) {
  24182. + synaptics_rmi4_enable_reg(rmi4_data, true);
  24183. +
  24184. + if (bdata->power_gpio >= 0) {
  24185. + gpio_set_value(bdata->power_gpio,
  24186. + bdata->power_on_state);
  24187. + mdelay(bdata->power_delay_ms);
  24188. + }
  24189. +
  24190. + if (bdata->reset_gpio >= 0) {
  24191. + gpio_set_value(bdata->reset_gpio,
  24192. + !bdata->reset_on_state);
  24193. + mdelay(bdata->reset_delay_ms);
  24194. + }
  24195. +
  24196. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  24197. + } else {
  24198. + synaptics_secure_touch_stop(rmi4_data, 0);
  24199. +
  24200. + if (rmi4_data->wakeup_en) {
  24201. + synaptics_rmi4_wakeup_gesture(rmi4_data, false);
  24202. + } else {
  24203. + rmi4_data->current_page = MASK_8BIT;
  24204. +
  24205. + synaptics_rmi4_sleep_enable(rmi4_data, false);
  24206. + synaptics_rmi4_irq_enable(rmi4_data, true, false);
  24207. +
  24208. +#ifdef FB_READY_RESET
  24209. + retval = synaptics_rmi4_reset_device(rmi4_data, false);
  24210. + if (retval < 0) {
  24211. + dev_err(rmi4_data->pdev->dev.parent,
  24212. + "%s: Failed to issue reset command\n",
  24213. + __func__);
  24214. + }
  24215. +#endif
  24216. + mutex_lock(&exp_data.mutex);
  24217. + if (!list_empty(&exp_data.list)) {
  24218. + list_for_each_entry(exp_fhandler, &exp_data.list, link)
  24219. + if (exp_fhandler->exp_fn->resume != NULL)
  24220. + exp_fhandler->exp_fn->resume(rmi4_data);
  24221. + }
  24222. + mutex_unlock(&exp_data.mutex);
  24223. + }
  24224. + }
  24225. +
  24226. + if (rmi4_data->enable_cover_mode)
  24227. + cover_mode_set(rmi4_data, rmi4_data->enable_cover_mode);
  24228. +
  24229. + rmi4_data->suspend = false;
  24230. +
  24231. + return 0;
  24232. +}
  24233. +
  24234. +#ifdef CONFIG_PM
  24235. +static int synaptics_rmi4_pm_suspend(struct device *dev)
  24236. +{
  24237. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  24238. + const struct synaptics_dsx_board_data *bdata =
  24239. + rmi4_data->hw_if->board_data;
  24240. +
  24241. + if (device_may_wakeup(dev) &&
  24242. + rmi4_data->wakeup_en &&
  24243. + !bdata->cut_off_power) {
  24244. + dev_info(rmi4_data->pdev->dev.parent,
  24245. + "Enable touch irq wake\n");
  24246. + disable_irq(rmi4_data->irq);
  24247. + enable_irq_wake(rmi4_data->irq);
  24248. + }
  24249. +
  24250. + return 0;
  24251. +
  24252. +}
  24253. +
  24254. +static int synaptics_rmi4_pm_resume(struct device *dev)
  24255. +{
  24256. + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
  24257. + const struct synaptics_dsx_board_data *bdata =
  24258. + rmi4_data->hw_if->board_data;
  24259. +
  24260. + if (device_may_wakeup(dev) &&
  24261. + rmi4_data->wakeup_en &&
  24262. + !bdata->cut_off_power) {
  24263. + dev_info(rmi4_data->pdev->dev.parent,
  24264. + "Disable touch irq wake\n");
  24265. + disable_irq_wake(rmi4_data->irq);
  24266. + enable_irq(rmi4_data->irq);
  24267. + }
  24268. +
  24269. + return 0;
  24270. +}
  24271. +
  24272. +static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = {
  24273. + .suspend = synaptics_rmi4_pm_suspend,
  24274. + .resume = synaptics_rmi4_pm_resume,
  24275. +};
  24276. +#endif
  24277. +
  24278. +static struct platform_driver synaptics_rmi4_driver = {
  24279. + .driver = {
  24280. + .name = PLATFORM_DRIVER_FORCE,
  24281. + .owner = THIS_MODULE,
  24282. +#ifdef CONFIG_PM
  24283. + .pm = &synaptics_rmi4_dev_pm_ops,
  24284. +#endif
  24285. + },
  24286. + .probe = synaptics_rmi4_probe,
  24287. + .remove = synaptics_rmi4_remove,
  24288. +};
  24289. +
  24290. +static int __init synaptics_rmi4_init(void)
  24291. +{
  24292. + int retval;
  24293. +
  24294. + retval = synaptics_rmi4_bus_init_force();
  24295. + if (retval)
  24296. + return retval;
  24297. +
  24298. + return platform_driver_register(&synaptics_rmi4_driver);
  24299. +}
  24300. +
  24301. +static void __exit synaptics_rmi4_exit(void)
  24302. +{
  24303. + platform_driver_unregister(&synaptics_rmi4_driver);
  24304. +
  24305. + synaptics_rmi4_bus_exit_force();
  24306. +
  24307. + return;
  24308. +}
  24309. +
  24310. +module_init(synaptics_rmi4_init);
  24311. +module_exit(synaptics_rmi4_exit);
  24312. +
  24313. +MODULE_AUTHOR("Synaptics, Inc.");
  24314. +MODULE_DESCRIPTION("Synaptics DSX Touch Driver");
  24315. +MODULE_LICENSE("GPL v2");
  24316. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.h
  24317. new file mode 100644
  24318. index 0000000..20298d8
  24319. --- /dev/null
  24320. +++ b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_core.h
  24321. @@ -0,0 +1,541 @@
  24322. +/*
  24323. + * Synaptics DSX touchscreen driver
  24324. + *
  24325. + * Copyright (C) 2012-2015 Synaptics Incorporated. All rights reserved.
  24326. + *
  24327. + * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
  24328. + * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
  24329. + * Copyright (C) 2017 XiaoMi, Inc.
  24330. + *
  24331. + * This program is free software; you can redistribute it and/or modify
  24332. + * it under the terms of the GNU General Public License as published by
  24333. + * the Free Software Foundation; either version 2 of the License, or
  24334. + * (at your option) any later version.
  24335. + *
  24336. + * This program is distributed in the hope that it will be useful,
  24337. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24338. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24339. + * GNU General Public License for more details.
  24340. + *
  24341. + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  24342. + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  24343. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  24344. + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  24345. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24346. + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  24347. + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  24348. + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24349. + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  24350. + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  24351. + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  24352. + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  24353. + * DOLLARS.
  24354. + */
  24355. +
  24356. +#ifndef _SYNAPTICS_DSX_RMI4_H_
  24357. +#define _SYNAPTICS_DSX_RMI4_H_
  24358. +
  24359. +#define SYNAPTICS_DS4 (1 << 0)
  24360. +#define SYNAPTICS_DS5 (1 << 1)
  24361. +#define SYNAPTICS_DSX_DRIVER_PRODUCT (SYNAPTICS_DS4 | SYNAPTICS_DS5)
  24362. +#define SYNAPTICS_DSX_DRIVER_VERSION 0x2065
  24363. +
  24364. +#include <linux/version.h>
  24365. +#ifdef CONFIG_FB
  24366. +#include <linux/notifier.h>
  24367. +#include <linux/fb.h>
  24368. +#endif
  24369. +#ifdef CONFIG_HAS_EARLYSUSPEND
  24370. +#include <linux/earlysuspend.h>
  24371. +#endif
  24372. +
  24373. +#if defined(CONFIG_SECURE_TOUCH)
  24374. +#include <linux/completion.h>
  24375. +#include <linux/atomic.h>
  24376. +#include <linux/clk.h>
  24377. +#endif
  24378. +
  24379. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
  24380. +#define KERNEL_ABOVE_2_6_38
  24381. +#endif
  24382. +
  24383. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
  24384. +#define KERNEL_ABOVE_3_6
  24385. +#endif
  24386. +
  24387. +#ifdef KERNEL_ABOVE_2_6_38
  24388. +#define sstrtoul(...) kstrtoul(__VA_ARGS__)
  24389. +#else
  24390. +#define sstrtoul(...) strict_strtoul(__VA_ARGS__)
  24391. +#endif
  24392. +
  24393. +#define PDT_PROPS (0X00EF)
  24394. +#define PDT_START (0x00E9)
  24395. +#define PDT_END (0x00D0)
  24396. +#define PDT_ENTRY_SIZE (0x0006)
  24397. +#define PAGES_TO_SERVICE (10)
  24398. +#define PAGE_SELECT_LEN (2)
  24399. +#define ADDRESS_LEN (2)
  24400. +
  24401. +#define SYNAPTICS_RMI4_F01 (0x01)
  24402. +#define SYNAPTICS_RMI4_F11 (0x11)
  24403. +#define SYNAPTICS_RMI4_F12 (0x12)
  24404. +#define SYNAPTICS_RMI4_F1A (0x1A)
  24405. +#define SYNAPTICS_RMI4_F34 (0x34)
  24406. +#define SYNAPTICS_RMI4_F35 (0x35)
  24407. +#define SYNAPTICS_RMI4_F38 (0x38)
  24408. +#define SYNAPTICS_RMI4_F51 (0x51)
  24409. +#define SYNAPTICS_RMI4_F54 (0x54)
  24410. +#define SYNAPTICS_RMI4_F55 (0x55)
  24411. +#define SYNAPTICS_RMI4_FDB (0xDB)
  24412. +
  24413. +#define PRODUCT_INFO_SIZE 2
  24414. +#define PRODUCT_ID_SIZE 10
  24415. +#define BUILD_ID_SIZE 3
  24416. +#define LOCKDOWN_INFO_SIZE 8
  24417. +
  24418. +#define F12_FINGERS_TO_SUPPORT 10
  24419. +#define F12_NO_OBJECT_STATUS 0x00
  24420. +#define F12_FINGER_STATUS 0x01
  24421. +#define F12_ACTIVE_STYLUS_STATUS 0x02
  24422. +#define F12_PALM_STATUS 0x03
  24423. +#define F12_HOVERING_FINGER_STATUS 0x05
  24424. +#define F12_GLOVED_FINGER_STATUS 0x06
  24425. +#define F12_NARROW_OBJECT_STATUS 0x07
  24426. +#define F12_HAND_EDGE_STATUS 0x08
  24427. +#define F12_COVER_STATUS 0x0A
  24428. +#define F12_STYLUS_STATUS 0x0B
  24429. +#define F12_ERASER_STATUS 0x0C
  24430. +#define F12_SMALL_OBJECT_STATUS 0x0D
  24431. +
  24432. +#define F12_GESTURE_DETECTION_LEN 5
  24433. +
  24434. +#define MAX_NUMBER_OF_BUTTONS 4
  24435. +#define MAX_INTR_REGISTERS 4
  24436. +
  24437. +#define MASK_16BIT 0xFFFF
  24438. +#define MASK_8BIT 0xFF
  24439. +#define MASK_7BIT 0x7F
  24440. +#define MASK_6BIT 0x3F
  24441. +#define MASK_5BIT 0x1F
  24442. +#define MASK_4BIT 0x0F
  24443. +#define MASK_3BIT 0x07
  24444. +#define MASK_2BIT 0x03
  24445. +#define MASK_1BIT 0x01
  24446. +
  24447. +#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
  24448. +#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
  24449. +
  24450. +
  24451. +enum exp_fn {
  24452. + RMI_DEV = 0,
  24453. + RMI_FW_UPDATER,
  24454. + RMI_TEST_REPORTING,
  24455. + RMI_PROXIMITY,
  24456. + RMI_ACTIVE_PEN,
  24457. + RMI_GESTURE,
  24458. + RMI_VIDEO,
  24459. + RMI_DEBUG,
  24460. + RMI_LAST,
  24461. +};
  24462. +
  24463. +/*
  24464. + * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT entry
  24465. + * @query_base_addr: base address for query registers
  24466. + * @cmd_base_addr: base address for command registers
  24467. + * @ctrl_base_addr: base address for control registers
  24468. + * @data_base_addr: base address for data registers
  24469. + * @intr_src_count: number of interrupt sources
  24470. + * @fn_version: version of function
  24471. + * @fn_number: function number
  24472. + */
  24473. +struct synaptics_rmi4_fn_desc {
  24474. + union {
  24475. + struct {
  24476. + unsigned char query_base_addr;
  24477. + unsigned char cmd_base_addr;
  24478. + unsigned char ctrl_base_addr;
  24479. + unsigned char data_base_addr;
  24480. + unsigned char intr_src_count:3;
  24481. + unsigned char reserved_1:2;
  24482. + unsigned char fn_version:2;
  24483. + unsigned char reserved_2:1;
  24484. + unsigned char fn_number;
  24485. + } __packed;
  24486. + unsigned char data[6];
  24487. + };
  24488. +};
  24489. +
  24490. +/*
  24491. + * synaptics_rmi4_fn_full_addr - full 16-bit base addresses
  24492. + * @query_base: 16-bit base address for query registers
  24493. + * @cmd_base: 16-bit base address for command registers
  24494. + * @ctrl_base: 16-bit base address for control registers
  24495. + * @data_base: 16-bit base address for data registers
  24496. + */
  24497. +struct synaptics_rmi4_fn_full_addr {
  24498. + unsigned short query_base;
  24499. + unsigned short cmd_base;
  24500. + unsigned short ctrl_base;
  24501. + unsigned short data_base;
  24502. +};
  24503. +
  24504. +/*
  24505. + * struct synaptics_rmi4_f11_extra_data - extra data of F$11
  24506. + * @data38_offset: offset to F11_2D_DATA38 register
  24507. + */
  24508. +struct synaptics_rmi4_f11_extra_data {
  24509. + unsigned char data38_offset;
  24510. +};
  24511. +
  24512. +/*
  24513. + * struct synaptics_rmi4_f12_extra_data - extra data of F$12
  24514. + * @data1_offset: offset to F12_2D_DATA01 register
  24515. + * @data4_offset: offset to F12_2D_DATA04 register
  24516. + * @data15_offset: offset to F12_2D_DATA15 register
  24517. + * @data15_size: size of F12_2D_DATA15 register
  24518. + * @data15_data: buffer for reading F12_2D_DATA15 register
  24519. + * @data29_offset: offset to F12_2D_DATA29 register
  24520. + * @data29_size: size of F12_2D_DATA29 register
  24521. + * @data29_data: buffer for reading F12_2D_DATA29 register
  24522. + * @ctrl20_offset: offset to F12_2D_CTRL20 register
  24523. + */
  24524. +struct synaptics_rmi4_f12_extra_data {
  24525. + unsigned char data1_offset;
  24526. + unsigned char data4_offset;
  24527. + unsigned char data15_offset;
  24528. + unsigned char data15_size;
  24529. + unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8];
  24530. + unsigned char data29_offset;
  24531. + unsigned char data29_size;
  24532. + unsigned char data29_data[F12_FINGERS_TO_SUPPORT * 2];
  24533. + unsigned char ctrl20_offset;
  24534. + unsigned char ctrl26_offset;
  24535. + unsigned char ctrl27_offset;
  24536. +};
  24537. +
  24538. +/*
  24539. + * struct synaptics_rmi4_fn - RMI function handler
  24540. + * @fn_number: function number
  24541. + * @num_of_data_sources: number of data sources
  24542. + * @num_of_data_points: maximum number of fingers supported
  24543. + * @intr_reg_num: index to associated interrupt register
  24544. + * @intr_mask: interrupt mask
  24545. + * @full_addr: full 16-bit base addresses of function registers
  24546. + * @link: linked list for function handlers
  24547. + * @data_size: size of private data
  24548. + * @data: pointer to private data
  24549. + * @extra: pointer to extra data
  24550. + */
  24551. +struct synaptics_rmi4_fn {
  24552. + unsigned char fn_number;
  24553. + unsigned char num_of_data_sources;
  24554. + unsigned char num_of_data_points;
  24555. + unsigned char intr_reg_num;
  24556. + unsigned char intr_mask;
  24557. + struct synaptics_rmi4_fn_full_addr full_addr;
  24558. + struct list_head link;
  24559. + int data_size;
  24560. + void *data;
  24561. + void *extra;
  24562. +};
  24563. +
  24564. +/*
  24565. + * struct synaptics_rmi4_device_info - device information
  24566. + * @version_major: RMI protocol major version number
  24567. + * @version_minor: RMI protocol minor version number
  24568. + * @manufacturer_id: manufacturer ID
  24569. + * @product_props: product properties
  24570. + * @product_info: product information
  24571. + * @product_id_string: product ID
  24572. + * @build_id: firmware build ID
  24573. + * @support_fn_list: linked list for function handlers
  24574. + */
  24575. +struct synaptics_rmi4_device_info {
  24576. + unsigned int version_major;
  24577. + unsigned int version_minor;
  24578. + unsigned char manufacturer_id;
  24579. + unsigned char product_props;
  24580. + unsigned char product_info[PRODUCT_INFO_SIZE];
  24581. + unsigned char product_id_string[PRODUCT_ID_SIZE + 1];
  24582. + unsigned char build_id[BUILD_ID_SIZE];
  24583. + struct list_head support_fn_list;
  24584. +};
  24585. +
  24586. +/*
  24587. + * struct synaptics_rmi4_data - RMI4 device instance data
  24588. + * @pdev: pointer to platform device
  24589. + * @input_dev: pointer to associated input device
  24590. + * @stylus_dev: pointer to associated stylus device
  24591. + * @hw_if: pointer to hardware interface data
  24592. + * @rmi4_mod_info: device information
  24593. + * @board_prop_dir: /sys/board_properties directory for virtual key map file
  24594. + * @pwr_reg: pointer to regulator for power control
  24595. + * @lab_reg: pointer to regulator for LCD lab control
  24596. + * @ibb_reg: pointer to regulator for LCD ibb control
  24597. + * @disp_reg: pointer to regulator for LCD disp control
  24598. + * @bus_reg: pointer to regulator for bus pullup control
  24599. + * @rmi4_reset_mutex: mutex for software reset
  24600. + * @rmi4_report_mutex: mutex for input event reporting
  24601. + * @rmi4_io_ctrl_mutex: mutex for communication interface I/O
  24602. + * @rmi4_exp_init_mutex: mutex for expansion function module initialization
  24603. + * @rmi4_irq_enable_mutex: mutex for enabling/disabling interrupt
  24604. + * @rb_work: work for rebuilding input device
  24605. + * @rb_workqueue: workqueue for rebuilding input device
  24606. + * @fb_notifier: framebuffer notifier client
  24607. + * @reset_work: work for issuing reset after display framebuffer ready
  24608. + * @reset_workqueue: workqueue for issuing reset after display framebuffer ready
  24609. + * @early_suspend: early suspend power management
  24610. + * @current_page: current RMI page for register access
  24611. + * @button_0d_enabled: switch for enabling 0d button support
  24612. + * @num_of_tx: number of Tx channels for 2D touch
  24613. + * @num_of_rx: number of Rx channels for 2D touch
  24614. + * @num_of_fingers: maximum number of fingers for 2D touch
  24615. + * @max_touch_width: maximum touch width
  24616. + * @report_enable: input data to report for F$12
  24617. + * @no_sleep_setting: default setting of NoSleep in F01_RMI_CTRL00 register
  24618. + * @gesture_detection: detected gesture type and properties
  24619. + * @intr_mask: interrupt enable mask
  24620. + * @button_txrx_mapping: Tx Rx mapping of 0D buttons
  24621. + * @num_of_intr_regs: number of interrupt registers
  24622. + * @f01_query_base_addr: query base address for f$01
  24623. + * @f01_cmd_base_addr: command base address for f$01
  24624. + * @f01_ctrl_base_addr: control base address for f$01
  24625. + * @f01_data_base_addr: data base address for f$01
  24626. + * @firmware_id: firmware build ID
  24627. + * @irq: attention interrupt
  24628. + * @sensor_max_x: maximum x coordinate for 2D touch
  24629. + * @sensor_max_y: maximum y coordinate for 2D touch
  24630. + * @flash_prog_mode: flag to indicate flash programming mode status
  24631. + * @irq_enabled: flag to indicate attention interrupt enable status
  24632. + * @fingers_on_2d: flag to indicate presence of fingers in 2D area
  24633. + * @suspend: flag to indicate whether in suspend state
  24634. + * @sensor_sleep: flag to indicate sleep state of sensor
  24635. + * @stay_awake: flag to indicate whether to stay awake during suspend
  24636. + * @fb_ready: flag to indicate whether display framebuffer in ready state
  24637. + * @f11_wakeup_gesture: flag to indicate support for wakeup gestures in F$11
  24638. + * @f12_wakeup_gesture: flag to indicate support for wakeup gestures in F$12
  24639. + * @enable_wakeup_gesture: flag to indicate usage of wakeup gestures
  24640. + * @wedge_sensor: flag to indicate use of wedge sensor
  24641. + * @report_pressure: flag to indicate reporting of pressure data
  24642. + * @stylus_enable: flag to indicate reporting of stylus data
  24643. + * @eraser_enable: flag to indicate reporting of eraser data
  24644. + * @external_afe_buttons: flag to indicate presence of external AFE buttons
  24645. + * @reset_device: pointer to device reset function
  24646. + * @irq_enable: pointer to interrupt enable function
  24647. + * @sleep_enable: pointer to sleep enable function
  24648. + * @report_touch: pointer to touch reporting function
  24649. + */
  24650. +struct synaptics_rmi4_data {
  24651. + struct platform_device *pdev;
  24652. + struct input_dev *input_dev;
  24653. + struct input_dev *stylus_dev;
  24654. + const struct synaptics_dsx_hw_interface *hw_if;
  24655. + struct synaptics_rmi4_device_info rmi4_mod_info;
  24656. + struct kobject *board_prop_dir;
  24657. + struct regulator *pwr_reg;
  24658. + struct regulator *lab_reg;
  24659. + struct regulator *ibb_reg;
  24660. + struct regulator *disp_reg;
  24661. + struct regulator *bus_reg;
  24662. + struct mutex rmi4_reset_mutex;
  24663. + struct mutex rmi4_report_mutex;
  24664. + struct mutex rmi4_io_ctrl_mutex;
  24665. + struct mutex rmi4_exp_init_mutex;
  24666. + struct mutex rmi4_cover_mutex;
  24667. + struct mutex rmi4_irq_enable_mutex;
  24668. + struct delayed_work rb_work;
  24669. + struct workqueue_struct *rb_workqueue;
  24670. + struct synaptics_dsx_panel_power_seq panel_power_seq;
  24671. +#ifdef CONFIG_FB
  24672. + struct notifier_block fb_notifier;
  24673. + struct work_struct reset_work;
  24674. + struct workqueue_struct *reset_workqueue;
  24675. +#endif
  24676. +#ifdef CONFIG_HAS_EARLYSUSPEND
  24677. + struct early_suspend early_suspend;
  24678. +#endif
  24679. + unsigned char current_page;
  24680. + unsigned char button_0d_enabled;
  24681. + unsigned char num_of_tx;
  24682. + unsigned char num_of_rx;
  24683. + unsigned char num_of_fingers;
  24684. + unsigned char max_touch_width;
  24685. + unsigned char report_enable;
  24686. + unsigned char no_sleep_setting;
  24687. + unsigned char gesture_detection[F12_GESTURE_DETECTION_LEN];
  24688. + unsigned char intr_mask[MAX_INTR_REGISTERS];
  24689. + unsigned char *button_txrx_mapping;
  24690. + unsigned short num_of_intr_regs;
  24691. + unsigned short f01_query_base_addr;
  24692. + unsigned short f01_cmd_base_addr;
  24693. + unsigned short f01_ctrl_base_addr;
  24694. + unsigned short f01_data_base_addr;
  24695. +#ifdef F51_DISCRETE_FORCE
  24696. + unsigned short f51_query_base_addr;
  24697. +#endif
  24698. + unsigned int hw_version;
  24699. + unsigned int firmware_id;
  24700. + unsigned char lockdown_info[LOCKDOWN_INFO_SIZE];
  24701. + unsigned char valid_button_count;
  24702. + int irq;
  24703. + int sensor_max_x;
  24704. + int sensor_max_y;
  24705. + int force_min;
  24706. + int force_max;
  24707. + int chip_id;
  24708. + int touchs;
  24709. + bool flash_prog_mode;
  24710. + bool irq_enabled;
  24711. + bool fingers_on_2d;
  24712. + bool suspend;
  24713. + bool sensor_sleep;
  24714. + bool stay_awake;
  24715. + bool fb_ready;
  24716. + bool f11_wakeup_gesture;
  24717. + bool f12_wakeup_gesture;
  24718. + bool enable_wakeup_gesture;
  24719. + bool enable_cover_mode;
  24720. + bool wedge_sensor;
  24721. + bool report_pressure;
  24722. + bool stylus_enable;
  24723. + bool eraser_enable;
  24724. + bool external_afe_buttons;
  24725. + bool fw_updating;
  24726. + bool wakeup_en;
  24727. + bool chip_is_tddi;
  24728. + bool disable_data_dump;
  24729. + bool dump_flags;
  24730. + int (*reset_device)(struct synaptics_rmi4_data *rmi4_data,
  24731. + bool rebuild);
  24732. + int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable,
  24733. + bool attn_only);
  24734. + void (*sleep_enable)(struct synaptics_rmi4_data *rmi4_data,
  24735. + bool enable);
  24736. + void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
  24737. + struct synaptics_rmi4_fn *fhandler);
  24738. + struct pinctrl *ts_pinctrl;
  24739. + struct pinctrl_state *pinctrl_state_active;
  24740. + struct pinctrl_state *pinctrl_state_suspend;
  24741. +
  24742. + struct completion dump_completion;
  24743. +#ifdef CONFIG_TOUCH_DEBUG_FS
  24744. + struct dentry *debugfs;
  24745. +#endif
  24746. +
  24747. +#if defined(CONFIG_SECURE_TOUCH)
  24748. + atomic_t st_enabled;
  24749. + atomic_t st_pending_irqs;
  24750. + bool st_initialized;
  24751. + struct completion st_powerdown;
  24752. + struct completion st_irq_processed;
  24753. + struct clk *core_clk;
  24754. + struct clk *iface_clk;
  24755. +#endif
  24756. +};
  24757. +
  24758. +struct synaptics_dsx_bus_access {
  24759. + unsigned char type;
  24760. + int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
  24761. + unsigned char *data, unsigned short length);
  24762. + int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
  24763. + unsigned char *data, unsigned short length);
  24764. +};
  24765. +
  24766. +struct synaptics_dsx_hw_interface {
  24767. + struct synaptics_dsx_board_data *board_data;
  24768. + const struct synaptics_dsx_bus_access *bus_access;
  24769. + int (*bl_hw_init)(struct synaptics_rmi4_data *rmi4_data);
  24770. + int (*ui_hw_init)(struct synaptics_rmi4_data *rmi4_data);
  24771. +};
  24772. +
  24773. +struct synaptics_rmi4_exp_fn {
  24774. + enum exp_fn fn_type;
  24775. + int (*init)(struct synaptics_rmi4_data *rmi4_data);
  24776. + void (*remove)(struct synaptics_rmi4_data *rmi4_data);
  24777. + void (*reset)(struct synaptics_rmi4_data *rmi4_data);
  24778. + void (*reinit)(struct synaptics_rmi4_data *rmi4_data);
  24779. + void (*early_suspend)(struct synaptics_rmi4_data *rmi4_data);
  24780. + void (*suspend)(struct synaptics_rmi4_data *rmi4_data);
  24781. + void (*resume)(struct synaptics_rmi4_data *rmi4_data);
  24782. + void (*late_resume)(struct synaptics_rmi4_data *rmi4_data);
  24783. + void (*attn)(struct synaptics_rmi4_data *rmi4_data,
  24784. + unsigned char intr_mask);
  24785. +};
  24786. +
  24787. +struct synaptics_rmi4_mode_switch {
  24788. + struct synaptics_rmi4_data *data;
  24789. + unsigned char mode;
  24790. + struct work_struct switch_mode_work;
  24791. +};
  24792. +
  24793. +int synaptics_rmi4_bus_init_force(void);
  24794. +
  24795. +void synaptics_rmi4_bus_exit_force(void);
  24796. +
  24797. +void synaptics_rmi4_new_function_force(struct synaptics_rmi4_exp_fn *exp_fn_module,
  24798. + bool insert);
  24799. +
  24800. +int synaptics_fw_updater(const unsigned char *fw_data);
  24801. +
  24802. +static inline int synaptics_rmi4_reg_read(
  24803. + struct synaptics_rmi4_data *rmi4_data,
  24804. + unsigned short addr,
  24805. + unsigned char *data,
  24806. + unsigned short len)
  24807. +{
  24808. + return rmi4_data->hw_if->bus_access->read(rmi4_data, addr, data, len);
  24809. +}
  24810. +
  24811. +static inline int synaptics_rmi4_reg_write(
  24812. + struct synaptics_rmi4_data *rmi4_data,
  24813. + unsigned short addr,
  24814. + unsigned char *data,
  24815. + unsigned short len)
  24816. +{
  24817. + return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len);
  24818. +}
  24819. +
  24820. +static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
  24821. + struct device_attribute *attr, char *buf)
  24822. +{
  24823. + dev_warn(dev, "%s Attempted to read from write-only attribute %s\n",
  24824. + __func__, attr->attr.name);
  24825. + return -EPERM;
  24826. +}
  24827. +
  24828. +static inline ssize_t synaptics_rmi4_store_error(struct device *dev,
  24829. + struct device_attribute *attr, const char *buf, size_t count)
  24830. +{
  24831. + dev_warn(dev, "%s Attempted to write to read-only attribute %s\n",
  24832. + __func__, attr->attr.name);
  24833. + return -EPERM;
  24834. +}
  24835. +
  24836. +static inline int secure_memcpy(unsigned char *dest, unsigned int dest_size,
  24837. + const unsigned char *src, unsigned int src_size,
  24838. + unsigned int count)
  24839. +{
  24840. + if (dest == NULL || src == NULL)
  24841. + return -EINVAL;
  24842. +
  24843. + if (count > dest_size || count > src_size)
  24844. + return -EINVAL;
  24845. +
  24846. + memcpy((void *)dest, (const void *)src, count);
  24847. +
  24848. + return 0;
  24849. +}
  24850. +
  24851. +static inline void batohs(unsigned short *dest, unsigned char *src)
  24852. +{
  24853. + *dest = src[1] * 0x100 + src[0];
  24854. +}
  24855. +
  24856. +static inline void hstoba(unsigned char *dest, unsigned short src)
  24857. +{
  24858. + dest[0] = src % 0x100;
  24859. + dest[1] = src / 0x100;
  24860. +}
  24861. +
  24862. +#endif
  24863. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_fw_update.c
  24864. new file mode 100644
  24865. index 0000000..62b03ce
  24866. --- /dev/null
  24867. +++ b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_fw_update.c
  24868. @@ -0,0 +1,5486 @@
  24869. +/*
  24870. + * Synaptics DSX touchscreen driver
  24871. + *
  24872. + * Copyright (C) 2012-2015 Synaptics Incorporated. All rights reserved.
  24873. + *
  24874. + * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
  24875. + * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
  24876. + * Copyright (C) 2017 XiaoMi, Inc.
  24877. + *
  24878. + * This program is free software; you can redistribute it and/or modify
  24879. + * it under the terms of the GNU General Public License as published by
  24880. + * the Free Software Foundation; either version 2 of the License, or
  24881. + * (at your option) any later version.
  24882. + *
  24883. + * This program is distributed in the hope that it will be useful,
  24884. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24885. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24886. + * GNU General Public License for more details.
  24887. + *
  24888. + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  24889. + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  24890. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  24891. + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  24892. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24893. + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  24894. + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  24895. + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24896. + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  24897. + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  24898. + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  24899. + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  24900. + * DOLLARS.
  24901. + */
  24902. +
  24903. +#include <linux/kernel.h>
  24904. +#include <linux/module.h>
  24905. +#include <linux/slab.h>
  24906. +#include <linux/interrupt.h>
  24907. +#include <linux/delay.h>
  24908. +#include <linux/input.h>
  24909. +#include <linux/firmware.h>
  24910. +#include <linux/platform_device.h>
  24911. +#include <linux/input/synaptics_dsx.h>
  24912. +#include "synaptics_dsx_core.h"
  24913. +#include <linux/hwinfo.h>
  24914. +
  24915. +#define FW_IHEX_NAME "synaptics/startup_fw_update.bin"
  24916. +#define FW_IMAGE_NAME "synaptics/startup_fw_update.img"
  24917. +#define DO_STARTUP_FW_UPDATE
  24918. +
  24919. +/*
  24920. +#ifdef DO_STARTUP_FW_UPDATE
  24921. +#ifdef CONFIG_FB
  24922. +#define WAIT_FOR_FB_READY
  24923. +#define FB_READY_WAIT_MS 100
  24924. +#define FB_READY_TIMEOUT_S 30
  24925. +#endif
  24926. +#endif
  24927. +*/
  24928. +#define MAX_WRITE_SIZE 4096
  24929. +
  24930. +#define FORCE_UPDATE false
  24931. +#define DO_LOCKDOWN false
  24932. +
  24933. +#define MAX_IMAGE_NAME_LEN 256
  24934. +#define MAX_FIRMWARE_ID_LEN 10
  24935. +
  24936. +#define IMAGE_HEADER_VERSION_05 0x05
  24937. +#define IMAGE_HEADER_VERSION_06 0x06
  24938. +#define IMAGE_HEADER_VERSION_10 0x10
  24939. +
  24940. +#define IMAGE_AREA_OFFSET 0x100
  24941. +#define LOCKDOWN_SIZE 0x50
  24942. +
  24943. +#define MAX_UTILITY_PARAMS 20
  24944. +
  24945. +#define V5V6_BOOTLOADER_ID_OFFSET 0
  24946. +#define V5V6_CONFIG_ID_SIZE 4
  24947. +
  24948. +#define V5_PROPERTIES_OFFSET 2
  24949. +#define V5_BLOCK_SIZE_OFFSET 3
  24950. +#define V5_BLOCK_COUNT_OFFSET 5
  24951. +#define V5_BLOCK_NUMBER_OFFSET 0
  24952. +#define V5_BLOCK_DATA_OFFSET 2
  24953. +
  24954. +#define V6_PROPERTIES_OFFSET 1
  24955. +#define V6_BLOCK_SIZE_OFFSET 2
  24956. +#define V6_BLOCK_COUNT_OFFSET 3
  24957. +#define V6_PROPERTIES_2_OFFSET 4
  24958. +#define V6_BLOCK_NUMBER_OFFSET 0
  24959. +#define V6_BLOCK_DATA_OFFSET 1
  24960. +#define V6_FLASH_COMMAND_OFFSET 2
  24961. +#define V6_FLASH_STATUS_OFFSET 3
  24962. +
  24963. +#define V7_CONFIG_ID_SIZE 32
  24964. +
  24965. +#define V7_FLASH_STATUS_OFFSET 0
  24966. +#define V7_PARTITION_ID_OFFSET 1
  24967. +#define V7_BLOCK_NUMBER_OFFSET 2
  24968. +#define V7_TRANSFER_LENGTH_OFFSET 3
  24969. +#define V7_COMMAND_OFFSET 4
  24970. +#define V7_PAYLOAD_OFFSET 5
  24971. +
  24972. +#define V7_PARTITION_SUPPORT_BYTES 4
  24973. +
  24974. +#define F35_ERROR_CODE_OFFSET 0
  24975. +#define F35_FLASH_STATUS_OFFSET 5
  24976. +#define F35_CHUNK_NUM_LSB_OFFSET 0
  24977. +#define F35_CHUNK_NUM_MSB_OFFSET 1
  24978. +#define F35_CHUNK_DATA_OFFSET 2
  24979. +#define F35_CHUNK_COMMAND_OFFSET 18
  24980. +
  24981. +#define F35_CHUNK_SIZE 16
  24982. +#define F35_ERASE_ALL_WAIT_MS 5000
  24983. +#define F35_RESET_WAIT_MS 250
  24984. +
  24985. +#define SLEEP_MODE_NORMAL (0x00)
  24986. +#define SLEEP_MODE_SENSOR_SLEEP (0x01)
  24987. +#define SLEEP_MODE_RESERVED0 (0x02)
  24988. +#define SLEEP_MODE_RESERVED1 (0x03)
  24989. +
  24990. +#define ENABLE_WAIT_MS (1 * 1000)
  24991. +#define WRITE_WAIT_MS (3 * 1000)
  24992. +#define ERASE_WAIT_MS (5 * 1000)
  24993. +
  24994. +#define MIN_SLEEP_TIME_US 50
  24995. +#define MAX_SLEEP_TIME_US 100
  24996. +
  24997. +#define INT_DISABLE_WAIT_MS 20
  24998. +#define ENTER_FLASH_PROG_WAIT_MS 20
  24999. +
  25000. +static int fwu_do_reflash(void);
  25001. +
  25002. +static int fwu_recovery_check_status(void);
  25003. +
  25004. +static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd);
  25005. +
  25006. +static ssize_t fwu_sysfs_show_image(struct file *data_file,
  25007. + struct kobject *kobj, struct bin_attribute *attributes,
  25008. + char *buf, loff_t pos, size_t count);
  25009. +
  25010. +static ssize_t fwu_sysfs_store_image(struct file *data_file,
  25011. + struct kobject *kobj, struct bin_attribute *attributes,
  25012. + char *buf, loff_t pos, size_t count);
  25013. +
  25014. +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev,
  25015. + struct device_attribute *attr, const char *buf, size_t count);
  25016. +
  25017. +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
  25018. + struct device_attribute *attr, const char *buf, size_t count);
  25019. +
  25020. +static ssize_t fwu_sysfs_write_config_store(struct device *dev,
  25021. + struct device_attribute *attr, const char *buf, size_t count);
  25022. +
  25023. +static ssize_t fwu_sysfs_read_config_store(struct device *dev,
  25024. + struct device_attribute *attr, const char *buf, size_t count);
  25025. +
  25026. +static ssize_t fwu_sysfs_config_area_store(struct device *dev,
  25027. + struct device_attribute *attr, const char *buf, size_t count);
  25028. +
  25029. +static ssize_t fwu_sysfs_image_name_store(struct device *dev,
  25030. + struct device_attribute *attr, const char *buf, size_t count);
  25031. +
  25032. +static ssize_t fwu_sysfs_image_size_store(struct device *dev,
  25033. + struct device_attribute *attr, const char *buf, size_t count);
  25034. +
  25035. +static ssize_t fwu_sysfs_block_size_show(struct device *dev,
  25036. + struct device_attribute *attr, char *buf);
  25037. +
  25038. +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
  25039. + struct device_attribute *attr, char *buf);
  25040. +
  25041. +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
  25042. + struct device_attribute *attr, char *buf);
  25043. +
  25044. +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
  25045. + struct device_attribute *attr, char *buf);
  25046. +
  25047. +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
  25048. + struct device_attribute *attr, char *buf);
  25049. +
  25050. +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
  25051. + struct device_attribute *attr, char *buf);
  25052. +
  25053. +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev,
  25054. + struct device_attribute *attr, char *buf);
  25055. +
  25056. +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev,
  25057. + struct device_attribute *attr, const char *buf, size_t count);
  25058. +
  25059. +static void firmware_force_update(struct synaptics_rmi4_data *rmi4_data);
  25060. +
  25061. +enum f34_version {
  25062. + F34_V0 = 0,
  25063. + F34_V1,
  25064. + F34_V2,
  25065. +};
  25066. +
  25067. +enum bl_version {
  25068. + BL_V5 = 5,
  25069. + BL_V6 = 6,
  25070. + BL_V7 = 7,
  25071. + BL_V8 = 8,
  25072. +};
  25073. +
  25074. +enum flash_area {
  25075. + NONE = 0,
  25076. + UI_FIRMWARE,
  25077. + UI_CONFIG,
  25078. +};
  25079. +
  25080. +enum update_mode {
  25081. + NORMAL = 1,
  25082. + FORCE = 2,
  25083. + LOCKDOWN = 8,
  25084. +};
  25085. +
  25086. +enum config_area {
  25087. + UI_CONFIG_AREA = 0,
  25088. + PM_CONFIG_AREA,
  25089. + BL_CONFIG_AREA,
  25090. + DP_CONFIG_AREA,
  25091. + FLASH_CONFIG_AREA,
  25092. + INVALID_CONFIG_AREA = 0xff,
  25093. +};
  25094. +
  25095. +enum v7_status {
  25096. + SUCCESS = 0x00,
  25097. + DEVICE_NOT_IN_BOOTLOADER_MODE,
  25098. + INVALID_PARTITION,
  25099. + INVALID_COMMAND,
  25100. + INVALID_BLOCK_OFFSET,
  25101. + INVALID_TRANSFER,
  25102. + NOT_ERASED,
  25103. + FLASH_PROGRAMMING_KEY_INCORRECT,
  25104. + BAD_PARTITION_TABLE,
  25105. + CHECKSUM_FAILED,
  25106. + FLASH_HARDWARE_FAILURE = 0x1f,
  25107. +};
  25108. +
  25109. +enum v7_partition_id {
  25110. + BOOTLOADER_PARTITION = 0x01,
  25111. + DEVICE_CONFIG_PARTITION,
  25112. + FLASH_CONFIG_PARTITION,
  25113. + MANUFACTURING_BLOCK_PARTITION,
  25114. + GUEST_SERIALIZATION_PARTITION,
  25115. + GLOBAL_PARAMETERS_PARTITION,
  25116. + CORE_CODE_PARTITION,
  25117. + CORE_CONFIG_PARTITION,
  25118. + GUEST_CODE_PARTITION,
  25119. + DISPLAY_CONFIG_PARTITION,
  25120. + EXTERNAL_TOUCH_AFE_CONFIG_PARTITION,
  25121. + UTILITY_PARAMETER_PARTITION,
  25122. +};
  25123. +
  25124. +enum v7_flash_command {
  25125. + CMD_V7_IDLE = 0x00,
  25126. + CMD_V7_ENTER_BL,
  25127. + CMD_V7_READ,
  25128. + CMD_V7_WRITE,
  25129. + CMD_V7_ERASE,
  25130. + CMD_V7_ERASE_AP,
  25131. + CMD_V7_SENSOR_ID,
  25132. +};
  25133. +
  25134. +enum v5v6_flash_command {
  25135. + CMD_V5V6_IDLE = 0x0,
  25136. + CMD_V5V6_WRITE_FW = 0x2,
  25137. + CMD_V5V6_ERASE_ALL = 0x3,
  25138. + CMD_V5V6_WRITE_LOCKDOWN = 0x4,
  25139. + CMD_V5V6_READ_CONFIG = 0x5,
  25140. + CMD_V5V6_WRITE_CONFIG = 0x6,
  25141. + CMD_V5V6_ERASE_UI_CONFIG = 0x7,
  25142. + CMD_V5V6_ERASE_BL_CONFIG = 0x9,
  25143. + CMD_V5V6_ERASE_DISP_CONFIG = 0xa,
  25144. + CMD_V5V6_ERASE_GUEST_CODE = 0xb,
  25145. + CMD_V5V6_WRITE_GUEST_CODE = 0xc,
  25146. + CMD_V5V6_ENABLE_FLASH_PROG = 0xf,
  25147. + CMD_V5V6_READ_LOCKDOWN_DATA = 0x1b,
  25148. +};
  25149. +
  25150. +enum flash_command {
  25151. + CMD_IDLE = 0,
  25152. + CMD_WRITE_FW,
  25153. + CMD_WRITE_CONFIG,
  25154. + CMD_WRITE_LOCKDOWN,
  25155. + CMD_WRITE_GUEST_CODE,
  25156. + CMD_WRITE_BOOTLOADER,
  25157. + CMD_WRITE_UTILITY_PARAM,
  25158. + CMD_READ_CONFIG,
  25159. + CMD_ERASE_ALL,
  25160. + CMD_ERASE_UI_FIRMWARE,
  25161. + CMD_ERASE_UI_CONFIG,
  25162. + CMD_ERASE_BL_CONFIG,
  25163. + CMD_ERASE_DISP_CONFIG,
  25164. + CMD_ERASE_FLASH_CONFIG,
  25165. + CMD_ERASE_GUEST_CODE,
  25166. + CMD_ERASE_BOOTLOADER,
  25167. + CMD_ERASE_UTILITY_PARAMETER,
  25168. + CMD_ENABLE_FLASH_PROG,
  25169. + CMD_READ_LOCKDOWN_DATA,
  25170. +};
  25171. +
  25172. +enum f35_flash_command {
  25173. + CMD_F35_IDLE = 0x0,
  25174. + CMD_F35_RESERVED = 0x1,
  25175. + CMD_F35_WRITE_CHUNK = 0x2,
  25176. + CMD_F35_ERASE_ALL = 0x3,
  25177. + CMD_F35_RESET = 0x10,
  25178. +};
  25179. +
  25180. +enum container_id {
  25181. + TOP_LEVEL_CONTAINER = 0,
  25182. + UI_CONTAINER,
  25183. + UI_CONFIG_CONTAINER,
  25184. + BL_CONTAINER,
  25185. + BL_IMAGE_CONTAINER,
  25186. + BL_CONFIG_CONTAINER,
  25187. + BL_LOCKDOWN_INFO_CONTAINER,
  25188. + PERMANENT_CONFIG_CONTAINER,
  25189. + GUEST_CODE_CONTAINER,
  25190. + BL_PROTOCOL_DESCRIPTOR_CONTAINER,
  25191. + UI_PROTOCOL_DESCRIPTOR_CONTAINER,
  25192. + RMI_SELF_DISCOVERY_CONTAINER,
  25193. + RMI_PAGE_CONTENT_CONTAINER,
  25194. + GENERAL_INFORMATION_CONTAINER,
  25195. + DEVICE_CONFIG_CONTAINER,
  25196. + FLASH_CONFIG_CONTAINER,
  25197. + GUEST_SERIALIZATION_CONTAINER,
  25198. + GLOBAL_PARAMETERS_CONTAINER,
  25199. + CORE_CODE_CONTAINER,
  25200. + CORE_CONFIG_CONTAINER,
  25201. + DISPLAY_CONFIG_CONTAINER,
  25202. + EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER,
  25203. + UTILITY_CONTAINER,
  25204. + UTILITY_PARAMETER_CONTAINER,
  25205. +};
  25206. +
  25207. +enum utility_parameter_id {
  25208. + UNUSED = 0,
  25209. + FORCE_PARAMETER,
  25210. + ANTI_BENDING_PARAMETER,
  25211. +};
  25212. +
  25213. +struct pdt_properties {
  25214. + union {
  25215. + struct {
  25216. + unsigned char reserved_1:6;
  25217. + unsigned char has_bsr:1;
  25218. + unsigned char reserved_2:1;
  25219. + } __packed;
  25220. + unsigned char data[1];
  25221. + };
  25222. +};
  25223. +
  25224. +struct partition_table {
  25225. + unsigned char partition_id:5;
  25226. + unsigned char byte_0_reserved:3;
  25227. + unsigned char byte_1_reserved;
  25228. + unsigned char partition_length_7_0;
  25229. + unsigned char partition_length_15_8;
  25230. + unsigned char start_physical_address_7_0;
  25231. + unsigned char start_physical_address_15_8;
  25232. + unsigned char partition_properties_7_0;
  25233. + unsigned char partition_properties_15_8;
  25234. +} __packed;
  25235. +
  25236. +struct f01_device_control {
  25237. + union {
  25238. + struct {
  25239. + unsigned char sleep_mode:2;
  25240. + unsigned char nosleep:1;
  25241. + unsigned char reserved:2;
  25242. + unsigned char charger_connected:1;
  25243. + unsigned char report_rate:1;
  25244. + unsigned char configured:1;
  25245. + } __packed;
  25246. + unsigned char data[1];
  25247. + };
  25248. +};
  25249. +
  25250. +struct f34_v7_query_0 {
  25251. + union {
  25252. + struct {
  25253. + unsigned char subpacket_1_size:3;
  25254. + unsigned char has_config_id:1;
  25255. + unsigned char f34_query0_b4:1;
  25256. + unsigned char has_thqa:1;
  25257. + unsigned char f34_query0_b6__7:2;
  25258. + } __packed;
  25259. + unsigned char data[1];
  25260. + };
  25261. +};
  25262. +
  25263. +struct f34_v7_query_1_7 {
  25264. + union {
  25265. + struct {
  25266. + /* query 1 */
  25267. + unsigned char bl_minor_revision;
  25268. + unsigned char bl_major_revision;
  25269. +
  25270. + /* query 2 */
  25271. + unsigned char bl_fw_id_7_0;
  25272. + unsigned char bl_fw_id_15_8;
  25273. + unsigned char bl_fw_id_23_16;
  25274. + unsigned char bl_fw_id_31_24;
  25275. +
  25276. + /* query 3 */
  25277. + unsigned char minimum_write_size;
  25278. + unsigned char block_size_7_0;
  25279. + unsigned char block_size_15_8;
  25280. + unsigned char flash_page_size_7_0;
  25281. + unsigned char flash_page_size_15_8;
  25282. +
  25283. + /* query 4 */
  25284. + unsigned char adjustable_partition_area_size_7_0;
  25285. + unsigned char adjustable_partition_area_size_15_8;
  25286. +
  25287. + /* query 5 */
  25288. + unsigned char flash_config_length_7_0;
  25289. + unsigned char flash_config_length_15_8;
  25290. +
  25291. + /* query 6 */
  25292. + unsigned char payload_length_7_0;
  25293. + unsigned char payload_length_15_8;
  25294. +
  25295. + /* query 7 */
  25296. + unsigned char f34_query7_b0:1;
  25297. + unsigned char has_bootloader:1;
  25298. + unsigned char has_device_config:1;
  25299. + unsigned char has_flash_config:1;
  25300. + unsigned char has_manufacturing_block:1;
  25301. + unsigned char has_guest_serialization:1;
  25302. + unsigned char has_global_parameters:1;
  25303. + unsigned char has_core_code:1;
  25304. + unsigned char has_core_config:1;
  25305. + unsigned char has_guest_code:1;
  25306. + unsigned char has_display_config:1;
  25307. + unsigned char f34_query7_b11__15:5;
  25308. + unsigned char f34_query7_b16__23;
  25309. + unsigned char f34_query7_b24__31;
  25310. + } __packed;
  25311. + unsigned char data[21];
  25312. + };
  25313. +};
  25314. +
  25315. +struct f34_v7_data0 {
  25316. + union {
  25317. + struct {
  25318. + unsigned char operation_status:5;
  25319. + unsigned char device_cfg_status:2;
  25320. + unsigned char bl_mode:1;
  25321. + } __packed;
  25322. + unsigned char data[1];
  25323. + };
  25324. +};
  25325. +
  25326. +struct f34_v7_data_1_5 {
  25327. + union {
  25328. + struct {
  25329. + unsigned char partition_id:5;
  25330. + unsigned char f34_data1_b5__7:3;
  25331. + unsigned char block_offset_7_0;
  25332. + unsigned char block_offset_15_8;
  25333. + unsigned char transfer_length_7_0;
  25334. + unsigned char transfer_length_15_8;
  25335. + unsigned char command;
  25336. + unsigned char payload_0;
  25337. + unsigned char payload_1;
  25338. + } __packed;
  25339. + unsigned char data[8];
  25340. + };
  25341. +};
  25342. +
  25343. +struct f34_v5v6_flash_properties {
  25344. + union {
  25345. + struct {
  25346. + unsigned char reg_map:1;
  25347. + unsigned char unlocked:1;
  25348. + unsigned char has_config_id:1;
  25349. + unsigned char has_pm_config:1;
  25350. + unsigned char has_bl_config:1;
  25351. + unsigned char has_disp_config:1;
  25352. + unsigned char has_ctrl1:1;
  25353. + unsigned char has_query4:1;
  25354. + } __packed;
  25355. + unsigned char data[1];
  25356. + };
  25357. +};
  25358. +
  25359. +struct f34_v5v6_flash_properties_2 {
  25360. + union {
  25361. + struct {
  25362. + unsigned char has_guest_code:1;
  25363. + unsigned char f34_query4_b1:1;
  25364. + unsigned char has_gesture_config_area:1;
  25365. + unsigned char has_force_config_block:1;
  25366. + unsigned char has_lockdown_data_block:1;
  25367. + unsigned char has_lcm_data_block:1;
  25368. + unsigned char has_oem_data_block:1;
  25369. + unsigned char f34_query4_b7:1;
  25370. + } __packed;
  25371. + unsigned char data[1];
  25372. + };
  25373. +};
  25374. +
  25375. +struct register_offset {
  25376. + unsigned char properties;
  25377. + unsigned char properties_2;
  25378. + unsigned char block_size;
  25379. + unsigned char block_count;
  25380. + unsigned char flash_status;
  25381. + unsigned char partition_id;
  25382. + unsigned char block_number;
  25383. + unsigned char transfer_length;
  25384. + unsigned char flash_cmd;
  25385. + unsigned char payload;
  25386. +};
  25387. +
  25388. +struct block_count {
  25389. + unsigned short ui_firmware;
  25390. + unsigned short ui_config;
  25391. + unsigned short dp_config;
  25392. + unsigned short pm_config;
  25393. + unsigned short fl_config;
  25394. + unsigned short bl_image;
  25395. + unsigned short bl_config;
  25396. + unsigned short utility_param;
  25397. + unsigned short lockdown;
  25398. + unsigned short guest_code;
  25399. + unsigned short lockdown_data;
  25400. + unsigned short total_count;
  25401. +};
  25402. +
  25403. +struct physical_address {
  25404. + unsigned short ui_firmware;
  25405. + unsigned short ui_config;
  25406. + unsigned short dp_config;
  25407. + unsigned short pm_config;
  25408. + unsigned short fl_config;
  25409. + unsigned short bl_image;
  25410. + unsigned short bl_config;
  25411. + unsigned short utility_param;
  25412. + unsigned short lockdown;
  25413. + unsigned short guest_code;
  25414. +};
  25415. +
  25416. +struct container_descriptor {
  25417. + unsigned char content_checksum[4];
  25418. + unsigned char container_id[2];
  25419. + unsigned char minor_version;
  25420. + unsigned char major_version;
  25421. + unsigned char reserved_08;
  25422. + unsigned char reserved_09;
  25423. + unsigned char reserved_0a;
  25424. + unsigned char reserved_0b;
  25425. + unsigned char container_option_flags[4];
  25426. + unsigned char content_options_length[4];
  25427. + unsigned char content_options_address[4];
  25428. + unsigned char content_length[4];
  25429. + unsigned char content_address[4];
  25430. +};
  25431. +
  25432. +struct image_header_10 {
  25433. + unsigned char checksum[4];
  25434. + unsigned char reserved_04;
  25435. + unsigned char reserved_05;
  25436. + unsigned char minor_header_version;
  25437. + unsigned char major_header_version;
  25438. + unsigned char reserved_08;
  25439. + unsigned char reserved_09;
  25440. + unsigned char reserved_0a;
  25441. + unsigned char reserved_0b;
  25442. + unsigned char top_level_container_start_addr[4];
  25443. +};
  25444. +
  25445. +struct image_header_05_06 {
  25446. + /* 0x00 - 0x0f */
  25447. + unsigned char checksum[4];
  25448. + unsigned char reserved_04;
  25449. + unsigned char reserved_05;
  25450. + unsigned char options_firmware_id:1;
  25451. + unsigned char options_bootloader:1;
  25452. + unsigned char options_guest_code:1;
  25453. + unsigned char options_tddi:1;
  25454. + unsigned char options_reserved:4;
  25455. + unsigned char header_version;
  25456. + unsigned char firmware_size[4];
  25457. + unsigned char config_size[4];
  25458. + /* 0x10 - 0x1f */
  25459. + unsigned char product_id[PRODUCT_ID_SIZE];
  25460. + unsigned char package_id[2];
  25461. + unsigned char package_id_revision[2];
  25462. + unsigned char product_info[PRODUCT_INFO_SIZE];
  25463. + /* 0x20 - 0x2f */
  25464. + unsigned char bootloader_addr[4];
  25465. + unsigned char bootloader_size[4];
  25466. + unsigned char ui_addr[4];
  25467. + unsigned char ui_size[4];
  25468. + /* 0x30 - 0x3f */
  25469. + unsigned char ds_id[16];
  25470. + /* 0x40 - 0x4f */
  25471. + union {
  25472. + struct {
  25473. + unsigned char cstmr_product_id[PRODUCT_ID_SIZE];
  25474. + unsigned char reserved_4a_4f[6];
  25475. + };
  25476. + struct {
  25477. + unsigned char dsp_cfg_addr[4];
  25478. + unsigned char dsp_cfg_size[4];
  25479. + unsigned char reserved_48_4f[8];
  25480. + };
  25481. + };
  25482. + /* 0x50 - 0x53 */
  25483. + unsigned char firmware_id[4];
  25484. +};
  25485. +
  25486. +struct block_data {
  25487. + unsigned int size;
  25488. + const unsigned char *data;
  25489. +};
  25490. +
  25491. +struct image_metadata {
  25492. + bool contains_firmware_id;
  25493. + bool contains_bootloader;
  25494. + bool contains_guest_code;
  25495. + bool contains_disp_config;
  25496. + bool contains_perm_config;
  25497. + bool contains_flash_config;
  25498. + bool contains_utility_param;
  25499. + unsigned int firmware_id;
  25500. + unsigned int checksum;
  25501. + unsigned int bootloader_size;
  25502. + unsigned int disp_config_offset;
  25503. + unsigned char bl_version;
  25504. + unsigned char product_id[PRODUCT_ID_SIZE + 1];
  25505. + unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1];
  25506. + unsigned char utility_param_id[MAX_UTILITY_PARAMS];
  25507. + struct block_data bootloader;
  25508. + struct block_data utility;
  25509. + struct block_data ui_firmware;
  25510. + struct block_data ui_config;
  25511. + struct block_data dp_config;
  25512. + struct block_data pm_config;
  25513. + struct block_data fl_config;
  25514. + struct block_data bl_image;
  25515. + struct block_data bl_config;
  25516. + struct block_data utility_param[MAX_UTILITY_PARAMS];
  25517. + struct block_data lockdown;
  25518. + struct block_data guest_code;
  25519. + struct block_count blkcount;
  25520. + struct physical_address phyaddr;
  25521. +};
  25522. +
  25523. +struct synaptics_rmi4_fwu_handle {
  25524. + enum bl_version bl_version;
  25525. + bool initialized;
  25526. + bool in_bl_mode;
  25527. + bool in_ub_mode;
  25528. + bool bl_mode_device;
  25529. + bool force_update;
  25530. + bool do_lockdown;
  25531. + bool has_guest_code;
  25532. + bool has_lockdown_data;
  25533. + bool has_utility_param;
  25534. + bool new_partition_table;
  25535. + bool incompatible_partition_tables;
  25536. + bool write_bootloader;
  25537. + unsigned int data_pos;
  25538. + unsigned char *ext_data_source;
  25539. + unsigned char *read_config_buf;
  25540. + unsigned char intr_mask;
  25541. + unsigned char command;
  25542. + unsigned char bootloader_id[2];
  25543. + unsigned char config_id[32];
  25544. + unsigned char flash_status;
  25545. + unsigned char partitions;
  25546. +#ifdef F51_DISCRETE_FORCE
  25547. + unsigned char *cal_data;
  25548. + unsigned short cal_data_off;
  25549. + unsigned short cal_data_size;
  25550. + unsigned short cal_data_buf_size;
  25551. + unsigned short cal_packet_data_size;
  25552. +#endif
  25553. + unsigned short block_size;
  25554. + unsigned short config_size;
  25555. + unsigned short config_area;
  25556. + unsigned short config_block_count;
  25557. + unsigned short flash_config_length;
  25558. + unsigned short payload_length;
  25559. + unsigned short partition_table_bytes;
  25560. + unsigned short read_config_buf_size;
  25561. + const unsigned char *config_data;
  25562. + const unsigned char *image;
  25563. + unsigned char *image_name;
  25564. + unsigned int image_size;
  25565. + struct image_metadata img;
  25566. + struct register_offset off;
  25567. + struct block_count blkcount;
  25568. + struct physical_address phyaddr;
  25569. + struct f34_v5v6_flash_properties flash_properties;
  25570. + struct synaptics_rmi4_fn_desc f34_fd;
  25571. + struct synaptics_rmi4_fn_desc f35_fd;
  25572. + struct synaptics_rmi4_data *rmi4_data;
  25573. + struct workqueue_struct *fwu_workqueue;
  25574. + struct work_struct fwu_work;
  25575. +};
  25576. +
  25577. +static struct bin_attribute dev_attr_data = {
  25578. + .attr = {
  25579. + .name = "data",
  25580. + .mode = (S_IRUGO | S_IWUGO),
  25581. + },
  25582. + .size = 0,
  25583. + .read = fwu_sysfs_show_image,
  25584. + .write = fwu_sysfs_store_image,
  25585. +};
  25586. +
  25587. +static struct device_attribute attrs[] = {
  25588. + __ATTR(dorecovery, S_IWUSR,
  25589. + synaptics_rmi4_show_error,
  25590. + fwu_sysfs_do_recovery_store),
  25591. + __ATTR(doreflash, S_IWUSR,
  25592. + synaptics_rmi4_show_error,
  25593. + fwu_sysfs_do_reflash_store),
  25594. + __ATTR(writeconfig, S_IWUSR,
  25595. + synaptics_rmi4_show_error,
  25596. + fwu_sysfs_write_config_store),
  25597. + __ATTR(readconfig, S_IWUSR,
  25598. + synaptics_rmi4_show_error,
  25599. + fwu_sysfs_read_config_store),
  25600. + __ATTR(configarea, S_IWUSR,
  25601. + synaptics_rmi4_show_error,
  25602. + fwu_sysfs_config_area_store),
  25603. + __ATTR(imagename, S_IWUSR,
  25604. + synaptics_rmi4_show_error,
  25605. + fwu_sysfs_image_name_store),
  25606. + __ATTR(imagesize, S_IWUSR,
  25607. + synaptics_rmi4_show_error,
  25608. + fwu_sysfs_image_size_store),
  25609. + __ATTR(blocksize, S_IRUGO,
  25610. + fwu_sysfs_block_size_show,
  25611. + synaptics_rmi4_store_error),
  25612. + __ATTR(fwblockcount, S_IRUGO,
  25613. + fwu_sysfs_firmware_block_count_show,
  25614. + synaptics_rmi4_store_error),
  25615. + __ATTR(configblockcount, S_IRUGO,
  25616. + fwu_sysfs_configuration_block_count_show,
  25617. + synaptics_rmi4_store_error),
  25618. + __ATTR(dispconfigblockcount, S_IRUGO,
  25619. + fwu_sysfs_disp_config_block_count_show,
  25620. + synaptics_rmi4_store_error),
  25621. + __ATTR(permconfigblockcount, S_IRUGO,
  25622. + fwu_sysfs_perm_config_block_count_show,
  25623. + synaptics_rmi4_store_error),
  25624. + __ATTR(blconfigblockcount, S_IRUGO,
  25625. + fwu_sysfs_bl_config_block_count_show,
  25626. + synaptics_rmi4_store_error),
  25627. + __ATTR(guestcodeblockcount, S_IRUGO,
  25628. + fwu_sysfs_guest_code_block_count_show,
  25629. + synaptics_rmi4_store_error),
  25630. + __ATTR(writeguestcode, S_IWUSR,
  25631. + synaptics_rmi4_show_error,
  25632. + fwu_sysfs_write_guest_code_store),
  25633. +};
  25634. +
  25635. +static struct synaptics_rmi4_fwu_handle *fwu;
  25636. +
  25637. +DECLARE_COMPLETION(fwu_remove_complete_force);
  25638. +static int fwu_read_f34_guest_serialization_partition(void);
  25639. +
  25640. +static void calculate_checksum(unsigned short *data, unsigned long len,
  25641. + unsigned long *result)
  25642. +{
  25643. + unsigned long temp;
  25644. + unsigned long sum1 = 0xffff;
  25645. + unsigned long sum2 = 0xffff;
  25646. +
  25647. + *result = 0xffffffff;
  25648. +
  25649. + while (len--) {
  25650. + temp = *data;
  25651. + sum1 += temp;
  25652. + sum2 += sum1;
  25653. + sum1 = (sum1 & 0xffff) + (sum1 >> 16);
  25654. + sum2 = (sum2 & 0xffff) + (sum2 >> 16);
  25655. + data++;
  25656. + }
  25657. +
  25658. + *result = sum2 << 16 | sum1;
  25659. +
  25660. + return;
  25661. +}
  25662. +
  25663. +static void convert_to_little_endian(unsigned char *dest, unsigned long src)
  25664. +{
  25665. + dest[0] = (unsigned char)(src & 0xff);
  25666. + dest[1] = (unsigned char)((src >> 8) & 0xff);
  25667. + dest[2] = (unsigned char)((src >> 16) & 0xff);
  25668. + dest[3] = (unsigned char)((src >> 24) & 0xff);
  25669. +
  25670. + return;
  25671. +}
  25672. +
  25673. +static unsigned int le_to_uint(const unsigned char *ptr)
  25674. +{
  25675. + return (unsigned int)ptr[0] +
  25676. + (unsigned int)ptr[1] * 0x100 +
  25677. + (unsigned int)ptr[2] * 0x10000 +
  25678. + (unsigned int)ptr[3] * 0x1000000;
  25679. +}
  25680. +
  25681. +#ifdef F51_DISCRETE_FORCE
  25682. +static int fwu_f51_force_data_init(void)
  25683. +{
  25684. + int retval;
  25685. + unsigned char query_count;
  25686. + unsigned char packet_info;
  25687. + unsigned char offset[2];
  25688. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  25689. +
  25690. + retval = synaptics_rmi4_reg_read(rmi4_data,
  25691. + rmi4_data->f51_query_base_addr + 7,
  25692. + offset,
  25693. + sizeof(offset));
  25694. + if (retval < 0) {
  25695. + dev_err(rmi4_data->pdev->dev.parent,
  25696. + "%s: Failed to read force data offset\n",
  25697. + __func__);
  25698. + return retval;
  25699. + }
  25700. +
  25701. + fwu->cal_data_off = offset[0] | offset[1] << 8;
  25702. +
  25703. + retval = synaptics_rmi4_reg_read(rmi4_data,
  25704. + rmi4_data->f51_query_base_addr,
  25705. + &query_count,
  25706. + sizeof(query_count));
  25707. + if (retval < 0) {
  25708. + dev_err(rmi4_data->pdev->dev.parent,
  25709. + "%s: Failed to read number of F51 query registers\n",
  25710. + __func__);
  25711. + return retval;
  25712. + }
  25713. +
  25714. + if (query_count >= 10) {
  25715. + retval = synaptics_rmi4_reg_read(rmi4_data,
  25716. + rmi4_data->f51_query_base_addr + 9,
  25717. + &packet_info,
  25718. + sizeof(packet_info));
  25719. + if (retval < 0) {
  25720. + dev_err(rmi4_data->pdev->dev.parent,
  25721. + "%s: Failed to read F51 packet register info\n",
  25722. + __func__);
  25723. + return retval;
  25724. + }
  25725. +
  25726. + if (packet_info & MASK_1BIT) {
  25727. + fwu->cal_packet_data_size = packet_info >> 1;
  25728. + fwu->cal_packet_data_size *= 2;
  25729. + } else {
  25730. + fwu->cal_packet_data_size = 0;
  25731. + }
  25732. + } else {
  25733. + fwu->cal_packet_data_size = 0;
  25734. + }
  25735. +
  25736. + fwu->cal_data_size = CAL_DATA_SIZE + fwu->cal_packet_data_size;
  25737. + if (fwu->cal_data_size > fwu->cal_data_buf_size) {
  25738. + kfree(fwu->cal_data);
  25739. + fwu->cal_data_buf_size = fwu->cal_data_size;
  25740. + fwu->cal_data = kmalloc(fwu->cal_data_buf_size, GFP_KERNEL);
  25741. + if (!fwu->cal_data) {
  25742. + dev_err(rmi4_data->pdev->dev.parent,
  25743. + "%s: Failed to alloc mem for fwu->cal_data\n",
  25744. + __func__);
  25745. + fwu->cal_data_buf_size = 0;
  25746. + return -ENOMEM;
  25747. + }
  25748. + }
  25749. +
  25750. + return 0;
  25751. +}
  25752. +#endif
  25753. +
  25754. +static int fwu_allocate_read_config_buf(unsigned int count)
  25755. +{
  25756. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  25757. +
  25758. + if (count > fwu->read_config_buf_size) {
  25759. + kfree(fwu->read_config_buf);
  25760. + fwu->read_config_buf = kzalloc(count, GFP_KERNEL);
  25761. + if (!fwu->read_config_buf) {
  25762. + dev_err(rmi4_data->pdev->dev.parent,
  25763. + "%s: Failed to alloc mem for fwu->read_config_buf\n",
  25764. + __func__);
  25765. + fwu->read_config_buf_size = 0;
  25766. + return -ENOMEM;
  25767. + }
  25768. + fwu->read_config_buf_size = count;
  25769. + }
  25770. +
  25771. + return 0;
  25772. +}
  25773. +
  25774. +static void fwu_compare_partition_tables(void)
  25775. +{
  25776. + fwu->incompatible_partition_tables = false;
  25777. +
  25778. + if (fwu->phyaddr.bl_image != fwu->img.phyaddr.bl_image)
  25779. + fwu->incompatible_partition_tables = true;
  25780. + else if (fwu->phyaddr.lockdown != fwu->img.phyaddr.lockdown)
  25781. + fwu->incompatible_partition_tables = true;
  25782. + else if (fwu->phyaddr.bl_config != fwu->img.phyaddr.bl_config)
  25783. + fwu->incompatible_partition_tables = true;
  25784. + else if (fwu->phyaddr.utility_param != fwu->img.phyaddr.utility_param)
  25785. + fwu->incompatible_partition_tables = true;
  25786. +
  25787. + if (fwu->bl_version == BL_V7) {
  25788. + if (fwu->phyaddr.fl_config != fwu->img.phyaddr.fl_config)
  25789. + fwu->incompatible_partition_tables = true;
  25790. + }
  25791. +
  25792. + fwu->new_partition_table = false;
  25793. +
  25794. + if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware)
  25795. + fwu->new_partition_table = true;
  25796. + else if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config)
  25797. + fwu->new_partition_table = true;
  25798. +
  25799. + if (fwu->flash_properties.has_disp_config) {
  25800. + if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config)
  25801. + fwu->new_partition_table = true;
  25802. + }
  25803. +
  25804. + if (fwu->has_guest_code) {
  25805. + if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code)
  25806. + fwu->new_partition_table = true;
  25807. + }
  25808. +
  25809. + return;
  25810. +}
  25811. +
  25812. +static void fwu_parse_partition_table(const unsigned char *partition_table,
  25813. + struct block_count *blkcount, struct physical_address *phyaddr)
  25814. +{
  25815. + unsigned char ii;
  25816. + unsigned char index;
  25817. + unsigned char offset;
  25818. + unsigned short partition_length;
  25819. + unsigned short physical_address;
  25820. + struct partition_table *ptable;
  25821. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  25822. +
  25823. + for (ii = 0; ii < fwu->partitions; ii++) {
  25824. + index = ii * 8 + 2;
  25825. + ptable = (struct partition_table *)&partition_table[index];
  25826. + partition_length = ptable->partition_length_15_8 << 8 |
  25827. + ptable->partition_length_7_0;
  25828. + physical_address = ptable->start_physical_address_15_8 << 8 |
  25829. + ptable->start_physical_address_7_0;
  25830. + dev_dbg(rmi4_data->pdev->dev.parent,
  25831. + "%s: Partition entry %d:\n",
  25832. + __func__, ii);
  25833. + for (offset = 0; offset < 8; offset++) {
  25834. + dev_dbg(rmi4_data->pdev->dev.parent,
  25835. + "%s: 0x%02x\n",
  25836. + __func__,
  25837. + partition_table[index + offset]);
  25838. + }
  25839. + switch (ptable->partition_id) {
  25840. + case CORE_CODE_PARTITION:
  25841. + blkcount->ui_firmware = partition_length;
  25842. + phyaddr->ui_firmware = physical_address;
  25843. + dev_dbg(rmi4_data->pdev->dev.parent,
  25844. + "%s: Core code block count: %d\n",
  25845. + __func__, blkcount->ui_firmware);
  25846. + blkcount->total_count += partition_length;
  25847. + break;
  25848. + case CORE_CONFIG_PARTITION:
  25849. + blkcount->ui_config = partition_length;
  25850. + phyaddr->ui_config = physical_address;
  25851. + dev_dbg(rmi4_data->pdev->dev.parent,
  25852. + "%s: Core config block count: %d\n",
  25853. + __func__, blkcount->ui_config);
  25854. + blkcount->total_count += partition_length;
  25855. + break;
  25856. + case BOOTLOADER_PARTITION:
  25857. + blkcount->bl_image = partition_length;
  25858. + phyaddr->bl_image = physical_address;
  25859. + dev_dbg(rmi4_data->pdev->dev.parent,
  25860. + "%s: Bootloader block count: %d\n",
  25861. + __func__, blkcount->bl_image);
  25862. + blkcount->total_count += partition_length;
  25863. + break;
  25864. + case UTILITY_PARAMETER_PARTITION:
  25865. + blkcount->utility_param = partition_length;
  25866. + phyaddr->utility_param = physical_address;
  25867. + dev_dbg(rmi4_data->pdev->dev.parent,
  25868. + "%s: Utility parameter block count: %d\n",
  25869. + __func__, blkcount->utility_param);
  25870. + blkcount->total_count += partition_length;
  25871. + break;
  25872. + case DISPLAY_CONFIG_PARTITION:
  25873. + blkcount->dp_config = partition_length;
  25874. + phyaddr->dp_config = physical_address;
  25875. + dev_dbg(rmi4_data->pdev->dev.parent,
  25876. + "%s: Display config block count: %d\n",
  25877. + __func__, blkcount->dp_config);
  25878. + blkcount->total_count += partition_length;
  25879. + break;
  25880. + case FLASH_CONFIG_PARTITION:
  25881. + blkcount->fl_config = partition_length;
  25882. + phyaddr->fl_config = physical_address;
  25883. + dev_dbg(rmi4_data->pdev->dev.parent,
  25884. + "%s: Flash config block count: %d\n",
  25885. + __func__, blkcount->fl_config);
  25886. + blkcount->total_count += partition_length;
  25887. + break;
  25888. + case GUEST_CODE_PARTITION:
  25889. + blkcount->guest_code = partition_length;
  25890. + phyaddr->guest_code = physical_address;
  25891. + dev_dbg(rmi4_data->pdev->dev.parent,
  25892. + "%s: Guest code block count: %d\n",
  25893. + __func__, blkcount->guest_code);
  25894. + blkcount->total_count += partition_length;
  25895. + break;
  25896. + case GUEST_SERIALIZATION_PARTITION:
  25897. + blkcount->pm_config = partition_length;
  25898. + phyaddr->pm_config = physical_address;
  25899. + dev_dbg(rmi4_data->pdev->dev.parent,
  25900. + "%s: Guest serialization block count: %d\n",
  25901. + __func__, blkcount->pm_config);
  25902. + blkcount->total_count += partition_length;
  25903. + break;
  25904. + case GLOBAL_PARAMETERS_PARTITION:
  25905. + blkcount->bl_config = partition_length;
  25906. + phyaddr->bl_config = physical_address;
  25907. + dev_dbg(rmi4_data->pdev->dev.parent,
  25908. + "%s: Global parameters block count: %d\n",
  25909. + __func__, blkcount->bl_config);
  25910. + blkcount->total_count += partition_length;
  25911. + break;
  25912. + case DEVICE_CONFIG_PARTITION:
  25913. + blkcount->lockdown = partition_length;
  25914. + phyaddr->lockdown = physical_address;
  25915. + dev_dbg(rmi4_data->pdev->dev.parent,
  25916. + "%s: Device config block count: %d\n",
  25917. + __func__, blkcount->lockdown);
  25918. + blkcount->total_count += partition_length;
  25919. + break;
  25920. + };
  25921. + }
  25922. +
  25923. + return;
  25924. +}
  25925. +
  25926. +static void fwu_parse_image_header_10_utility(const unsigned char *image)
  25927. +{
  25928. + unsigned char ii;
  25929. + unsigned char num_of_containers;
  25930. + unsigned int addr;
  25931. + unsigned int container_id;
  25932. + unsigned int length;
  25933. + const unsigned char *content;
  25934. + struct container_descriptor *descriptor;
  25935. +
  25936. + num_of_containers = fwu->img.utility.size / 4;
  25937. +
  25938. + for (ii = 0; ii < num_of_containers; ii++) {
  25939. + if (ii >= MAX_UTILITY_PARAMS)
  25940. + continue;
  25941. + addr = le_to_uint(fwu->img.utility.data + (ii * 4));
  25942. + descriptor = (struct container_descriptor *)(image + addr);
  25943. + container_id = descriptor->container_id[0] |
  25944. + descriptor->container_id[1] << 8;
  25945. + content = image + le_to_uint(descriptor->content_address);
  25946. + length = le_to_uint(descriptor->content_length);
  25947. + switch (container_id) {
  25948. + case UTILITY_PARAMETER_CONTAINER:
  25949. + fwu->img.utility_param[ii].data = content;
  25950. + fwu->img.utility_param[ii].size = length;
  25951. + fwu->img.utility_param_id[ii] = content[0];
  25952. + break;
  25953. + default:
  25954. + break;
  25955. + };
  25956. + }
  25957. +
  25958. + return;
  25959. +}
  25960. +
  25961. +static void fwu_parse_image_header_10_bootloader(const unsigned char *image)
  25962. +{
  25963. + unsigned char ii;
  25964. + unsigned char num_of_containers;
  25965. + unsigned int addr;
  25966. + unsigned int container_id;
  25967. + unsigned int length;
  25968. + const unsigned char *content;
  25969. + struct container_descriptor *descriptor;
  25970. +
  25971. + num_of_containers = (fwu->img.bootloader.size - 4) / 4;
  25972. +
  25973. + for (ii = 1; ii <= num_of_containers; ii++) {
  25974. + addr = le_to_uint(fwu->img.bootloader.data + (ii * 4));
  25975. + descriptor = (struct container_descriptor *)(image + addr);
  25976. + container_id = descriptor->container_id[0] |
  25977. + descriptor->container_id[1] << 8;
  25978. + content = image + le_to_uint(descriptor->content_address);
  25979. + length = le_to_uint(descriptor->content_length);
  25980. + switch (container_id) {
  25981. + case BL_IMAGE_CONTAINER:
  25982. + fwu->img.bl_image.data = content;
  25983. + fwu->img.bl_image.size = length;
  25984. + break;
  25985. + case BL_CONFIG_CONTAINER:
  25986. + case GLOBAL_PARAMETERS_CONTAINER:
  25987. + fwu->img.bl_config.data = content;
  25988. + fwu->img.bl_config.size = length;
  25989. + break;
  25990. + case BL_LOCKDOWN_INFO_CONTAINER:
  25991. + case DEVICE_CONFIG_CONTAINER:
  25992. + fwu->img.lockdown.data = content;
  25993. + fwu->img.lockdown.size = length;
  25994. + break;
  25995. + default:
  25996. + break;
  25997. + };
  25998. + }
  25999. +
  26000. + return;
  26001. +}
  26002. +
  26003. +static void fwu_parse_image_header_10(void)
  26004. +{
  26005. + unsigned char ii;
  26006. + unsigned char num_of_containers;
  26007. + unsigned int addr;
  26008. + unsigned int offset;
  26009. + unsigned int container_id;
  26010. + unsigned int length;
  26011. + const unsigned char *image;
  26012. + const unsigned char *content;
  26013. + struct container_descriptor *descriptor;
  26014. + struct image_header_10 *header;
  26015. +
  26016. + image = fwu->image;
  26017. + header = (struct image_header_10 *)image;
  26018. +
  26019. + fwu->img.checksum = le_to_uint(header->checksum);
  26020. +
  26021. + /* address of top level container */
  26022. + offset = le_to_uint(header->top_level_container_start_addr);
  26023. + descriptor = (struct container_descriptor *)(image + offset);
  26024. +
  26025. + /* address of top level container content */
  26026. + offset = le_to_uint(descriptor->content_address);
  26027. + num_of_containers = le_to_uint(descriptor->content_length) / 4;
  26028. +
  26029. + for (ii = 0; ii < num_of_containers; ii++) {
  26030. + addr = le_to_uint(image + offset);
  26031. + offset += 4;
  26032. + descriptor = (struct container_descriptor *)(image + addr);
  26033. + container_id = descriptor->container_id[0] |
  26034. + descriptor->container_id[1] << 8;
  26035. + content = image + le_to_uint(descriptor->content_address);
  26036. + length = le_to_uint(descriptor->content_length);
  26037. + switch (container_id) {
  26038. + case UI_CONTAINER:
  26039. + case CORE_CODE_CONTAINER:
  26040. + fwu->img.ui_firmware.data = content;
  26041. + fwu->img.ui_firmware.size = length;
  26042. + break;
  26043. + case UI_CONFIG_CONTAINER:
  26044. + case CORE_CONFIG_CONTAINER:
  26045. + fwu->img.ui_config.data = content;
  26046. + fwu->img.ui_config.size = length;
  26047. + break;
  26048. + case BL_CONTAINER:
  26049. + fwu->img.bl_version = *content;
  26050. + fwu->img.bootloader.data = content;
  26051. + fwu->img.bootloader.size = length;
  26052. + fwu_parse_image_header_10_bootloader(image);
  26053. + break;
  26054. + case UTILITY_CONTAINER:
  26055. + fwu->img.utility.data = content;
  26056. + fwu->img.utility.size = length;
  26057. + fwu_parse_image_header_10_utility(image);
  26058. + break;
  26059. + case GUEST_CODE_CONTAINER:
  26060. + fwu->img.contains_guest_code = true;
  26061. + fwu->img.guest_code.data = content;
  26062. + fwu->img.guest_code.size = length;
  26063. + break;
  26064. + case DISPLAY_CONFIG_CONTAINER:
  26065. + fwu->img.contains_disp_config = true;
  26066. + fwu->img.dp_config.data = content;
  26067. + fwu->img.dp_config.size = length;
  26068. + break;
  26069. + case PERMANENT_CONFIG_CONTAINER:
  26070. + case GUEST_SERIALIZATION_CONTAINER:
  26071. + fwu->img.contains_perm_config = true;
  26072. + fwu->img.pm_config.data = content;
  26073. + fwu->img.pm_config.size = length;
  26074. + break;
  26075. + case FLASH_CONFIG_CONTAINER:
  26076. + fwu->img.contains_flash_config = true;
  26077. + fwu->img.fl_config.data = content;
  26078. + fwu->img.fl_config.size = length;
  26079. + break;
  26080. + case GENERAL_INFORMATION_CONTAINER:
  26081. + fwu->img.contains_firmware_id = true;
  26082. + fwu->img.firmware_id = le_to_uint(content + 4);
  26083. + break;
  26084. + default:
  26085. + break;
  26086. + }
  26087. + }
  26088. +
  26089. + return;
  26090. +}
  26091. +
  26092. +static void fwu_parse_image_header_05_06(void)
  26093. +{
  26094. + int retval;
  26095. + const unsigned char *image;
  26096. + struct image_header_05_06 *header;
  26097. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26098. +
  26099. + image = fwu->image;
  26100. + header = (struct image_header_05_06 *)image;
  26101. +
  26102. + fwu->img.checksum = le_to_uint(header->checksum);
  26103. +
  26104. + fwu->img.bl_version = header->header_version;
  26105. +
  26106. + fwu->img.contains_bootloader = header->options_bootloader;
  26107. + if (fwu->img.contains_bootloader)
  26108. + fwu->img.bootloader_size = le_to_uint(header->bootloader_size);
  26109. +
  26110. + fwu->img.ui_firmware.size = le_to_uint(header->firmware_size);
  26111. + if (fwu->img.ui_firmware.size) {
  26112. + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET;
  26113. + if (fwu->img.contains_bootloader)
  26114. + fwu->img.ui_firmware.data += fwu->img.bootloader_size;
  26115. + }
  26116. +
  26117. + if ((fwu->img.bl_version == BL_V6) && header->options_tddi)
  26118. + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET;
  26119. +
  26120. + fwu->img.ui_config.size = le_to_uint(header->config_size);
  26121. + if (fwu->img.ui_config.size) {
  26122. + fwu->img.ui_config.data = fwu->img.ui_firmware.data +
  26123. + fwu->img.ui_firmware.size;
  26124. + }
  26125. +
  26126. + if (fwu->img.contains_bootloader || header->options_tddi)
  26127. + fwu->img.contains_disp_config = true;
  26128. + else
  26129. + fwu->img.contains_disp_config = false;
  26130. +
  26131. + if (fwu->img.contains_disp_config) {
  26132. + fwu->img.disp_config_offset = le_to_uint(header->dsp_cfg_addr);
  26133. + fwu->img.dp_config.size = le_to_uint(header->dsp_cfg_size);
  26134. + fwu->img.dp_config.data = image + fwu->img.disp_config_offset;
  26135. + } else {
  26136. + retval = secure_memcpy(fwu->img.cstmr_product_id,
  26137. + sizeof(fwu->img.cstmr_product_id),
  26138. + header->cstmr_product_id,
  26139. + sizeof(header->cstmr_product_id),
  26140. + PRODUCT_ID_SIZE);
  26141. + if (retval < 0) {
  26142. + dev_err(rmi4_data->pdev->dev.parent,
  26143. + "%s: Failed to copy custom product ID string\n",
  26144. + __func__);
  26145. + }
  26146. + fwu->img.cstmr_product_id[PRODUCT_ID_SIZE] = 0;
  26147. + }
  26148. +
  26149. + fwu->img.contains_firmware_id = header->options_firmware_id;
  26150. + if (fwu->img.contains_firmware_id)
  26151. + fwu->img.firmware_id = le_to_uint(header->firmware_id);
  26152. +
  26153. + retval = secure_memcpy(fwu->img.product_id,
  26154. + sizeof(fwu->img.product_id),
  26155. + header->product_id,
  26156. + sizeof(header->product_id),
  26157. + PRODUCT_ID_SIZE);
  26158. + if (retval < 0) {
  26159. + dev_err(rmi4_data->pdev->dev.parent,
  26160. + "%s: Failed to copy product ID string\n",
  26161. + __func__);
  26162. + }
  26163. + fwu->img.product_id[PRODUCT_ID_SIZE] = 0;
  26164. +
  26165. + fwu->img.lockdown.size = LOCKDOWN_SIZE;
  26166. + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE;
  26167. +
  26168. + return;
  26169. +}
  26170. +
  26171. +static int fwu_parse_image_info(void)
  26172. +{
  26173. + struct image_header_10 *header;
  26174. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26175. +
  26176. + header = (struct image_header_10 *)fwu->image;
  26177. +
  26178. + memset(&fwu->img, 0x00, sizeof(fwu->img));
  26179. +
  26180. + switch (header->major_header_version) {
  26181. + case IMAGE_HEADER_VERSION_10:
  26182. + fwu_parse_image_header_10();
  26183. + break;
  26184. + case IMAGE_HEADER_VERSION_05:
  26185. + case IMAGE_HEADER_VERSION_06:
  26186. + fwu_parse_image_header_05_06();
  26187. + break;
  26188. + default:
  26189. + dev_err(rmi4_data->pdev->dev.parent,
  26190. + "%s: Unsupported image file format (0x%02x)\n",
  26191. + __func__, header->major_header_version);
  26192. + return -EINVAL;
  26193. + }
  26194. +
  26195. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) {
  26196. + if (!fwu->img.contains_flash_config) {
  26197. + dev_err(rmi4_data->pdev->dev.parent,
  26198. + "%s: No flash config found in firmware image\n",
  26199. + __func__);
  26200. + return -EINVAL;
  26201. + }
  26202. +
  26203. + fwu_parse_partition_table(fwu->img.fl_config.data,
  26204. + &fwu->img.blkcount, &fwu->img.phyaddr);
  26205. +
  26206. + if (fwu->img.blkcount.utility_param)
  26207. + fwu->img.contains_utility_param = true;
  26208. +
  26209. + fwu_compare_partition_tables();
  26210. + } else {
  26211. + fwu->new_partition_table = false;
  26212. + fwu->incompatible_partition_tables = false;
  26213. + }
  26214. +
  26215. + return 0;
  26216. +}
  26217. +
  26218. +static int fwu_read_flash_status(void)
  26219. +{
  26220. + int retval;
  26221. + unsigned char status;
  26222. + unsigned char command;
  26223. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26224. +
  26225. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26226. + fwu->f34_fd.data_base_addr + fwu->off.flash_status,
  26227. + &status,
  26228. + sizeof(status));
  26229. + if (retval < 0) {
  26230. + dev_err(rmi4_data->pdev->dev.parent,
  26231. + "%s: Failed to read flash status\n",
  26232. + __func__);
  26233. + return retval;
  26234. + }
  26235. +
  26236. + fwu->in_bl_mode = status >> 7;
  26237. +
  26238. + if (fwu->bl_version == BL_V5)
  26239. + fwu->flash_status = (status >> 4) & MASK_3BIT;
  26240. + else if (fwu->bl_version == BL_V6)
  26241. + fwu->flash_status = status & MASK_3BIT;
  26242. + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  26243. + fwu->flash_status = status & MASK_5BIT;
  26244. +
  26245. + if (fwu->write_bootloader)
  26246. + fwu->flash_status = 0x00;
  26247. +
  26248. + if (fwu->flash_status != 0x00) {
  26249. + dev_err(rmi4_data->pdev->dev.parent,
  26250. + "%s: Flash status = %d, command = 0x%02x, config area = 0x%02x\n",
  26251. + __func__, fwu->flash_status, fwu->command, fwu->config_area);
  26252. + }
  26253. +
  26254. + if (fwu->flash_status == 0x08)
  26255. + fwu->flash_status = 0;
  26256. +
  26257. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26258. + fwu->f34_fd.data_base_addr + fwu->off.flash_cmd,
  26259. + &command,
  26260. + sizeof(command));
  26261. + if (retval < 0) {
  26262. + dev_err(rmi4_data->pdev->dev.parent,
  26263. + "%s: Failed to read flash command\n",
  26264. + __func__);
  26265. + return retval;
  26266. + }
  26267. +
  26268. + if (fwu->bl_version == BL_V5)
  26269. + fwu->command = command & MASK_4BIT;
  26270. + else if (fwu->bl_version == BL_V6)
  26271. + fwu->command = command & MASK_6BIT;
  26272. + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  26273. + fwu->command = command;
  26274. +
  26275. + if (fwu->write_bootloader)
  26276. + fwu->command = 0x00;
  26277. +
  26278. + return 0;
  26279. +}
  26280. +
  26281. +static int fwu_wait_for_idle(int timeout_ms, bool poll)
  26282. +{
  26283. + int count = 0;
  26284. + int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
  26285. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26286. +
  26287. + do {
  26288. + usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
  26289. +
  26290. + count++;
  26291. + if (poll || (count == timeout_count))
  26292. + fwu_read_flash_status();
  26293. +
  26294. + if ((fwu->command == CMD_IDLE) && (fwu->flash_status == 0x00))
  26295. + return 0;
  26296. + } while (count < timeout_count);
  26297. +
  26298. + dev_err(rmi4_data->pdev->dev.parent,
  26299. + "%s: Timed out waiting for idle status\n",
  26300. + __func__);
  26301. +
  26302. + return -ETIMEDOUT;
  26303. +}
  26304. +
  26305. +static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd)
  26306. +{
  26307. + int retval;
  26308. + unsigned char data_base;
  26309. + struct f34_v7_data_1_5 data_1_5;
  26310. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26311. +
  26312. + data_base = fwu->f34_fd.data_base_addr;
  26313. +
  26314. + memset(data_1_5.data, 0x00, sizeof(data_1_5.data));
  26315. +
  26316. + switch (cmd) {
  26317. + case CMD_ERASE_ALL:
  26318. + data_1_5.partition_id = CORE_CODE_PARTITION;
  26319. + data_1_5.command = CMD_V7_ERASE_AP;
  26320. + break;
  26321. + case CMD_ERASE_UI_FIRMWARE:
  26322. + data_1_5.partition_id = CORE_CODE_PARTITION;
  26323. + data_1_5.command = CMD_V7_ERASE;
  26324. + break;
  26325. + case CMD_ERASE_BL_CONFIG:
  26326. + data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION;
  26327. + data_1_5.command = CMD_V7_ERASE;
  26328. + break;
  26329. + case CMD_ERASE_UI_CONFIG:
  26330. + data_1_5.partition_id = CORE_CONFIG_PARTITION;
  26331. + data_1_5.command = CMD_V7_ERASE;
  26332. + break;
  26333. + case CMD_ERASE_DISP_CONFIG:
  26334. + data_1_5.partition_id = DISPLAY_CONFIG_PARTITION;
  26335. + data_1_5.command = CMD_V7_ERASE;
  26336. + break;
  26337. + case CMD_ERASE_FLASH_CONFIG:
  26338. + data_1_5.partition_id = FLASH_CONFIG_PARTITION;
  26339. + data_1_5.command = CMD_V7_ERASE;
  26340. + break;
  26341. + case CMD_ERASE_GUEST_CODE:
  26342. + data_1_5.partition_id = GUEST_CODE_PARTITION;
  26343. + data_1_5.command = CMD_V7_ERASE;
  26344. + break;
  26345. + case CMD_ERASE_BOOTLOADER:
  26346. + data_1_5.partition_id = BOOTLOADER_PARTITION;
  26347. + data_1_5.command = CMD_V7_ERASE;
  26348. + break;
  26349. + case CMD_ERASE_UTILITY_PARAMETER:
  26350. + data_1_5.partition_id = UTILITY_PARAMETER_PARTITION;
  26351. + data_1_5.command = CMD_V7_ERASE;
  26352. + break;
  26353. + case CMD_ENABLE_FLASH_PROG:
  26354. + data_1_5.partition_id = BOOTLOADER_PARTITION;
  26355. + data_1_5.command = CMD_V7_ENTER_BL;
  26356. + break;
  26357. + };
  26358. +
  26359. + data_1_5.payload_0 = fwu->bootloader_id[0];
  26360. + data_1_5.payload_1 = fwu->bootloader_id[1];
  26361. +
  26362. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26363. + data_base + fwu->off.partition_id,
  26364. + data_1_5.data,
  26365. + sizeof(data_1_5.data));
  26366. + if (retval < 0) {
  26367. + dev_err(rmi4_data->pdev->dev.parent,
  26368. + "%s: Failed to write single transaction command\n",
  26369. + __func__);
  26370. + return retval;
  26371. + }
  26372. +
  26373. + return 0;
  26374. +}
  26375. +
  26376. +static int fwu_write_f34_v7_command(unsigned char cmd)
  26377. +{
  26378. + int retval;
  26379. + unsigned char data_base;
  26380. + unsigned char command;
  26381. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26382. +
  26383. + data_base = fwu->f34_fd.data_base_addr;
  26384. +
  26385. + switch (cmd) {
  26386. + case CMD_WRITE_FW:
  26387. + case CMD_WRITE_CONFIG:
  26388. + case CMD_WRITE_LOCKDOWN:
  26389. + case CMD_WRITE_GUEST_CODE:
  26390. + case CMD_WRITE_BOOTLOADER:
  26391. + case CMD_WRITE_UTILITY_PARAM:
  26392. + command = CMD_V7_WRITE;
  26393. + break;
  26394. + case CMD_READ_CONFIG:
  26395. + command = CMD_V7_READ;
  26396. + break;
  26397. + case CMD_ERASE_ALL:
  26398. + command = CMD_V7_ERASE_AP;
  26399. + break;
  26400. + case CMD_ERASE_UI_FIRMWARE:
  26401. + case CMD_ERASE_BL_CONFIG:
  26402. + case CMD_ERASE_UI_CONFIG:
  26403. + case CMD_ERASE_DISP_CONFIG:
  26404. + case CMD_ERASE_FLASH_CONFIG:
  26405. + case CMD_ERASE_GUEST_CODE:
  26406. + case CMD_ERASE_BOOTLOADER:
  26407. + case CMD_ERASE_UTILITY_PARAMETER:
  26408. + command = CMD_V7_ERASE;
  26409. + break;
  26410. + case CMD_ENABLE_FLASH_PROG:
  26411. + command = CMD_V7_ENTER_BL;
  26412. + break;
  26413. + default:
  26414. + dev_err(rmi4_data->pdev->dev.parent,
  26415. + "%s: Invalid command 0x%02x\n",
  26416. + __func__, cmd);
  26417. + return -EINVAL;
  26418. + };
  26419. +
  26420. + fwu->command = command;
  26421. +
  26422. + switch (cmd) {
  26423. + case CMD_ERASE_ALL:
  26424. + case CMD_ERASE_UI_FIRMWARE:
  26425. + case CMD_ERASE_BL_CONFIG:
  26426. + case CMD_ERASE_UI_CONFIG:
  26427. + case CMD_ERASE_DISP_CONFIG:
  26428. + case CMD_ERASE_FLASH_CONFIG:
  26429. + case CMD_ERASE_GUEST_CODE:
  26430. + case CMD_ERASE_BOOTLOADER:
  26431. + case CMD_ERASE_UTILITY_PARAMETER:
  26432. + case CMD_ENABLE_FLASH_PROG:
  26433. + retval = fwu_write_f34_v7_command_single_transaction(cmd);
  26434. + if (retval < 0)
  26435. + return retval;
  26436. + else
  26437. + return 0;
  26438. + default:
  26439. + break;
  26440. + };
  26441. +
  26442. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26443. + data_base + fwu->off.flash_cmd,
  26444. + &command,
  26445. + sizeof(command));
  26446. + if (retval < 0) {
  26447. + dev_err(rmi4_data->pdev->dev.parent,
  26448. + "%s: Failed to write flash command\n",
  26449. + __func__);
  26450. + return retval;
  26451. + }
  26452. +
  26453. + return 0;
  26454. +}
  26455. +
  26456. +static int fwu_write_f34_v5v6_command(unsigned char cmd)
  26457. +{
  26458. + int retval;
  26459. + unsigned char data_base;
  26460. + unsigned char command;
  26461. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26462. +
  26463. + data_base = fwu->f34_fd.data_base_addr;
  26464. +
  26465. + switch (cmd) {
  26466. + case CMD_IDLE:
  26467. + command = CMD_V5V6_IDLE;
  26468. + break;
  26469. + case CMD_WRITE_FW:
  26470. + command = CMD_V5V6_WRITE_FW;
  26471. + break;
  26472. + case CMD_WRITE_CONFIG:
  26473. + command = CMD_V5V6_WRITE_CONFIG;
  26474. + break;
  26475. + case CMD_WRITE_LOCKDOWN:
  26476. + command = CMD_V5V6_WRITE_LOCKDOWN;
  26477. + break;
  26478. + case CMD_WRITE_GUEST_CODE:
  26479. + command = CMD_V5V6_WRITE_GUEST_CODE;
  26480. + break;
  26481. + case CMD_READ_CONFIG:
  26482. + command = CMD_V5V6_READ_CONFIG;
  26483. + break;
  26484. + case CMD_ERASE_ALL:
  26485. + command = CMD_V5V6_ERASE_ALL;
  26486. + break;
  26487. + case CMD_ERASE_UI_CONFIG:
  26488. + command = CMD_V5V6_ERASE_UI_CONFIG;
  26489. + break;
  26490. + case CMD_ERASE_DISP_CONFIG:
  26491. + command = CMD_V5V6_ERASE_DISP_CONFIG;
  26492. + break;
  26493. + case CMD_ERASE_GUEST_CODE:
  26494. + command = CMD_V5V6_ERASE_GUEST_CODE;
  26495. + break;
  26496. + case CMD_ENABLE_FLASH_PROG:
  26497. + command = CMD_V5V6_ENABLE_FLASH_PROG;
  26498. + break;
  26499. + case CMD_READ_LOCKDOWN_DATA:
  26500. + command = CMD_V5V6_READ_LOCKDOWN_DATA;
  26501. + break;
  26502. + default:
  26503. + dev_err(rmi4_data->pdev->dev.parent,
  26504. + "%s: Invalid command 0x%02x\n",
  26505. + __func__, cmd);
  26506. + return -EINVAL;
  26507. + }
  26508. +
  26509. + switch (cmd) {
  26510. + case CMD_ERASE_ALL:
  26511. + case CMD_ERASE_UI_CONFIG:
  26512. + case CMD_ERASE_DISP_CONFIG:
  26513. + case CMD_ERASE_GUEST_CODE:
  26514. + case CMD_ENABLE_FLASH_PROG:
  26515. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26516. + data_base + fwu->off.payload,
  26517. + fwu->bootloader_id,
  26518. + sizeof(fwu->bootloader_id));
  26519. + if (retval < 0) {
  26520. + dev_err(rmi4_data->pdev->dev.parent,
  26521. + "%s: Failed to write bootloader ID\n",
  26522. + __func__);
  26523. + return retval;
  26524. + }
  26525. + break;
  26526. + default:
  26527. + break;
  26528. + };
  26529. +
  26530. + fwu->command = command;
  26531. +
  26532. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26533. + data_base + fwu->off.flash_cmd,
  26534. + &command,
  26535. + sizeof(command));
  26536. + if (retval < 0) {
  26537. + dev_err(rmi4_data->pdev->dev.parent,
  26538. + "%s: Failed to write command 0x%02x\n",
  26539. + __func__, command);
  26540. + return retval;
  26541. + }
  26542. +
  26543. + return 0;
  26544. +}
  26545. +
  26546. +static int fwu_write_f34_command(unsigned char cmd)
  26547. +{
  26548. + int retval;
  26549. +
  26550. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  26551. + retval = fwu_write_f34_v7_command(cmd);
  26552. + else
  26553. + retval = fwu_write_f34_v5v6_command(cmd);
  26554. +
  26555. + return retval;
  26556. +}
  26557. +
  26558. +static int fwu_write_f34_v7_partition_id(unsigned char cmd)
  26559. +{
  26560. + int retval;
  26561. + unsigned char data_base;
  26562. + unsigned char partition;
  26563. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26564. +
  26565. + data_base = fwu->f34_fd.data_base_addr;
  26566. +
  26567. + switch (cmd) {
  26568. + case CMD_WRITE_FW:
  26569. + partition = CORE_CODE_PARTITION;
  26570. + break;
  26571. + case CMD_WRITE_CONFIG:
  26572. + case CMD_READ_CONFIG:
  26573. + if (fwu->config_area == UI_CONFIG_AREA)
  26574. + partition = CORE_CONFIG_PARTITION;
  26575. + else if (fwu->config_area == DP_CONFIG_AREA)
  26576. + partition = DISPLAY_CONFIG_PARTITION;
  26577. + else if (fwu->config_area == PM_CONFIG_AREA)
  26578. + partition = GUEST_SERIALIZATION_PARTITION;
  26579. + else if (fwu->config_area == BL_CONFIG_AREA)
  26580. + partition = GLOBAL_PARAMETERS_PARTITION;
  26581. + else if (fwu->config_area == FLASH_CONFIG_AREA)
  26582. + partition = FLASH_CONFIG_PARTITION;
  26583. + break;
  26584. + case CMD_WRITE_LOCKDOWN:
  26585. + partition = DEVICE_CONFIG_PARTITION;
  26586. + break;
  26587. + case CMD_WRITE_GUEST_CODE:
  26588. + partition = GUEST_CODE_PARTITION;
  26589. + break;
  26590. + case CMD_WRITE_BOOTLOADER:
  26591. + partition = BOOTLOADER_PARTITION;
  26592. + break;
  26593. + case CMD_WRITE_UTILITY_PARAM:
  26594. + partition = UTILITY_PARAMETER_PARTITION;
  26595. + break;
  26596. + case CMD_ERASE_ALL:
  26597. + partition = CORE_CODE_PARTITION;
  26598. + break;
  26599. + case CMD_ERASE_BL_CONFIG:
  26600. + partition = GLOBAL_PARAMETERS_PARTITION;
  26601. + break;
  26602. + case CMD_ERASE_UI_CONFIG:
  26603. + partition = CORE_CONFIG_PARTITION;
  26604. + break;
  26605. + case CMD_ERASE_DISP_CONFIG:
  26606. + partition = DISPLAY_CONFIG_PARTITION;
  26607. + break;
  26608. + case CMD_ERASE_FLASH_CONFIG:
  26609. + partition = FLASH_CONFIG_PARTITION;
  26610. + break;
  26611. + case CMD_ERASE_GUEST_CODE:
  26612. + partition = GUEST_CODE_PARTITION;
  26613. + break;
  26614. + case CMD_ERASE_BOOTLOADER:
  26615. + partition = BOOTLOADER_PARTITION;
  26616. + break;
  26617. + case CMD_ENABLE_FLASH_PROG:
  26618. + partition = BOOTLOADER_PARTITION;
  26619. + break;
  26620. + default:
  26621. + dev_err(rmi4_data->pdev->dev.parent,
  26622. + "%s: Invalid command 0x%02x\n",
  26623. + __func__, cmd);
  26624. + return -EINVAL;
  26625. + };
  26626. +
  26627. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26628. + data_base + fwu->off.partition_id,
  26629. + &partition,
  26630. + sizeof(partition));
  26631. + if (retval < 0) {
  26632. + dev_err(rmi4_data->pdev->dev.parent,
  26633. + "%s: Failed to write partition ID\n",
  26634. + __func__);
  26635. + return retval;
  26636. + }
  26637. +
  26638. + return 0;
  26639. +}
  26640. +
  26641. +static int fwu_write_f34_partition_id(unsigned char cmd)
  26642. +{
  26643. + int retval;
  26644. +
  26645. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  26646. + retval = fwu_write_f34_v7_partition_id(cmd);
  26647. + else
  26648. + retval = 0;
  26649. +
  26650. + return retval;
  26651. +}
  26652. +
  26653. +static int fwu_read_f34_v7_partition_table(unsigned char *partition_table)
  26654. +{
  26655. + int retval;
  26656. + unsigned char data_base;
  26657. + unsigned char length[2];
  26658. + unsigned short block_number = 0;
  26659. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26660. +
  26661. + data_base = fwu->f34_fd.data_base_addr;
  26662. +
  26663. + fwu->config_area = FLASH_CONFIG_AREA;
  26664. +
  26665. + retval = fwu_write_f34_partition_id(CMD_READ_CONFIG);
  26666. + if (retval < 0)
  26667. + return retval;
  26668. +
  26669. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26670. + data_base + fwu->off.block_number,
  26671. + (unsigned char *)&block_number,
  26672. + sizeof(block_number));
  26673. + if (retval < 0) {
  26674. + dev_err(rmi4_data->pdev->dev.parent,
  26675. + "%s: Failed to write block number\n",
  26676. + __func__);
  26677. + return retval;
  26678. + }
  26679. +
  26680. + length[0] = (unsigned char)(fwu->flash_config_length & MASK_8BIT);
  26681. + length[1] = (unsigned char)(fwu->flash_config_length >> 8);
  26682. +
  26683. + retval = synaptics_rmi4_reg_write(rmi4_data,
  26684. + data_base + fwu->off.transfer_length,
  26685. + length,
  26686. + sizeof(length));
  26687. + if (retval < 0) {
  26688. + dev_err(rmi4_data->pdev->dev.parent,
  26689. + "%s: Failed to write transfer length\n",
  26690. + __func__);
  26691. + return retval;
  26692. + }
  26693. +
  26694. + retval = fwu_write_f34_command(CMD_READ_CONFIG);
  26695. + if (retval < 0) {
  26696. + dev_err(rmi4_data->pdev->dev.parent,
  26697. + "%s: Failed to write command\n",
  26698. + __func__);
  26699. + return retval;
  26700. + }
  26701. +
  26702. + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true);
  26703. + if (retval < 0) {
  26704. + dev_err(rmi4_data->pdev->dev.parent,
  26705. + "%s: Failed to wait for idle status\n",
  26706. + __func__);
  26707. + return retval;
  26708. + }
  26709. +
  26710. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26711. + data_base + fwu->off.payload,
  26712. + partition_table,
  26713. + fwu->partition_table_bytes);
  26714. + if (retval < 0) {
  26715. + dev_err(rmi4_data->pdev->dev.parent,
  26716. + "%s: Failed to read block data\n",
  26717. + __func__);
  26718. + return retval;
  26719. + }
  26720. +
  26721. + return 0;
  26722. +}
  26723. +
  26724. +static int fwu_read_f34_v7_queries(void)
  26725. +{
  26726. + int retval;
  26727. + unsigned char ii;
  26728. + unsigned char query_base;
  26729. + unsigned char index;
  26730. + unsigned char offset;
  26731. + unsigned char *ptable;
  26732. + struct f34_v7_query_0 query_0;
  26733. + struct f34_v7_query_1_7 query_1_7;
  26734. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26735. +
  26736. + query_base = fwu->f34_fd.query_base_addr;
  26737. +
  26738. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26739. + query_base,
  26740. + query_0.data,
  26741. + sizeof(query_0.data));
  26742. + if (retval < 0) {
  26743. + dev_err(rmi4_data->pdev->dev.parent,
  26744. + "%s: Failed to read query 0\n",
  26745. + __func__);
  26746. + return retval;
  26747. + }
  26748. +
  26749. + offset = query_0.subpacket_1_size + 1;
  26750. +
  26751. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26752. + query_base + offset,
  26753. + query_1_7.data,
  26754. + sizeof(query_1_7.data));
  26755. + if (retval < 0) {
  26756. + dev_err(rmi4_data->pdev->dev.parent,
  26757. + "%s: Failed to read queries 1 to 7\n",
  26758. + __func__);
  26759. + return retval;
  26760. + }
  26761. +
  26762. + fwu->bootloader_id[0] = query_1_7.bl_minor_revision;
  26763. + fwu->bootloader_id[1] = query_1_7.bl_major_revision;
  26764. +
  26765. + if (fwu->bootloader_id[1] == BL_V8)
  26766. + fwu->bl_version = BL_V8;
  26767. +
  26768. + fwu->block_size = query_1_7.block_size_15_8 << 8 |
  26769. + query_1_7.block_size_7_0;
  26770. +
  26771. + fwu->flash_config_length = query_1_7.flash_config_length_15_8 << 8 |
  26772. + query_1_7.flash_config_length_7_0;
  26773. +
  26774. + fwu->payload_length = query_1_7.payload_length_15_8 << 8 |
  26775. + query_1_7.payload_length_7_0;
  26776. +
  26777. + fwu->off.flash_status = V7_FLASH_STATUS_OFFSET;
  26778. + fwu->off.partition_id = V7_PARTITION_ID_OFFSET;
  26779. + fwu->off.block_number = V7_BLOCK_NUMBER_OFFSET;
  26780. + fwu->off.transfer_length = V7_TRANSFER_LENGTH_OFFSET;
  26781. + fwu->off.flash_cmd = V7_COMMAND_OFFSET;
  26782. + fwu->off.payload = V7_PAYLOAD_OFFSET;
  26783. +
  26784. + index = sizeof(query_1_7.data) - V7_PARTITION_SUPPORT_BYTES;
  26785. +
  26786. + fwu->partitions = 0;
  26787. + for (offset = 0; offset < V7_PARTITION_SUPPORT_BYTES; offset++) {
  26788. + for (ii = 0; ii < 8; ii++) {
  26789. + if (query_1_7.data[index + offset] & (1 << ii))
  26790. + fwu->partitions++;
  26791. + }
  26792. +
  26793. + dev_dbg(rmi4_data->pdev->dev.parent,
  26794. + "%s: Supported partitions: 0x%02x\n",
  26795. + __func__, query_1_7.data[index + offset]);
  26796. + }
  26797. +
  26798. + fwu->partition_table_bytes = fwu->partitions * 8 + 2;
  26799. +
  26800. + ptable = kzalloc(fwu->partition_table_bytes, GFP_KERNEL);
  26801. + if (!ptable) {
  26802. + dev_err(rmi4_data->pdev->dev.parent,
  26803. + "%s: Failed to alloc mem for partition table\n",
  26804. + __func__);
  26805. + return -ENOMEM;
  26806. + }
  26807. +
  26808. + retval = fwu_read_f34_v7_partition_table(ptable);
  26809. + if (retval < 0) {
  26810. + dev_err(rmi4_data->pdev->dev.parent,
  26811. + "%s: Failed to read partition table\n",
  26812. + __func__);
  26813. + kfree(ptable);
  26814. + return retval;
  26815. + }
  26816. +
  26817. + fwu_parse_partition_table(ptable, &fwu->blkcount, &fwu->phyaddr);
  26818. +
  26819. + if (fwu->blkcount.dp_config)
  26820. + fwu->flash_properties.has_disp_config = 1;
  26821. + else
  26822. + fwu->flash_properties.has_disp_config = 0;
  26823. +
  26824. + if (fwu->blkcount.pm_config)
  26825. + fwu->flash_properties.has_pm_config = 1;
  26826. + else
  26827. + fwu->flash_properties.has_pm_config = 0;
  26828. +
  26829. + if (fwu->blkcount.bl_config)
  26830. + fwu->flash_properties.has_bl_config = 1;
  26831. + else
  26832. + fwu->flash_properties.has_bl_config = 0;
  26833. +
  26834. + if (fwu->blkcount.guest_code)
  26835. + fwu->has_guest_code = 1;
  26836. + else
  26837. + fwu->has_guest_code = 0;
  26838. +
  26839. + if (fwu->blkcount.utility_param)
  26840. + fwu->has_utility_param = 1;
  26841. + else
  26842. + fwu->has_utility_param = 0;
  26843. +
  26844. + kfree(ptable);
  26845. +
  26846. + if (rmi4_data->hw_if->board_data->lockdown_area == LOCKDOWN_AREA_GUEST_SERIALIZATION)
  26847. + fwu_read_f34_guest_serialization_partition();
  26848. +
  26849. + return 0;
  26850. +}
  26851. +
  26852. +static int fwu_read_f34_lockdown_data(void)
  26853. +{
  26854. + int retval = 0;
  26855. + unsigned short block_count;
  26856. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26857. +
  26858. + if (!fwu->has_lockdown_data)
  26859. + return -EINVAL;
  26860. +
  26861. + block_count = fwu->blkcount.lockdown_data;
  26862. + fwu->config_area = UI_CONFIG_AREA;
  26863. + fwu->config_size = fwu->block_size * block_count;
  26864. +
  26865. + retval = fwu_allocate_read_config_buf(fwu->config_size);
  26866. + if (retval < 0)
  26867. + return retval;
  26868. +
  26869. + retval = fwu_read_f34_blocks(block_count, CMD_READ_LOCKDOWN_DATA);
  26870. + if (retval < 0)
  26871. + return retval;
  26872. +
  26873. + secure_memcpy(rmi4_data->lockdown_info, LOCKDOWN_INFO_SIZE,
  26874. + &fwu->read_config_buf[4], fwu->read_config_buf_size, LOCKDOWN_INFO_SIZE);
  26875. +
  26876. + dev_info(rmi4_data->pdev->dev.parent,
  26877. + "%s: Lockdown info: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  26878. + __func__, fwu->read_config_buf[4], fwu->read_config_buf[5],
  26879. + fwu->read_config_buf[6], fwu->read_config_buf[7],
  26880. + fwu->read_config_buf[8], fwu->read_config_buf[9],
  26881. + fwu->read_config_buf[10], fwu->read_config_buf[11]);
  26882. +
  26883. + return retval;
  26884. +}
  26885. +
  26886. +static int fwu_read_f34_v5v6_queries(void)
  26887. +{
  26888. + int retval;
  26889. + unsigned char count;
  26890. + unsigned char query_base;
  26891. + unsigned char buf[10];
  26892. + struct f34_v5v6_flash_properties_2 properties_2;
  26893. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  26894. +
  26895. + query_base = fwu->f34_fd.query_base_addr;
  26896. +
  26897. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26898. + query_base + V5V6_BOOTLOADER_ID_OFFSET,
  26899. + fwu->bootloader_id,
  26900. + sizeof(fwu->bootloader_id));
  26901. + if (retval < 0) {
  26902. + dev_err(rmi4_data->pdev->dev.parent,
  26903. + "%s: Failed to read bootloader ID\n",
  26904. + __func__);
  26905. + return retval;
  26906. + }
  26907. +
  26908. + if (fwu->bl_version == BL_V5) {
  26909. + fwu->off.properties = V5_PROPERTIES_OFFSET;
  26910. + fwu->off.block_size = V5_BLOCK_SIZE_OFFSET;
  26911. + fwu->off.block_count = V5_BLOCK_COUNT_OFFSET;
  26912. + fwu->off.block_number = V5_BLOCK_NUMBER_OFFSET;
  26913. + fwu->off.payload = V5_BLOCK_DATA_OFFSET;
  26914. + } else if (fwu->bl_version == BL_V6) {
  26915. + fwu->off.properties = V6_PROPERTIES_OFFSET;
  26916. + fwu->off.properties_2 = V6_PROPERTIES_2_OFFSET;
  26917. + fwu->off.block_size = V6_BLOCK_SIZE_OFFSET;
  26918. + fwu->off.block_count = V6_BLOCK_COUNT_OFFSET;
  26919. + fwu->off.block_number = V6_BLOCK_NUMBER_OFFSET;
  26920. + fwu->off.payload = V6_BLOCK_DATA_OFFSET;
  26921. + }
  26922. +
  26923. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26924. + query_base + fwu->off.block_size,
  26925. + buf,
  26926. + 2);
  26927. + if (retval < 0) {
  26928. + dev_err(rmi4_data->pdev->dev.parent,
  26929. + "%s: Failed to read block size info\n",
  26930. + __func__);
  26931. + return retval;
  26932. + }
  26933. +
  26934. + batohs(&fwu->block_size, &(buf[0]));
  26935. +
  26936. + if (fwu->bl_version == BL_V5) {
  26937. + fwu->off.flash_cmd = fwu->off.payload + fwu->block_size;
  26938. + fwu->off.flash_status = fwu->off.flash_cmd;
  26939. + } else if (fwu->bl_version == BL_V6) {
  26940. + fwu->off.flash_cmd = V6_FLASH_COMMAND_OFFSET;
  26941. + fwu->off.flash_status = V6_FLASH_STATUS_OFFSET;
  26942. + }
  26943. +
  26944. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26945. + query_base + fwu->off.properties,
  26946. + fwu->flash_properties.data,
  26947. + sizeof(fwu->flash_properties.data));
  26948. + if (retval < 0) {
  26949. + dev_err(rmi4_data->pdev->dev.parent,
  26950. + "%s: Failed to read flash properties\n",
  26951. + __func__);
  26952. + return retval;
  26953. + }
  26954. +
  26955. + count = 4;
  26956. +
  26957. + if (fwu->flash_properties.has_pm_config)
  26958. + count += 2;
  26959. +
  26960. + if (fwu->flash_properties.has_bl_config)
  26961. + count += 2;
  26962. +
  26963. + if (fwu->flash_properties.has_disp_config)
  26964. + count += 2;
  26965. +
  26966. + retval = synaptics_rmi4_reg_read(rmi4_data,
  26967. + query_base + fwu->off.block_count,
  26968. + buf,
  26969. + count);
  26970. + if (retval < 0) {
  26971. + dev_err(rmi4_data->pdev->dev.parent,
  26972. + "%s: Failed to read block count info\n",
  26973. + __func__);
  26974. + return retval;
  26975. + }
  26976. +
  26977. + batohs(&fwu->blkcount.ui_firmware, &(buf[0]));
  26978. + batohs(&fwu->blkcount.ui_config, &(buf[2]));
  26979. +
  26980. + count = 4;
  26981. +
  26982. + if (fwu->flash_properties.has_pm_config) {
  26983. + batohs(&fwu->blkcount.pm_config, &(buf[count]));
  26984. + count += 2;
  26985. + }
  26986. +
  26987. + if (fwu->flash_properties.has_bl_config) {
  26988. + batohs(&fwu->blkcount.bl_config, &(buf[count]));
  26989. + count += 2;
  26990. + }
  26991. +
  26992. + if (fwu->flash_properties.has_disp_config)
  26993. + batohs(&fwu->blkcount.dp_config, &(buf[count]));
  26994. +
  26995. + fwu->has_guest_code = false;
  26996. +
  26997. + fwu->has_lockdown_data = false;
  26998. +
  26999. + if (fwu->flash_properties.has_query4) {
  27000. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27001. + query_base + fwu->off.properties_2,
  27002. + properties_2.data,
  27003. + sizeof(properties_2.data));
  27004. + if (retval < 0) {
  27005. + dev_err(rmi4_data->pdev->dev.parent,
  27006. + "%s: Failed to read flash properties 2\n",
  27007. + __func__);
  27008. + return retval;
  27009. + }
  27010. +
  27011. + count = 0;
  27012. +
  27013. + if (properties_2.has_guest_code) {
  27014. + count++;
  27015. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27016. + query_base + fwu->off.properties_2 + count,
  27017. + buf,
  27018. + 2);
  27019. + if (retval < 0) {
  27020. + dev_err(rmi4_data->pdev->dev.parent,
  27021. + "%s: Failed to read guest code block count\n",
  27022. + __func__);
  27023. + return retval;
  27024. + }
  27025. +
  27026. + batohs(&fwu->blkcount.guest_code, &(buf[0]));
  27027. + fwu->has_guest_code = true;
  27028. + }
  27029. +
  27030. + if (properties_2.has_gesture_config_area)
  27031. + count++;
  27032. +
  27033. + if (properties_2.has_force_config_block)
  27034. + count++;
  27035. +
  27036. + if (properties_2.has_lockdown_data_block) {
  27037. + count++;
  27038. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27039. + query_base + fwu->off.properties_2 + count,
  27040. + buf,
  27041. + 2);
  27042. + if (retval < 0) {
  27043. + dev_err(rmi4_data->pdev->dev.parent,
  27044. + "%s: Failed to read lockdown data block count\n",
  27045. + __func__);
  27046. + return retval;
  27047. + }
  27048. +
  27049. + batohs(&fwu->blkcount.lockdown_data, &(buf[0]));
  27050. + fwu->has_lockdown_data = true;
  27051. +
  27052. + fwu_read_f34_lockdown_data();
  27053. + }
  27054. + }
  27055. +
  27056. + fwu->has_utility_param = false;
  27057. +
  27058. + return 0;
  27059. +}
  27060. +
  27061. +static int fwu_read_f34_queries(void)
  27062. +{
  27063. + int retval;
  27064. +
  27065. + memset(&fwu->blkcount, 0x00, sizeof(fwu->blkcount));
  27066. + memset(&fwu->phyaddr, 0x00, sizeof(fwu->phyaddr));
  27067. +
  27068. + if (fwu->bl_version == BL_V7)
  27069. + retval = fwu_read_f34_v7_queries();
  27070. + else
  27071. + retval = fwu_read_f34_v5v6_queries();
  27072. +
  27073. + return retval;
  27074. +}
  27075. +
  27076. +static int fwu_write_f34_v7_blocks(unsigned char *block_ptr,
  27077. + unsigned short block_cnt, unsigned char command)
  27078. +{
  27079. + int retval;
  27080. + unsigned char data_base;
  27081. + unsigned char length[2];
  27082. + unsigned short transfer;
  27083. + unsigned short remaining = block_cnt;
  27084. + unsigned short block_number = 0;
  27085. + unsigned short left_bytes;
  27086. + unsigned short write_size;
  27087. + unsigned short max_write_size;
  27088. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27089. +
  27090. + data_base = fwu->f34_fd.data_base_addr;
  27091. +
  27092. + retval = fwu_write_f34_partition_id(command);
  27093. + if (retval < 0)
  27094. + return retval;
  27095. +
  27096. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27097. + data_base + fwu->off.block_number,
  27098. + (unsigned char *)&block_number,
  27099. + sizeof(block_number));
  27100. + if (retval < 0) {
  27101. + dev_err(rmi4_data->pdev->dev.parent,
  27102. + "%s: Failed to write block number\n",
  27103. + __func__);
  27104. + return retval;
  27105. + }
  27106. +
  27107. + do {
  27108. + if (remaining / fwu->payload_length)
  27109. + transfer = fwu->payload_length;
  27110. + else
  27111. + transfer = remaining;
  27112. +
  27113. + length[0] = (unsigned char)(transfer & MASK_8BIT);
  27114. + length[1] = (unsigned char)(transfer >> 8);
  27115. +
  27116. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27117. + data_base + fwu->off.transfer_length,
  27118. + length,
  27119. + sizeof(length));
  27120. + if (retval < 0) {
  27121. + dev_err(rmi4_data->pdev->dev.parent,
  27122. + "%s: Failed to write transfer length (remaining = %d)\n",
  27123. + __func__, remaining);
  27124. + return retval;
  27125. + }
  27126. +
  27127. + retval = fwu_write_f34_command(command);
  27128. + if (retval < 0) {
  27129. + dev_err(rmi4_data->pdev->dev.parent,
  27130. + "%s: Failed to write command (remaining = %d)\n",
  27131. + __func__, remaining);
  27132. + return retval;
  27133. + }
  27134. +
  27135. +#ifdef MAX_WRITE_SIZE
  27136. + max_write_size = MAX_WRITE_SIZE;
  27137. + if (max_write_size >= transfer * fwu->block_size)
  27138. + max_write_size = transfer * fwu->block_size;
  27139. + else if (max_write_size > fwu->block_size)
  27140. + max_write_size -= max_write_size % fwu->block_size;
  27141. + else
  27142. + max_write_size = fwu->block_size;
  27143. +#else
  27144. + max_write_size = transfer * fwu->block_size;
  27145. +#endif
  27146. + left_bytes = transfer * fwu->block_size;
  27147. +
  27148. + do {
  27149. + if (left_bytes / max_write_size)
  27150. + write_size = max_write_size;
  27151. + else
  27152. + write_size = left_bytes;
  27153. +
  27154. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27155. + data_base + fwu->off.payload,
  27156. + block_ptr,
  27157. + write_size);
  27158. + if (retval < 0) {
  27159. + dev_err(rmi4_data->pdev->dev.parent,
  27160. + "%s: Failed to write block data (remaining = %d)\n",
  27161. + __func__, remaining);
  27162. + return retval;
  27163. + }
  27164. +
  27165. + block_ptr += write_size;
  27166. + left_bytes -= write_size;
  27167. + } while (left_bytes);
  27168. +
  27169. + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false);
  27170. + if (retval < 0) {
  27171. + dev_err(rmi4_data->pdev->dev.parent,
  27172. + "%s: Failed to wait for idle status (remaining = %d)\n",
  27173. + __func__, remaining);
  27174. + return retval;
  27175. + }
  27176. +
  27177. + remaining -= transfer;
  27178. + } while (remaining);
  27179. +
  27180. + return 0;
  27181. +}
  27182. +
  27183. +static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr,
  27184. + unsigned short block_cnt, unsigned char command)
  27185. +{
  27186. + int retval;
  27187. + unsigned char data_base;
  27188. + unsigned char block_number[] = {0, 0};
  27189. + unsigned short blk;
  27190. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27191. +
  27192. + data_base = fwu->f34_fd.data_base_addr;
  27193. +
  27194. + block_number[1] |= (fwu->config_area << 5);
  27195. +
  27196. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27197. + data_base + fwu->off.block_number,
  27198. + block_number,
  27199. + sizeof(block_number));
  27200. + if (retval < 0) {
  27201. + dev_err(rmi4_data->pdev->dev.parent,
  27202. + "%s: Failed to write block number\n",
  27203. + __func__);
  27204. + return retval;
  27205. + }
  27206. +
  27207. + for (blk = 0; blk < block_cnt; blk++) {
  27208. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27209. + data_base + fwu->off.payload,
  27210. + block_ptr,
  27211. + fwu->block_size);
  27212. + if (retval < 0) {
  27213. + dev_err(rmi4_data->pdev->dev.parent,
  27214. + "%s: Failed to write block data (block %d)\n",
  27215. + __func__, blk);
  27216. + return retval;
  27217. + }
  27218. +
  27219. + retval = fwu_write_f34_command(command);
  27220. + if (retval < 0) {
  27221. + dev_err(rmi4_data->pdev->dev.parent,
  27222. + "%s: Failed to write command for block %d\n",
  27223. + __func__, blk);
  27224. + return retval;
  27225. + }
  27226. +
  27227. + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false);
  27228. + if (retval < 0) {
  27229. + dev_err(rmi4_data->pdev->dev.parent,
  27230. + "%s: Failed to wait for idle status (block %d)\n",
  27231. + __func__, blk);
  27232. + return retval;
  27233. + }
  27234. +
  27235. + block_ptr += fwu->block_size;
  27236. + }
  27237. +
  27238. + return 0;
  27239. +}
  27240. +
  27241. +static int fwu_write_f34_blocks(unsigned char *block_ptr,
  27242. + unsigned short block_cnt, unsigned char cmd)
  27243. +{
  27244. + int retval;
  27245. +
  27246. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  27247. + retval = fwu_write_f34_v7_blocks(block_ptr, block_cnt, cmd);
  27248. + else
  27249. + retval = fwu_write_f34_v5v6_blocks(block_ptr, block_cnt, cmd);
  27250. +
  27251. + return retval;
  27252. +}
  27253. +
  27254. +static int fwu_read_f34_v7_blocks(unsigned short block_cnt,
  27255. + unsigned char command)
  27256. +{
  27257. + int retval;
  27258. + unsigned char data_base;
  27259. + unsigned char length[2];
  27260. + unsigned short transfer;
  27261. + unsigned short remaining = block_cnt;
  27262. + unsigned short block_number = 0;
  27263. + unsigned short index = 0;
  27264. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27265. +
  27266. + data_base = fwu->f34_fd.data_base_addr;
  27267. +
  27268. + retval = fwu_write_f34_partition_id(command);
  27269. + if (retval < 0)
  27270. + return retval;
  27271. +
  27272. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27273. + data_base + fwu->off.block_number,
  27274. + (unsigned char *)&block_number,
  27275. + sizeof(block_number));
  27276. + if (retval < 0) {
  27277. + dev_err(rmi4_data->pdev->dev.parent,
  27278. + "%s: Failed to write block number\n",
  27279. + __func__);
  27280. + return retval;
  27281. + }
  27282. +
  27283. + do {
  27284. + if (remaining / fwu->payload_length)
  27285. + transfer = fwu->payload_length;
  27286. + else
  27287. + transfer = remaining;
  27288. +
  27289. + length[0] = (unsigned char)(transfer & MASK_8BIT);
  27290. + length[1] = (unsigned char)(transfer >> 8);
  27291. +
  27292. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27293. + data_base + fwu->off.transfer_length,
  27294. + length,
  27295. + sizeof(length));
  27296. + if (retval < 0) {
  27297. + dev_err(rmi4_data->pdev->dev.parent,
  27298. + "%s: Failed to write transfer length (remaining = %d)\n",
  27299. + __func__, remaining);
  27300. + return retval;
  27301. + }
  27302. +
  27303. + retval = fwu_write_f34_command(command);
  27304. + if (retval < 0) {
  27305. + dev_err(rmi4_data->pdev->dev.parent,
  27306. + "%s: Failed to write command (remaining = %d)\n",
  27307. + __func__, remaining);
  27308. + return retval;
  27309. + }
  27310. +
  27311. + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true);
  27312. + if (retval < 0) {
  27313. + dev_err(rmi4_data->pdev->dev.parent,
  27314. + "%s: Failed to wait for idle status (remaining = %d)\n",
  27315. + __func__, remaining);
  27316. + return retval;
  27317. + }
  27318. +
  27319. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27320. + data_base + fwu->off.payload,
  27321. + &fwu->read_config_buf[index],
  27322. + transfer * fwu->block_size);
  27323. + if (retval < 0) {
  27324. + dev_err(rmi4_data->pdev->dev.parent,
  27325. + "%s: Failed to read block data (remaining = %d)\n",
  27326. + __func__, remaining);
  27327. + return retval;
  27328. + }
  27329. +
  27330. + index += (transfer * fwu->block_size);
  27331. + remaining -= transfer;
  27332. + } while (remaining);
  27333. +
  27334. + return 0;
  27335. +}
  27336. +
  27337. +static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt,
  27338. + unsigned char command)
  27339. +{
  27340. + int retval;
  27341. + unsigned char data_base;
  27342. + unsigned char block_number[] = {0, 0};
  27343. + unsigned short blk;
  27344. + unsigned short index = 0;
  27345. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27346. +
  27347. + data_base = fwu->f34_fd.data_base_addr;
  27348. +
  27349. + block_number[1] |= (fwu->config_area << 5);
  27350. +
  27351. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27352. + data_base + fwu->off.block_number,
  27353. + block_number,
  27354. + sizeof(block_number));
  27355. + if (retval < 0) {
  27356. + dev_err(rmi4_data->pdev->dev.parent,
  27357. + "%s: Failed to write block number\n",
  27358. + __func__);
  27359. + return retval;
  27360. + }
  27361. +
  27362. + for (blk = 0; blk < block_cnt; blk++) {
  27363. + retval = fwu_write_f34_command(command);
  27364. + if (retval < 0) {
  27365. + dev_err(rmi4_data->pdev->dev.parent,
  27366. + "%s: Failed to write read config command\n",
  27367. + __func__);
  27368. + return retval;
  27369. + }
  27370. +
  27371. + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true);
  27372. + if (retval < 0) {
  27373. + dev_err(rmi4_data->pdev->dev.parent,
  27374. + "%s: Failed to wait for idle status\n",
  27375. + __func__);
  27376. + return retval;
  27377. + }
  27378. +
  27379. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27380. + data_base + fwu->off.payload,
  27381. + &fwu->read_config_buf[index],
  27382. + fwu->block_size);
  27383. + if (retval < 0) {
  27384. + dev_err(rmi4_data->pdev->dev.parent,
  27385. + "%s: Failed to read block data (block %d)\n",
  27386. + __func__, blk);
  27387. + return retval;
  27388. + }
  27389. +
  27390. + index += fwu->block_size;
  27391. + }
  27392. +
  27393. + return 0;
  27394. +}
  27395. +
  27396. +static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd)
  27397. +{
  27398. + int retval;
  27399. +
  27400. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  27401. + retval = fwu_read_f34_v7_blocks(block_cnt, cmd);
  27402. + else
  27403. + retval = fwu_read_f34_v5v6_blocks(block_cnt, cmd);
  27404. +
  27405. + return retval;
  27406. +}
  27407. +
  27408. +static int fwu_read_f34_guest_serialization_partition(void)
  27409. +{
  27410. + int retval = 0;
  27411. + unsigned short block_count;
  27412. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27413. +
  27414. + fwu->config_area = PM_CONFIG_AREA;
  27415. + if (!fwu->flash_properties.has_pm_config) {
  27416. + dev_err(rmi4_data->pdev->dev.parent,
  27417. + "%s: Permanent configuration not supported\n",
  27418. + __func__);
  27419. + return -EINVAL;
  27420. + }
  27421. + block_count = fwu->blkcount.pm_config;
  27422. +
  27423. + fwu->config_size = fwu->block_size * block_count;
  27424. + kfree(fwu->read_config_buf);
  27425. + fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
  27426. + if (!fwu->read_config_buf) {
  27427. + dev_err(rmi4_data->pdev->dev.parent,
  27428. + "%s: Failed to alloc mem for fwu->read_config_buf\n",
  27429. + __func__);
  27430. + fwu->read_config_buf_size = 0;
  27431. + retval = -ENOMEM;
  27432. + return retval;
  27433. + }
  27434. + fwu->read_config_buf_size = fwu->config_size;
  27435. +
  27436. + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG);
  27437. + if (retval < 0) {
  27438. + dev_err(rmi4_data->pdev->dev.parent,
  27439. + "%s: Failed to get guest serialization partition\n",
  27440. + __func__);
  27441. + return retval;
  27442. + }
  27443. +
  27444. + secure_memcpy(rmi4_data->lockdown_info, LOCKDOWN_INFO_SIZE,
  27445. + fwu->read_config_buf, fwu->read_config_buf_size, LOCKDOWN_INFO_SIZE);
  27446. +
  27447. + dev_info(rmi4_data->pdev->dev.parent,
  27448. + "%s: Lockdown info: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  27449. + __func__, fwu->read_config_buf[0], fwu->read_config_buf[1],
  27450. + fwu->read_config_buf[2], fwu->read_config_buf[3],
  27451. + fwu->read_config_buf[4], fwu->read_config_buf[5],
  27452. + fwu->read_config_buf[6], fwu->read_config_buf[7]);
  27453. +
  27454. + return retval;
  27455. +}
  27456. +
  27457. +static int fwu_get_image_firmware_id(unsigned int *fw_id)
  27458. +{
  27459. + int retval;
  27460. + unsigned char index = 0;
  27461. + char *strptr;
  27462. + char *firmware_id;
  27463. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27464. +
  27465. + if (fwu->img.contains_firmware_id) {
  27466. + *fw_id = fwu->img.firmware_id;
  27467. + } else {
  27468. + strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN);
  27469. + if (!strptr) {
  27470. + dev_err(rmi4_data->pdev->dev.parent,
  27471. + "%s: No valid PR number (PRxxxxxxx) "
  27472. + "found in image file name (%s)\n",
  27473. + __func__, fwu->image_name);
  27474. + return -EINVAL;
  27475. + }
  27476. +
  27477. + strptr += 2;
  27478. + firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL);
  27479. + if (!firmware_id) {
  27480. + dev_err(rmi4_data->pdev->dev.parent,
  27481. + "%s: Failed to alloc mem for firmware_id\n",
  27482. + __func__);
  27483. + return -ENOMEM;
  27484. + }
  27485. + while (strptr[index] >= '0' && strptr[index] <= '9') {
  27486. + firmware_id[index] = strptr[index];
  27487. + index++;
  27488. + }
  27489. +
  27490. + retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id);
  27491. + kfree(firmware_id);
  27492. + if (retval) {
  27493. + dev_err(rmi4_data->pdev->dev.parent,
  27494. + "%s: Failed to obtain image firmware ID\n",
  27495. + __func__);
  27496. + return -EINVAL;
  27497. + }
  27498. + }
  27499. +
  27500. + return 0;
  27501. +}
  27502. +
  27503. +static int fwu_get_device_config_id(void)
  27504. +{
  27505. + int retval;
  27506. + unsigned char config_id_size;
  27507. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27508. +
  27509. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  27510. + config_id_size = V7_CONFIG_ID_SIZE;
  27511. + else
  27512. + config_id_size = V5V6_CONFIG_ID_SIZE;
  27513. +
  27514. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27515. + fwu->f34_fd.ctrl_base_addr,
  27516. + fwu->config_id,
  27517. + config_id_size);
  27518. + if (retval < 0)
  27519. + return retval;
  27520. +
  27521. + return 0;
  27522. +}
  27523. +
  27524. +static enum flash_area fwu_go_nogo(void)
  27525. +{
  27526. + int retval;
  27527. + enum flash_area flash_area = NONE;
  27528. + unsigned char ii;
  27529. + unsigned char config_id_size;
  27530. + unsigned int device_fw_id;
  27531. + unsigned int image_fw_id;
  27532. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27533. +
  27534. + if (fwu->force_update) {
  27535. + flash_area = UI_FIRMWARE;
  27536. + goto exit;
  27537. + }
  27538. +
  27539. + /* Update both UI and config if device is in bootloader mode */
  27540. + if (fwu->bl_mode_device) {
  27541. + flash_area = UI_FIRMWARE;
  27542. + goto exit;
  27543. + }
  27544. +
  27545. + /* Get device firmware ID */
  27546. + device_fw_id = rmi4_data->firmware_id;
  27547. + dev_info(rmi4_data->pdev->dev.parent,
  27548. + "%s: Device firmware ID = %d\n",
  27549. + __func__, device_fw_id);
  27550. +
  27551. + /* Get image firmware ID */
  27552. + retval = fwu_get_image_firmware_id(&image_fw_id);
  27553. + if (retval < 0) {
  27554. + flash_area = NONE;
  27555. + goto exit;
  27556. + }
  27557. + dev_info(rmi4_data->pdev->dev.parent,
  27558. + "%s: Image firmware ID = %d\n",
  27559. + __func__, image_fw_id);
  27560. +
  27561. + if (image_fw_id != device_fw_id) {
  27562. + flash_area = UI_FIRMWARE;
  27563. + goto exit;
  27564. + }
  27565. +
  27566. + /* Get device config ID */
  27567. + retval = fwu_get_device_config_id();
  27568. + if (retval < 0) {
  27569. + dev_err(rmi4_data->pdev->dev.parent,
  27570. + "%s: Failed to read device config ID\n",
  27571. + __func__);
  27572. + flash_area = NONE;
  27573. + goto exit;
  27574. + }
  27575. +
  27576. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  27577. + config_id_size = V7_CONFIG_ID_SIZE;
  27578. + else
  27579. + config_id_size = V5V6_CONFIG_ID_SIZE;
  27580. +
  27581. + for (ii = 0; ii < config_id_size; ii++) {
  27582. + if (fwu->img.ui_config.data[ii] != fwu->config_id[ii]) {
  27583. + flash_area = UI_CONFIG;
  27584. + goto exit;
  27585. + }
  27586. + }
  27587. +
  27588. + flash_area = NONE;
  27589. +
  27590. +exit:
  27591. + if (flash_area == NONE) {
  27592. + dev_info(rmi4_data->pdev->dev.parent,
  27593. + "%s: No need to do reflash\n",
  27594. + __func__);
  27595. + } else {
  27596. + dev_info(rmi4_data->pdev->dev.parent,
  27597. + "%s: Updating %s\n",
  27598. + __func__,
  27599. + flash_area == UI_FIRMWARE ?
  27600. + "UI firmware and config" :
  27601. + "UI config only");
  27602. + }
  27603. +
  27604. + return flash_area;
  27605. +}
  27606. +
  27607. +static int fwu_scan_pdt(void)
  27608. +{
  27609. + int retval;
  27610. + unsigned char ii;
  27611. + unsigned char intr_count = 0;
  27612. + unsigned char intr_off;
  27613. + unsigned char intr_src;
  27614. + unsigned short addr;
  27615. + bool f01found = false;
  27616. + bool f34found = false;
  27617. + bool f35found = false;
  27618. + struct synaptics_rmi4_fn_desc rmi_fd;
  27619. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27620. +
  27621. + fwu->in_ub_mode = false;
  27622. +
  27623. + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
  27624. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27625. + addr,
  27626. + (unsigned char *)&rmi_fd,
  27627. + sizeof(rmi_fd));
  27628. + if (retval < 0)
  27629. + return retval;
  27630. +
  27631. + if (rmi_fd.fn_number) {
  27632. + dev_dbg(rmi4_data->pdev->dev.parent,
  27633. + "%s: Found F%02x\n",
  27634. + __func__, rmi_fd.fn_number);
  27635. + switch (rmi_fd.fn_number) {
  27636. + case SYNAPTICS_RMI4_F01:
  27637. + f01found = true;
  27638. +
  27639. + rmi4_data->f01_query_base_addr =
  27640. + rmi_fd.query_base_addr;
  27641. + rmi4_data->f01_ctrl_base_addr =
  27642. + rmi_fd.ctrl_base_addr;
  27643. + rmi4_data->f01_data_base_addr =
  27644. + rmi_fd.data_base_addr;
  27645. + rmi4_data->f01_cmd_base_addr =
  27646. + rmi_fd.cmd_base_addr;
  27647. + break;
  27648. + case SYNAPTICS_RMI4_F34:
  27649. + f34found = true;
  27650. + fwu->f34_fd.query_base_addr =
  27651. + rmi_fd.query_base_addr;
  27652. + fwu->f34_fd.ctrl_base_addr =
  27653. + rmi_fd.ctrl_base_addr;
  27654. + fwu->f34_fd.data_base_addr =
  27655. + rmi_fd.data_base_addr;
  27656. +
  27657. + switch (rmi_fd.fn_version) {
  27658. + case F34_V0:
  27659. + fwu->bl_version = BL_V5;
  27660. + break;
  27661. + case F34_V1:
  27662. + fwu->bl_version = BL_V6;
  27663. + break;
  27664. + case F34_V2:
  27665. + fwu->bl_version = BL_V7;
  27666. + break;
  27667. + default:
  27668. + dev_err(rmi4_data->pdev->dev.parent,
  27669. + "%s: Unrecognized F34 version\n",
  27670. + __func__);
  27671. + return -EINVAL;
  27672. + }
  27673. +
  27674. + fwu->intr_mask = 0;
  27675. + intr_src = rmi_fd.intr_src_count;
  27676. + intr_off = intr_count % 8;
  27677. + for (ii = intr_off;
  27678. + ii < (intr_src + intr_off);
  27679. + ii++) {
  27680. + fwu->intr_mask |= 1 << ii;
  27681. + }
  27682. + break;
  27683. + case SYNAPTICS_RMI4_F35:
  27684. + f35found = true;
  27685. + fwu->f35_fd.query_base_addr =
  27686. + rmi_fd.query_base_addr;
  27687. + fwu->f35_fd.ctrl_base_addr =
  27688. + rmi_fd.ctrl_base_addr;
  27689. + fwu->f35_fd.data_base_addr =
  27690. + rmi_fd.data_base_addr;
  27691. + fwu->f35_fd.cmd_base_addr =
  27692. + rmi_fd.cmd_base_addr;
  27693. + break;
  27694. + }
  27695. + } else {
  27696. + break;
  27697. + }
  27698. +
  27699. + intr_count += rmi_fd.intr_src_count;
  27700. + }
  27701. +
  27702. + if (!f01found || !f34found) {
  27703. + dev_err(rmi4_data->pdev->dev.parent,
  27704. + "%s: Failed to find both F01 and F34\n",
  27705. + __func__);
  27706. + if (!f35found) {
  27707. + dev_err(rmi4_data->pdev->dev.parent,
  27708. + "%s: Failed to find F35\n",
  27709. + __func__);
  27710. + return -EINVAL;
  27711. + } else {
  27712. + fwu->in_ub_mode = true;
  27713. + dev_dbg(rmi4_data->pdev->dev.parent,
  27714. + "%s: In microbootloader mode\n",
  27715. + __func__);
  27716. + fwu_recovery_check_status();
  27717. + return 0;
  27718. + }
  27719. + }
  27720. +
  27721. + rmi4_data->intr_mask[0] |= fwu->intr_mask;
  27722. +
  27723. + addr = rmi4_data->f01_ctrl_base_addr + 1;
  27724. +
  27725. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27726. + addr,
  27727. + &(rmi4_data->intr_mask[0]),
  27728. + sizeof(rmi4_data->intr_mask[0]));
  27729. + if (retval < 0) {
  27730. + dev_err(rmi4_data->pdev->dev.parent,
  27731. + "%s: Failed to set interrupt enable bit\n",
  27732. + __func__);
  27733. + return retval;
  27734. + }
  27735. +
  27736. + return 0;
  27737. +}
  27738. +
  27739. +static int fwu_enter_flash_prog(void)
  27740. +{
  27741. + int retval;
  27742. + struct f01_device_control f01_device_control;
  27743. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27744. +
  27745. + retval = fwu_read_flash_status();
  27746. + if (retval < 0)
  27747. + return retval;
  27748. +
  27749. + if (fwu->in_bl_mode)
  27750. + return 0;
  27751. +
  27752. + retval = rmi4_data->irq_enable(rmi4_data, false, true);
  27753. + if (retval < 0)
  27754. + return retval;
  27755. +
  27756. + msleep(INT_DISABLE_WAIT_MS);
  27757. +
  27758. + retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
  27759. + if (retval < 0)
  27760. + return retval;
  27761. +
  27762. + retval = fwu_wait_for_idle(ENABLE_WAIT_MS, false);
  27763. + if (retval < 0)
  27764. + return retval;
  27765. +
  27766. + if (!fwu->in_bl_mode) {
  27767. + dev_err(rmi4_data->pdev->dev.parent,
  27768. + "%s: BL mode not entered\n",
  27769. + __func__);
  27770. + return -EINVAL;
  27771. + }
  27772. +
  27773. + if (rmi4_data->hw_if->bl_hw_init) {
  27774. + retval = rmi4_data->hw_if->bl_hw_init(rmi4_data);
  27775. + if (retval < 0)
  27776. + return retval;
  27777. + }
  27778. +
  27779. + retval = fwu_scan_pdt();
  27780. + if (retval < 0)
  27781. + return retval;
  27782. +
  27783. + pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
  27784. +
  27785. + retval = fwu_read_f34_queries();
  27786. + if (retval < 0)
  27787. + return retval;
  27788. +
  27789. + retval = synaptics_rmi4_reg_read(rmi4_data,
  27790. + rmi4_data->f01_ctrl_base_addr,
  27791. + f01_device_control.data,
  27792. + sizeof(f01_device_control.data));
  27793. + if (retval < 0) {
  27794. + dev_err(rmi4_data->pdev->dev.parent,
  27795. + "%s: Failed to read F01 device control\n",
  27796. + __func__);
  27797. + return retval;
  27798. + }
  27799. +
  27800. + f01_device_control.nosleep = true;
  27801. + f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
  27802. +
  27803. + retval = synaptics_rmi4_reg_write(rmi4_data,
  27804. + rmi4_data->f01_ctrl_base_addr,
  27805. + f01_device_control.data,
  27806. + sizeof(f01_device_control.data));
  27807. + if (retval < 0) {
  27808. + dev_err(rmi4_data->pdev->dev.parent,
  27809. + "%s: Failed to write F01 device control\n",
  27810. + __func__);
  27811. + return retval;
  27812. + }
  27813. +
  27814. + msleep(ENTER_FLASH_PROG_WAIT_MS);
  27815. +
  27816. + return retval;
  27817. +}
  27818. +
  27819. +static int fwu_check_ui_firmware_size(void)
  27820. +{
  27821. + unsigned short block_count;
  27822. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27823. +
  27824. + block_count = fwu->img.ui_firmware.size / fwu->block_size;
  27825. +
  27826. + if (block_count != fwu->blkcount.ui_firmware) {
  27827. + dev_err(rmi4_data->pdev->dev.parent,
  27828. + "%s: UI firmware size mismatch\n",
  27829. + __func__);
  27830. + return -EINVAL;
  27831. + }
  27832. +
  27833. + return 0;
  27834. +}
  27835. +
  27836. +static int fwu_check_ui_configuration_size(void)
  27837. +{
  27838. + unsigned short block_count;
  27839. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27840. +
  27841. + block_count = fwu->img.ui_config.size / fwu->block_size;
  27842. +
  27843. + if (block_count != fwu->blkcount.ui_config) {
  27844. + dev_err(rmi4_data->pdev->dev.parent,
  27845. + "%s: UI configuration size mismatch\n",
  27846. + __func__);
  27847. + return -EINVAL;
  27848. + }
  27849. +
  27850. + return 0;
  27851. +}
  27852. +
  27853. +static int fwu_check_dp_configuration_size(void)
  27854. +{
  27855. + unsigned short block_count;
  27856. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27857. +
  27858. + block_count = fwu->img.dp_config.size / fwu->block_size;
  27859. +
  27860. + if (block_count != fwu->blkcount.dp_config) {
  27861. + dev_err(rmi4_data->pdev->dev.parent,
  27862. + "%s: Display configuration size mismatch\n",
  27863. + __func__);
  27864. + return -EINVAL;
  27865. + }
  27866. +
  27867. + return 0;
  27868. +}
  27869. +
  27870. +static int fwu_check_pm_configuration_size(void)
  27871. +{
  27872. + unsigned short block_count;
  27873. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27874. +
  27875. + block_count = fwu->img.pm_config.size / fwu->block_size;
  27876. +
  27877. + if (block_count != fwu->blkcount.pm_config) {
  27878. + dev_err(rmi4_data->pdev->dev.parent,
  27879. + "%s: Permanent configuration size mismatch\n",
  27880. + __func__);
  27881. + return -EINVAL;
  27882. + }
  27883. +
  27884. + return 0;
  27885. +}
  27886. +
  27887. +static int fwu_check_bl_configuration_size(void)
  27888. +{
  27889. + unsigned short block_count;
  27890. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27891. +
  27892. + block_count = fwu->img.bl_config.size / fwu->block_size;
  27893. +
  27894. + if (block_count != fwu->blkcount.bl_config) {
  27895. + dev_err(rmi4_data->pdev->dev.parent,
  27896. + "%s: Bootloader configuration size mismatch\n",
  27897. + __func__);
  27898. + return -EINVAL;
  27899. + }
  27900. +
  27901. + return 0;
  27902. +}
  27903. +
  27904. +static int fwu_check_guest_code_size(void)
  27905. +{
  27906. + unsigned short block_count;
  27907. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27908. +
  27909. + block_count = fwu->img.guest_code.size / fwu->block_size;
  27910. + if (block_count != fwu->blkcount.guest_code) {
  27911. + dev_err(rmi4_data->pdev->dev.parent,
  27912. + "%s: Guest code size mismatch\n",
  27913. + __func__);
  27914. + return -EINVAL;
  27915. + }
  27916. +
  27917. + return 0;
  27918. +}
  27919. +
  27920. +static int fwu_erase_configuration(void)
  27921. +{
  27922. + int retval;
  27923. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27924. +
  27925. + switch (fwu->config_area) {
  27926. + case UI_CONFIG_AREA:
  27927. + retval = fwu_write_f34_command(CMD_ERASE_UI_CONFIG);
  27928. + if (retval < 0)
  27929. + return retval;
  27930. + break;
  27931. + case DP_CONFIG_AREA:
  27932. + retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
  27933. + if (retval < 0)
  27934. + return retval;
  27935. + break;
  27936. + case BL_CONFIG_AREA:
  27937. + retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
  27938. + if (retval < 0)
  27939. + return retval;
  27940. + break;
  27941. + case FLASH_CONFIG_AREA:
  27942. + retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG);
  27943. + if (retval < 0)
  27944. + return retval;
  27945. + break;
  27946. + default:
  27947. + dev_err(rmi4_data->pdev->dev.parent,
  27948. + "%s: Invalid config area\n",
  27949. + __func__);
  27950. + return -EINVAL;
  27951. + }
  27952. +
  27953. + dev_dbg(rmi4_data->pdev->dev.parent,
  27954. + "%s: Erase command written\n",
  27955. + __func__);
  27956. +
  27957. + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
  27958. + if (retval < 0)
  27959. + return retval;
  27960. +
  27961. + dev_dbg(rmi4_data->pdev->dev.parent,
  27962. + "%s: Idle status detected\n",
  27963. + __func__);
  27964. +
  27965. + return retval;
  27966. +}
  27967. +
  27968. +static int fwu_erase_bootloader(void)
  27969. +{
  27970. + int retval;
  27971. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27972. +
  27973. + retval = fwu_write_f34_command(CMD_ERASE_BOOTLOADER);
  27974. + if (retval < 0)
  27975. + return retval;
  27976. +
  27977. + dev_dbg(rmi4_data->pdev->dev.parent,
  27978. + "%s: Erase command written\n",
  27979. + __func__);
  27980. +
  27981. + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
  27982. + if (retval < 0)
  27983. + return retval;
  27984. +
  27985. + dev_dbg(rmi4_data->pdev->dev.parent,
  27986. + "%s: Idle status detected\n",
  27987. + __func__);
  27988. +
  27989. + return 0;
  27990. +}
  27991. +
  27992. +static int fwu_erase_utility_parameter(void)
  27993. +{
  27994. + int retval;
  27995. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  27996. +
  27997. + retval = fwu_write_f34_command(CMD_ERASE_UTILITY_PARAMETER);
  27998. + if (retval < 0)
  27999. + return retval;
  28000. +
  28001. + dev_dbg(rmi4_data->pdev->dev.parent,
  28002. + "%s: Erase command written\n",
  28003. + __func__);
  28004. +
  28005. + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
  28006. + if (retval < 0)
  28007. + return retval;
  28008. +
  28009. + dev_dbg(rmi4_data->pdev->dev.parent,
  28010. + "%s: Idle status detected\n",
  28011. + __func__);
  28012. +
  28013. + return 0;
  28014. +}
  28015. +
  28016. +static int fwu_erase_guest_code(void)
  28017. +{
  28018. + int retval;
  28019. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28020. +
  28021. + retval = fwu_write_f34_command(CMD_ERASE_GUEST_CODE);
  28022. + if (retval < 0)
  28023. + return retval;
  28024. +
  28025. + dev_dbg(rmi4_data->pdev->dev.parent,
  28026. + "%s: Erase command written\n",
  28027. + __func__);
  28028. +
  28029. + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
  28030. + if (retval < 0)
  28031. + return retval;
  28032. +
  28033. + dev_dbg(rmi4_data->pdev->dev.parent,
  28034. + "%s: Idle status detected\n",
  28035. + __func__);
  28036. +
  28037. + return 0;
  28038. +}
  28039. +
  28040. +static int fwu_erase_all(void)
  28041. +{
  28042. + int retval;
  28043. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28044. +
  28045. + if (fwu->bl_version == BL_V7) {
  28046. + fwu->config_area = INVALID_CONFIG_AREA;
  28047. + retval = fwu_write_f34_command(CMD_ERASE_UI_FIRMWARE);
  28048. + if (retval < 0)
  28049. + return retval;
  28050. +
  28051. + dev_dbg(rmi4_data->pdev->dev.parent,
  28052. + "%s: Erase command written\n",
  28053. + __func__);
  28054. +
  28055. + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
  28056. + if (retval < 0)
  28057. + return retval;
  28058. +
  28059. + dev_dbg(rmi4_data->pdev->dev.parent,
  28060. + "%s: Idle status detected\n",
  28061. + __func__);
  28062. +
  28063. + pr_err("erased core code\n");
  28064. +
  28065. + fwu->config_area = UI_CONFIG_AREA;
  28066. + retval = fwu_erase_configuration();
  28067. + if (retval < 0)
  28068. + return retval;
  28069. +
  28070. + pr_err("erased core config\n");
  28071. + } else {
  28072. + retval = fwu_write_f34_command(CMD_ERASE_ALL);
  28073. + if (retval < 0)
  28074. + return retval;
  28075. +
  28076. + dev_dbg(rmi4_data->pdev->dev.parent,
  28077. + "%s: Erase all command written\n",
  28078. + __func__);
  28079. +
  28080. + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false);
  28081. + if (!(fwu->bl_version == BL_V8 &&
  28082. + fwu->flash_status == BAD_PARTITION_TABLE)) {
  28083. + if (retval < 0)
  28084. + return retval;
  28085. + }
  28086. +
  28087. + dev_dbg(rmi4_data->pdev->dev.parent,
  28088. + "%s: Idle status detected\n",
  28089. + __func__);
  28090. +
  28091. + if (fwu->bl_version == BL_V8)
  28092. + return 0;
  28093. + }
  28094. +
  28095. + if (fwu->flash_properties.has_disp_config &&
  28096. + fwu->img.contains_disp_config) {
  28097. + fwu->config_area = DP_CONFIG_AREA;
  28098. + retval = fwu_erase_configuration();
  28099. + if (retval < 0)
  28100. + return retval;
  28101. + }
  28102. +
  28103. + if (fwu->has_guest_code && fwu->img.contains_guest_code) {
  28104. + retval = fwu_erase_guest_code();
  28105. + if (retval < 0)
  28106. + return retval;
  28107. + }
  28108. +
  28109. + return 0;
  28110. +}
  28111. +
  28112. +static int fwu_write_firmware(void)
  28113. +{
  28114. + unsigned short firmware_block_count;
  28115. +
  28116. + firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size;
  28117. +
  28118. + pr_err("core code block count = %d\n", firmware_block_count);
  28119. +
  28120. + return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data,
  28121. + firmware_block_count, CMD_WRITE_FW);
  28122. +}
  28123. +
  28124. +static int fwu_write_bootloader(void)
  28125. +{
  28126. + int retval;
  28127. + unsigned short bootloader_block_count;
  28128. +
  28129. + bootloader_block_count = fwu->img.bl_image.size / fwu->block_size;
  28130. +
  28131. + pr_err("bootloader block count = %d\n", bootloader_block_count);
  28132. +
  28133. + fwu->write_bootloader = true;
  28134. + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.bl_image.data,
  28135. + bootloader_block_count, CMD_WRITE_BOOTLOADER);
  28136. + fwu->write_bootloader = false;
  28137. +
  28138. + return retval;
  28139. +}
  28140. +
  28141. +static int fwu_write_utility_parameter(void)
  28142. +{
  28143. + int retval;
  28144. + unsigned char ii;
  28145. + unsigned char checksum_array[4];
  28146. + unsigned char *pbuf;
  28147. + unsigned short remaining_size;
  28148. + unsigned short utility_param_size;
  28149. + unsigned long checksum;
  28150. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28151. +
  28152. + utility_param_size = fwu->blkcount.utility_param * fwu->block_size;
  28153. + retval = fwu_allocate_read_config_buf(utility_param_size);
  28154. + if (retval < 0)
  28155. + return retval;
  28156. + memset(fwu->read_config_buf, 0x00, utility_param_size);
  28157. +
  28158. + pbuf = fwu->read_config_buf;
  28159. + remaining_size = utility_param_size - 4;
  28160. +
  28161. + for (ii = 0; ii < MAX_UTILITY_PARAMS; ii++) {
  28162. + if (fwu->img.utility_param_id[ii] == UNUSED)
  28163. + continue;
  28164. +
  28165. +#ifdef F51_DISCRETE_FORCE
  28166. + if (fwu->img.utility_param_id[ii] == FORCE_PARAMETER) {
  28167. + if (fwu->bl_mode_device) {
  28168. + dev_info(rmi4_data->pdev->dev.parent,
  28169. + "%s: Device in bootloader mode, skipping calibration data restoration\n",
  28170. + __func__);
  28171. + goto image_param;
  28172. + }
  28173. + retval = secure_memcpy(&(pbuf[4]),
  28174. + remaining_size - 4,
  28175. + fwu->cal_data,
  28176. + fwu->cal_data_buf_size,
  28177. + fwu->cal_data_size);
  28178. + if (retval < 0) {
  28179. + dev_err(rmi4_data->pdev->dev.parent,
  28180. + "%s: Failed to copy force calibration data\n",
  28181. + __func__);
  28182. + return retval;
  28183. + }
  28184. + pbuf[0] = FORCE_PARAMETER;
  28185. + pbuf[1] = 0x00;
  28186. + pbuf[2] = (4 + fwu->cal_data_size) / 2;
  28187. + pbuf += (fwu->cal_data_size + 4);
  28188. + remaining_size -= (fwu->cal_data_size + 4);
  28189. + continue;
  28190. + }
  28191. +image_param:
  28192. +#endif
  28193. +
  28194. + retval = secure_memcpy(pbuf,
  28195. + remaining_size,
  28196. + fwu->img.utility_param[ii].data,
  28197. + fwu->img.utility_param[ii].size,
  28198. + fwu->img.utility_param[ii].size);
  28199. + if (retval < 0) {
  28200. + dev_err(rmi4_data->pdev->dev.parent,
  28201. + "%s: Failed to copy utility parameter data\n",
  28202. + __func__);
  28203. + return retval;
  28204. + }
  28205. + pbuf += fwu->img.utility_param[ii].size;
  28206. + remaining_size -= fwu->img.utility_param[ii].size;
  28207. + }
  28208. +
  28209. + calculate_checksum((unsigned short *)fwu->read_config_buf,
  28210. + ((utility_param_size - 4) / 2),
  28211. + &checksum);
  28212. +
  28213. + convert_to_little_endian(checksum_array, checksum);
  28214. +
  28215. + fwu->read_config_buf[utility_param_size - 4] = checksum_array[0];
  28216. + fwu->read_config_buf[utility_param_size - 3] = checksum_array[1];
  28217. + fwu->read_config_buf[utility_param_size - 2] = checksum_array[2];
  28218. + fwu->read_config_buf[utility_param_size - 1] = checksum_array[3];
  28219. +
  28220. + pr_err("utility parameter block count = %d\n", fwu->blkcount.utility_param);
  28221. +
  28222. + retval = fwu_write_f34_blocks((unsigned char *)fwu->read_config_buf,
  28223. + fwu->blkcount.utility_param, CMD_WRITE_UTILITY_PARAM);
  28224. + if (retval < 0)
  28225. + return retval;
  28226. +
  28227. + return 0;
  28228. +}
  28229. +
  28230. +static int fwu_write_configuration(void)
  28231. +{
  28232. + return fwu_write_f34_blocks((unsigned char *)fwu->config_data,
  28233. + fwu->config_block_count, CMD_WRITE_CONFIG);
  28234. +}
  28235. +
  28236. +static int fwu_write_ui_configuration(void)
  28237. +{
  28238. + fwu->config_area = UI_CONFIG_AREA;
  28239. + fwu->config_data = fwu->img.ui_config.data;
  28240. + fwu->config_size = fwu->img.ui_config.size;
  28241. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28242. +
  28243. + pr_err("core config block count = %d\n", fwu->config_block_count);
  28244. +
  28245. + return fwu_write_configuration();
  28246. +}
  28247. +
  28248. +static int fwu_write_dp_configuration(void)
  28249. +{
  28250. + fwu->config_area = DP_CONFIG_AREA;
  28251. + fwu->config_data = fwu->img.dp_config.data;
  28252. + fwu->config_size = fwu->img.dp_config.size;
  28253. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28254. +
  28255. + return fwu_write_configuration();
  28256. +}
  28257. +
  28258. +static int fwu_write_pm_configuration(void)
  28259. +{
  28260. + fwu->config_area = PM_CONFIG_AREA;
  28261. + fwu->config_data = fwu->img.pm_config.data;
  28262. + fwu->config_size = fwu->img.pm_config.size;
  28263. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28264. +
  28265. + return fwu_write_configuration();
  28266. +}
  28267. +
  28268. +static int fwu_write_flash_configuration(void)
  28269. +{
  28270. + int retval;
  28271. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28272. +
  28273. + fwu->config_area = FLASH_CONFIG_AREA;
  28274. + fwu->config_data = fwu->img.fl_config.data;
  28275. + fwu->config_size = fwu->img.fl_config.size;
  28276. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28277. +
  28278. + if (fwu->config_block_count != fwu->blkcount.fl_config) {
  28279. + dev_err(rmi4_data->pdev->dev.parent,
  28280. + "%s: Flash configuration size mismatch\n",
  28281. + __func__);
  28282. + return -EINVAL;
  28283. + }
  28284. +
  28285. + retval = fwu_erase_configuration();
  28286. + if (retval < 0)
  28287. + return retval;
  28288. +
  28289. + retval = fwu_write_configuration();
  28290. + if (retval < 0)
  28291. + return retval;
  28292. +
  28293. + rmi4_data->reset_device(rmi4_data, false);
  28294. +
  28295. + return 0;
  28296. +}
  28297. +
  28298. +static int fwu_write_guest_code(void)
  28299. +{
  28300. + int retval;
  28301. + unsigned short guest_code_block_count;
  28302. +
  28303. + guest_code_block_count = fwu->img.guest_code.size / fwu->block_size;
  28304. +
  28305. + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.guest_code.data,
  28306. + guest_code_block_count, CMD_WRITE_GUEST_CODE);
  28307. + if (retval < 0)
  28308. + return retval;
  28309. +
  28310. + return 0;
  28311. +}
  28312. +
  28313. +static int fwu_write_lockdown(void)
  28314. +{
  28315. + unsigned short lockdown_block_count;
  28316. +
  28317. + lockdown_block_count = fwu->img.lockdown.size / fwu->block_size;
  28318. +
  28319. + return fwu_write_f34_blocks((unsigned char *)fwu->img.lockdown.data,
  28320. + lockdown_block_count, CMD_WRITE_LOCKDOWN);
  28321. +}
  28322. +
  28323. +static int fwu_write_partition_table_v8(void)
  28324. +{
  28325. + int retval;
  28326. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28327. +
  28328. + fwu->config_area = FLASH_CONFIG_AREA;
  28329. + fwu->config_data = fwu->img.fl_config.data;
  28330. + fwu->config_size = fwu->img.fl_config.size;
  28331. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28332. +
  28333. + if (fwu->config_block_count != fwu->blkcount.fl_config) {
  28334. + dev_err(rmi4_data->pdev->dev.parent,
  28335. + "%s: Flash configuration size mismatch\n",
  28336. + __func__);
  28337. + return -EINVAL;
  28338. + }
  28339. +
  28340. + retval = fwu_write_configuration();
  28341. + if (retval < 0)
  28342. + return retval;
  28343. +
  28344. + rmi4_data->reset_device(rmi4_data, false);
  28345. +
  28346. + return 0;
  28347. +}
  28348. +
  28349. +static int fwu_write_partition_table_v7(void)
  28350. +{
  28351. + int retval;
  28352. + unsigned short block_count;
  28353. +
  28354. + block_count = fwu->blkcount.bl_config;
  28355. + fwu->config_area = BL_CONFIG_AREA;
  28356. + fwu->config_size = fwu->block_size * block_count;
  28357. +
  28358. + retval = fwu_allocate_read_config_buf(fwu->config_size);
  28359. + if (retval < 0)
  28360. + return retval;
  28361. +
  28362. + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG);
  28363. + if (retval < 0)
  28364. + return retval;
  28365. +
  28366. + retval = fwu_erase_configuration();
  28367. + if (retval < 0)
  28368. + return retval;
  28369. +
  28370. + retval = fwu_write_flash_configuration();
  28371. + if (retval < 0)
  28372. + return retval;
  28373. +
  28374. + fwu->config_area = BL_CONFIG_AREA;
  28375. + fwu->config_data = fwu->read_config_buf;
  28376. + fwu->config_size = fwu->img.bl_config.size;
  28377. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28378. +
  28379. + retval = fwu_write_configuration();
  28380. + if (retval < 0)
  28381. + return retval;
  28382. +
  28383. + return 0;
  28384. +}
  28385. +
  28386. +static int fwu_write_bl_area_v7(void)
  28387. +{
  28388. + int retval;
  28389. + bool has_utility_param;
  28390. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28391. +
  28392. + has_utility_param = fwu->has_utility_param;
  28393. +
  28394. + if (fwu->has_utility_param) {
  28395. + retval = fwu_erase_utility_parameter();
  28396. + if (retval < 0)
  28397. + return retval;
  28398. +
  28399. + pr_err("erased utility parameter\n");
  28400. + }
  28401. +
  28402. + fwu->config_area = BL_CONFIG_AREA;
  28403. + retval = fwu_erase_configuration();
  28404. + if (retval < 0)
  28405. + return retval;
  28406. +
  28407. + pr_err("erased bootloader config\n");
  28408. +
  28409. + fwu->config_area = FLASH_CONFIG_AREA;
  28410. + retval = fwu_erase_configuration();
  28411. + if (retval < 0)
  28412. + return retval;
  28413. +
  28414. + pr_err("erased flash config\n");
  28415. +
  28416. + retval = fwu_erase_bootloader();
  28417. + if (retval < 0)
  28418. + return retval;
  28419. +
  28420. + pr_err("erased bootloader\n");
  28421. +
  28422. + retval = fwu_write_bootloader();
  28423. + if (retval < 0)
  28424. + return retval;
  28425. +
  28426. + pr_err("bootloader written\n");
  28427. +
  28428. + msleep(rmi4_data->hw_if->board_data->reset_delay_ms);
  28429. + rmi4_data->reset_device(rmi4_data, false);
  28430. +
  28431. + pr_err("reset after writing bootloader\n");
  28432. +
  28433. + fwu->config_area = FLASH_CONFIG_AREA;
  28434. + fwu->config_data = fwu->img.fl_config.data;
  28435. + fwu->config_size = fwu->img.fl_config.size;
  28436. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28437. + pr_err("flash config block count = %d\n", fwu->config_block_count);
  28438. + retval = fwu_write_configuration();
  28439. + if (retval < 0)
  28440. + return retval;
  28441. +
  28442. + pr_err("flash config written\n");
  28443. +
  28444. + rmi4_data->reset_device(rmi4_data, false);
  28445. +
  28446. + pr_err("reset after writing flash config\n");
  28447. +
  28448. + fwu->config_area = BL_CONFIG_AREA;
  28449. + fwu->config_data = fwu->img.bl_config.data;
  28450. + fwu->config_size = fwu->img.bl_config.size;
  28451. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28452. + pr_err("bootloader config block count = %d\n", fwu->config_block_count);
  28453. + retval = fwu_write_configuration();
  28454. + if (retval < 0)
  28455. + return retval;
  28456. +
  28457. + pr_err("bootloader config written\n");
  28458. +
  28459. + if (fwu->img.contains_utility_param) {
  28460. + retval = fwu_write_utility_parameter();
  28461. + if (retval < 0)
  28462. + return retval;
  28463. +
  28464. + pr_err("utility parameter written\n");
  28465. + }
  28466. +
  28467. + return 0;
  28468. +}
  28469. +
  28470. +static int fwu_do_reflash(void)
  28471. +{
  28472. + int retval;
  28473. + bool do_bl_update = false;
  28474. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28475. +
  28476. + if (!fwu->new_partition_table) {
  28477. + retval = fwu_check_ui_firmware_size();
  28478. + if (retval < 0)
  28479. + return retval;
  28480. +
  28481. + retval = fwu_check_ui_configuration_size();
  28482. + if (retval < 0)
  28483. + return retval;
  28484. +
  28485. + if (fwu->flash_properties.has_disp_config &&
  28486. + fwu->img.contains_disp_config) {
  28487. + retval = fwu_check_dp_configuration_size();
  28488. + if (retval < 0)
  28489. + return retval;
  28490. + }
  28491. +
  28492. + if (fwu->has_guest_code && fwu->img.contains_guest_code) {
  28493. + retval = fwu_check_guest_code_size();
  28494. + if (retval < 0)
  28495. + return retval;
  28496. + }
  28497. + } else if (fwu->bl_version == BL_V7) {
  28498. + retval = fwu_check_bl_configuration_size();
  28499. + if (retval < 0)
  28500. + return retval;
  28501. + }
  28502. +
  28503. + if (!fwu->has_utility_param && fwu->img.contains_utility_param) {
  28504. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  28505. + do_bl_update = true;
  28506. + }
  28507. +
  28508. + if (fwu->has_utility_param && !fwu->img.contains_utility_param) {
  28509. + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8)
  28510. + do_bl_update = true;
  28511. + }
  28512. +
  28513. + pr_err("fwu->has_utility_param = %d\n", fwu->has_utility_param);
  28514. + pr_err("fwu->img.contains_utility_param = %d\n", fwu->img.contains_utility_param);
  28515. + pr_err("do_bl_update = %d\n", do_bl_update);
  28516. +
  28517. + if (!do_bl_update && fwu->incompatible_partition_tables) {
  28518. + dev_err(rmi4_data->pdev->dev.parent,
  28519. + "%s: Incompatible partition tables\n",
  28520. + __func__);
  28521. + return -EINVAL;
  28522. + } else if (!do_bl_update && fwu->new_partition_table) {
  28523. + if (!fwu->force_update) {
  28524. + dev_err(rmi4_data->pdev->dev.parent,
  28525. + "%s: Partition table mismatch\n",
  28526. + __func__);
  28527. + return -EINVAL;
  28528. + }
  28529. + }
  28530. +
  28531. + retval = fwu_erase_all();
  28532. + if (retval < 0)
  28533. + return retval;
  28534. +
  28535. + if (do_bl_update) {
  28536. + retval = fwu_write_bl_area_v7();
  28537. + if (retval < 0)
  28538. + return retval;
  28539. + pr_notice("%s: Bootloader area programmed\n", __func__);
  28540. + } else if (fwu->bl_version == BL_V7 && fwu->new_partition_table) {
  28541. + retval = fwu_write_partition_table_v7();
  28542. + if (retval < 0)
  28543. + return retval;
  28544. + pr_notice("%s: Partition table programmed\n", __func__);
  28545. + } else if (fwu->bl_version == BL_V8) {
  28546. + retval = fwu_write_partition_table_v8();
  28547. + if (retval < 0)
  28548. + return retval;
  28549. + pr_notice("%s: Partition table programmed\n", __func__);
  28550. + }
  28551. +
  28552. + retval = fwu_write_firmware();
  28553. + if (retval < 0)
  28554. + return retval;
  28555. + pr_notice("%s: Firmware programmed\n", __func__);
  28556. +
  28557. + fwu->config_area = UI_CONFIG_AREA;
  28558. + retval = fwu_write_ui_configuration();
  28559. + if (retval < 0)
  28560. + return retval;
  28561. + pr_notice("%s: Configuration programmed\n", __func__);
  28562. +
  28563. + if (fwu->flash_properties.has_disp_config &&
  28564. + fwu->img.contains_disp_config) {
  28565. + retval = fwu_write_dp_configuration();
  28566. + if (retval < 0)
  28567. + return retval;
  28568. + pr_notice("%s: Display configuration programmed\n", __func__);
  28569. + }
  28570. +
  28571. + if (fwu->has_guest_code && fwu->img.contains_guest_code) {
  28572. + retval = fwu_write_guest_code();
  28573. + if (retval < 0)
  28574. + return retval;
  28575. + pr_notice("%s: Guest code programmed\n", __func__);
  28576. + }
  28577. +
  28578. + return retval;
  28579. +}
  28580. +
  28581. +static int fwu_do_read_config(void)
  28582. +{
  28583. + int retval;
  28584. + unsigned short block_count;
  28585. + unsigned short config_area;
  28586. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28587. +
  28588. + switch (fwu->config_area) {
  28589. + case UI_CONFIG_AREA:
  28590. + block_count = fwu->blkcount.ui_config;
  28591. + break;
  28592. + case DP_CONFIG_AREA:
  28593. + if (!fwu->flash_properties.has_disp_config) {
  28594. + dev_err(rmi4_data->pdev->dev.parent,
  28595. + "%s: Display configuration not supported\n",
  28596. + __func__);
  28597. + return -EINVAL;
  28598. + }
  28599. + block_count = fwu->blkcount.dp_config;
  28600. + break;
  28601. + case PM_CONFIG_AREA:
  28602. + if (!fwu->flash_properties.has_pm_config) {
  28603. + dev_err(rmi4_data->pdev->dev.parent,
  28604. + "%s: Permanent configuration not supported\n",
  28605. + __func__);
  28606. + return -EINVAL;
  28607. + }
  28608. + block_count = fwu->blkcount.pm_config;
  28609. + break;
  28610. + case BL_CONFIG_AREA:
  28611. + if (!fwu->flash_properties.has_bl_config) {
  28612. + dev_err(rmi4_data->pdev->dev.parent,
  28613. + "%s: Bootloader configuration not supported\n",
  28614. + __func__);
  28615. + return -EINVAL;
  28616. + }
  28617. + block_count = fwu->blkcount.bl_config;
  28618. + break;
  28619. + default:
  28620. + dev_err(rmi4_data->pdev->dev.parent,
  28621. + "%s: Invalid config area\n",
  28622. + __func__);
  28623. + return -EINVAL;
  28624. + }
  28625. +
  28626. + if (block_count == 0) {
  28627. + dev_err(rmi4_data->pdev->dev.parent,
  28628. + "%s: Invalid block count\n",
  28629. + __func__);
  28630. + return -EINVAL;
  28631. + }
  28632. +
  28633. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  28634. +
  28635. + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) {
  28636. + config_area = fwu->config_area;
  28637. + retval = fwu_enter_flash_prog();
  28638. + fwu->config_area = config_area;
  28639. + if (retval < 0)
  28640. + goto exit;
  28641. + }
  28642. +
  28643. + fwu->config_size = fwu->block_size * block_count;
  28644. +
  28645. + retval = fwu_allocate_read_config_buf(fwu->config_size);
  28646. + if (retval < 0)
  28647. + goto exit;
  28648. +
  28649. + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG);
  28650. +
  28651. +exit:
  28652. + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6)
  28653. + rmi4_data->reset_device(rmi4_data, false);
  28654. +
  28655. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  28656. +
  28657. + return retval;
  28658. +}
  28659. +
  28660. +static int fwu_do_lockdown_v7(void)
  28661. +{
  28662. + int retval;
  28663. + struct f34_v7_data0 status;
  28664. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28665. +
  28666. + retval = fwu_enter_flash_prog();
  28667. + if (retval < 0)
  28668. + return retval;
  28669. +
  28670. + retval = synaptics_rmi4_reg_read(rmi4_data,
  28671. + fwu->f34_fd.data_base_addr + fwu->off.flash_status,
  28672. + status.data,
  28673. + sizeof(status.data));
  28674. + if (retval < 0) {
  28675. + dev_err(rmi4_data->pdev->dev.parent,
  28676. + "%s: Failed to read flash status\n",
  28677. + __func__);
  28678. + return retval;
  28679. + }
  28680. +
  28681. + if (status.device_cfg_status == 2) {
  28682. + dev_info(rmi4_data->pdev->dev.parent,
  28683. + "%s: Device already locked down\n",
  28684. + __func__);
  28685. + return 0;
  28686. + }
  28687. +
  28688. + retval = fwu_write_lockdown();
  28689. + if (retval < 0)
  28690. + return retval;
  28691. +
  28692. + pr_notice("%s: Lockdown programmed\n", __func__);
  28693. +
  28694. + return retval;
  28695. +}
  28696. +
  28697. +static int fwu_do_lockdown_v5v6(void)
  28698. +{
  28699. + int retval;
  28700. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28701. +
  28702. + retval = fwu_enter_flash_prog();
  28703. + if (retval < 0)
  28704. + return retval;
  28705. +
  28706. + retval = synaptics_rmi4_reg_read(rmi4_data,
  28707. + fwu->f34_fd.query_base_addr + fwu->off.properties,
  28708. + fwu->flash_properties.data,
  28709. + sizeof(fwu->flash_properties.data));
  28710. + if (retval < 0) {
  28711. + dev_err(rmi4_data->pdev->dev.parent,
  28712. + "%s: Failed to read flash properties\n",
  28713. + __func__);
  28714. + return retval;
  28715. + }
  28716. +
  28717. + if (fwu->flash_properties.unlocked == 0) {
  28718. + dev_info(rmi4_data->pdev->dev.parent,
  28719. + "%s: Device already locked down\n",
  28720. + __func__);
  28721. + return 0;
  28722. + }
  28723. +
  28724. + retval = fwu_write_lockdown();
  28725. + if (retval < 0)
  28726. + return retval;
  28727. +
  28728. + pr_notice("%s: Lockdown programmed\n", __func__);
  28729. +
  28730. + return retval;
  28731. +}
  28732. +
  28733. +#ifdef F51_DISCRETE_FORCE
  28734. +static int fwu_do_restore_f51_cal_data(void)
  28735. +{
  28736. + int retval;
  28737. + unsigned char checksum_array[4];
  28738. + unsigned short block_count;
  28739. + unsigned long checksum;
  28740. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28741. +
  28742. + block_count = fwu->blkcount.ui_config;
  28743. + fwu->config_size = fwu->block_size * block_count;
  28744. + fwu->config_area = UI_CONFIG_AREA;
  28745. +
  28746. + retval = fwu_allocate_read_config_buf(fwu->config_size);
  28747. + if (retval < 0)
  28748. + return retval;
  28749. +
  28750. + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG);
  28751. + if (retval < 0)
  28752. + return retval;
  28753. +
  28754. + retval = secure_memcpy(&fwu->read_config_buf[fwu->cal_data_off],
  28755. + fwu->cal_data_size, fwu->cal_data,
  28756. + fwu->cal_data_buf_size, fwu->cal_data_size);
  28757. + if (retval < 0) {
  28758. + dev_err(rmi4_data->pdev->dev.parent,
  28759. + "%s: Failed to restore calibration data\n",
  28760. + __func__);
  28761. + return retval;
  28762. + }
  28763. +
  28764. + calculate_checksum((unsigned short *)fwu->read_config_buf,
  28765. + ((fwu->config_size - 4) / 2),
  28766. + &checksum);
  28767. +
  28768. + convert_to_little_endian(checksum_array, checksum);
  28769. +
  28770. + fwu->read_config_buf[fwu->config_size - 4] = checksum_array[0];
  28771. + fwu->read_config_buf[fwu->config_size - 3] = checksum_array[1];
  28772. + fwu->read_config_buf[fwu->config_size - 2] = checksum_array[2];
  28773. + fwu->read_config_buf[fwu->config_size - 1] = checksum_array[3];
  28774. +
  28775. + retval = fwu_enter_flash_prog();
  28776. + if (retval < 0)
  28777. + return retval;
  28778. +
  28779. + fwu->config_area = UI_CONFIG_AREA;
  28780. + fwu->config_data = fwu->read_config_buf;
  28781. + fwu->config_block_count = fwu->config_size / fwu->block_size;
  28782. +
  28783. + retval = fwu_erase_configuration();
  28784. + if (retval < 0)
  28785. + return retval;
  28786. +
  28787. + retval = fwu_write_configuration();
  28788. + if (retval < 0)
  28789. + return retval;
  28790. +
  28791. + return 0;
  28792. +}
  28793. +#endif
  28794. +
  28795. +static int fwu_start_write_guest_code(void)
  28796. +{
  28797. + int retval;
  28798. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28799. +
  28800. + retval = fwu_parse_image_info();
  28801. + if (retval < 0)
  28802. + return -EINVAL;
  28803. +
  28804. + if (!fwu->has_guest_code) {
  28805. + dev_err(rmi4_data->pdev->dev.parent,
  28806. + "%s: Guest code not supported\n",
  28807. + __func__);
  28808. + return -EINVAL;
  28809. + }
  28810. +
  28811. + if (!fwu->img.contains_guest_code) {
  28812. + dev_err(rmi4_data->pdev->dev.parent,
  28813. + "%s: No guest code in firmware image\n",
  28814. + __func__);
  28815. + return -EINVAL;
  28816. + }
  28817. +
  28818. + if (rmi4_data->sensor_sleep) {
  28819. + dev_err(rmi4_data->pdev->dev.parent,
  28820. + "%s: Sensor sleeping\n",
  28821. + __func__);
  28822. + return -ENODEV;
  28823. + }
  28824. +
  28825. + rmi4_data->stay_awake = true;
  28826. +
  28827. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  28828. +
  28829. + pr_notice("%s: Start of write guest code process\n", __func__);
  28830. +
  28831. + retval = fwu_enter_flash_prog();
  28832. + if (retval < 0)
  28833. + goto exit;
  28834. +
  28835. + retval = fwu_check_guest_code_size();
  28836. + if (retval < 0)
  28837. + goto exit;
  28838. +
  28839. + retval = fwu_erase_guest_code();
  28840. + if (retval < 0)
  28841. + goto exit;
  28842. +
  28843. + retval = fwu_write_guest_code();
  28844. + if (retval < 0)
  28845. + goto exit;
  28846. +
  28847. + pr_notice("%s: Guest code programmed\n", __func__);
  28848. +
  28849. +exit:
  28850. + rmi4_data->reset_device(rmi4_data, false);
  28851. +
  28852. + pr_notice("%s: End of write guest code process\n", __func__);
  28853. +
  28854. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  28855. +
  28856. + rmi4_data->stay_awake = false;
  28857. +
  28858. + return retval;
  28859. +}
  28860. +
  28861. +static int fwu_start_write_config(void)
  28862. +{
  28863. + int retval;
  28864. + unsigned short config_area;
  28865. + unsigned int device_fw_id;
  28866. + unsigned int image_fw_id;
  28867. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  28868. +
  28869. + retval = fwu_parse_image_info();
  28870. + if (retval < 0)
  28871. + return -EINVAL;
  28872. +
  28873. + switch (fwu->config_area) {
  28874. + case UI_CONFIG_AREA:
  28875. + device_fw_id = rmi4_data->firmware_id;
  28876. + retval = fwu_get_image_firmware_id(&image_fw_id);
  28877. + if (retval < 0)
  28878. + return retval;
  28879. + if (device_fw_id != image_fw_id) {
  28880. + dev_err(rmi4_data->pdev->dev.parent,
  28881. + "%s: Device and image firmware IDs don't match\n",
  28882. + __func__);
  28883. + return -EINVAL;
  28884. + }
  28885. + retval = fwu_check_ui_configuration_size();
  28886. + if (retval < 0)
  28887. + return retval;
  28888. + break;
  28889. + case DP_CONFIG_AREA:
  28890. + if (!fwu->flash_properties.has_disp_config) {
  28891. + dev_err(rmi4_data->pdev->dev.parent,
  28892. + "%s: Display configuration not supported\n",
  28893. + __func__);
  28894. + return -EINVAL;
  28895. + }
  28896. + if (!fwu->img.contains_disp_config) {
  28897. + dev_err(rmi4_data->pdev->dev.parent,
  28898. + "%s: No display configuration in firmware image\n",
  28899. + __func__);
  28900. + return -EINVAL;
  28901. + }
  28902. + retval = fwu_check_dp_configuration_size();
  28903. + if (retval < 0)
  28904. + return retval;
  28905. + break;
  28906. + case PM_CONFIG_AREA:
  28907. + if (!fwu->flash_properties.has_pm_config) {
  28908. + dev_err(rmi4_data->pdev->dev.parent,
  28909. + "%s: Permanent configuration not supported\n",
  28910. + __func__);
  28911. + return -EINVAL;
  28912. + }
  28913. + if (!fwu->img.contains_perm_config) {
  28914. + dev_err(rmi4_data->pdev->dev.parent,
  28915. + "%s: No permanent configuration in firmware image\n",
  28916. + __func__);
  28917. + return -EINVAL;
  28918. + }
  28919. + retval = fwu_check_pm_configuration_size();
  28920. + if (retval < 0)
  28921. + return retval;
  28922. + break;
  28923. + default:
  28924. + dev_err(rmi4_data->pdev->dev.parent,
  28925. + "%s: Configuration not supported\n",
  28926. + __func__);
  28927. + return -EINVAL;
  28928. + }
  28929. +
  28930. + if (rmi4_data->sensor_sleep) {
  28931. + dev_err(rmi4_data->pdev->dev.parent,
  28932. + "%s: Sensor sleeping\n",
  28933. + __func__);
  28934. + return -ENODEV;
  28935. + }
  28936. +
  28937. + rmi4_data->stay_awake = true;
  28938. +
  28939. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  28940. +
  28941. + pr_notice("%s: Start of write config process\n", __func__);
  28942. +
  28943. + config_area = fwu->config_area;
  28944. +
  28945. + retval = fwu_enter_flash_prog();
  28946. + if (retval < 0)
  28947. + goto exit;
  28948. +
  28949. + fwu->config_area = config_area;
  28950. +
  28951. + if (fwu->config_area != PM_CONFIG_AREA) {
  28952. + retval = fwu_erase_configuration();
  28953. + if (retval < 0) {
  28954. + dev_err(rmi4_data->pdev->dev.parent,
  28955. + "%s: Failed to erase config\n",
  28956. + __func__);
  28957. + goto exit;
  28958. + }
  28959. + }
  28960. +
  28961. + switch (fwu->config_area) {
  28962. + case UI_CONFIG_AREA:
  28963. + retval = fwu_write_ui_configuration();
  28964. + if (retval < 0)
  28965. + goto exit;
  28966. + break;
  28967. + case DP_CONFIG_AREA:
  28968. + retval = fwu_write_dp_configuration();
  28969. + if (retval < 0)
  28970. + goto exit;
  28971. + break;
  28972. + case PM_CONFIG_AREA:
  28973. + retval = fwu_write_pm_configuration();
  28974. + if (retval < 0)
  28975. + goto exit;
  28976. + break;
  28977. + }
  28978. +
  28979. + pr_notice("%s: Config written\n", __func__);
  28980. +
  28981. +exit:
  28982. + switch (fwu->config_area) {
  28983. + case UI_CONFIG_AREA:
  28984. + rmi4_data->reset_device(rmi4_data, true);
  28985. + break;
  28986. + case DP_CONFIG_AREA:
  28987. + case PM_CONFIG_AREA:
  28988. + rmi4_data->reset_device(rmi4_data, false);
  28989. + break;
  28990. + }
  28991. +
  28992. + pr_notice("%s: End of write config process\n", __func__);
  28993. +
  28994. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  28995. +
  28996. + rmi4_data->stay_awake = false;
  28997. +
  28998. + return retval;
  28999. +}
  29000. +
  29001. +static const char *fwu_get_firmware_name(struct synaptics_rmi4_data *rmi4_data)
  29002. +{
  29003. + const char *fw_name = NULL;
  29004. + const struct synaptics_dsx_board_data *bdata =
  29005. + rmi4_data->hw_if->board_data;
  29006. + int i, j, def = -1;
  29007. + bool found = false;
  29008. +
  29009. + if (bdata->tp_id_num != 0) {
  29010. + for (i = 0; i < bdata->config_array_size; i++) {
  29011. + found = true;
  29012. + if (rmi4_data->chip_id != bdata->config_array[i].chip_id)
  29013. + continue;
  29014. + else
  29015. + def = i;
  29016. +
  29017. + for (j = 0; j < bdata->tp_id_num; j++) {
  29018. + if (bdata->config_array[i].tp_ids[j] !=
  29019. + rmi4_data->lockdown_info[bdata->tp_id_bytes[j]]) {
  29020. + found = false;
  29021. + break;
  29022. + }
  29023. + }
  29024. +
  29025. + if (found) {
  29026. + fw_name = bdata->config_array[i].fw_name;
  29027. + break;
  29028. + }
  29029. + }
  29030. + }
  29031. +
  29032. + if (!fw_name && (def >= 0))
  29033. + fw_name = bdata->config_array[def].fw_name;
  29034. +
  29035. + dev_info(rmi4_data->pdev->dev.parent,
  29036. + "%s: Choose firmware %s\n", __func__, fw_name);
  29037. +
  29038. + return fw_name;
  29039. +}
  29040. +
  29041. +static int fwu_start_reflash(void)
  29042. +{
  29043. + int retval = 0;
  29044. + enum flash_area flash_area;
  29045. + bool do_rebuild = false;
  29046. + const struct firmware *fw_entry = NULL;
  29047. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29048. + const char *fw_name;
  29049. +
  29050. + if (rmi4_data->sensor_sleep) {
  29051. + dev_err(rmi4_data->pdev->dev.parent,
  29052. + "%s: Sensor sleeping\n",
  29053. + __func__);
  29054. + return -ENODEV;
  29055. + }
  29056. +
  29057. + fw_name = fwu_get_firmware_name(rmi4_data);
  29058. +
  29059. + if (fw_name == NULL) {
  29060. + dev_err(rmi4_data->pdev->dev.parent, "%s: do not found fw to update\n", __func__);
  29061. +
  29062. + return -EINVAL;
  29063. + }
  29064. +
  29065. +
  29066. + rmi4_data->stay_awake = true;
  29067. +
  29068. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  29069. +
  29070. + dev_info(rmi4_data->pdev->dev.parent, "%s: Start of reflash process\n", __func__);
  29071. +
  29072. + if (fwu->image == NULL) {
  29073. + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN,
  29074. + fw_name, sizeof(FW_IMAGE_NAME),
  29075. + strlen(fw_name));
  29076. +
  29077. + if (retval < 0) {
  29078. + dev_err(rmi4_data->pdev->dev.parent,
  29079. + "%s: Failed to copy image file name\n",
  29080. + __func__);
  29081. + goto exit;
  29082. + }
  29083. + dev_dbg(rmi4_data->pdev->dev.parent,
  29084. + "%s: Requesting firmware image %s\n",
  29085. + __func__, fwu->image_name);
  29086. +
  29087. + retval = request_firmware(&fw_entry, fwu->image_name,
  29088. + rmi4_data->pdev->dev.parent);
  29089. + if (retval != 0) {
  29090. + dev_err(rmi4_data->pdev->dev.parent,
  29091. + "%s: Firmware image %s not available\n",
  29092. + __func__, fwu->image_name);
  29093. + retval = -EINVAL;
  29094. + goto exit;
  29095. + }
  29096. +
  29097. + dev_dbg(rmi4_data->pdev->dev.parent,
  29098. + "%s: Firmware image size = %ld\n",
  29099. + __func__, fw_entry->size);
  29100. +
  29101. + fwu->image = fw_entry->data;
  29102. + }
  29103. +
  29104. + retval = fwu_parse_image_info();
  29105. + if (retval < 0)
  29106. + goto exit;
  29107. +
  29108. + if (fwu->blkcount.total_count != fwu->img.blkcount.total_count) {
  29109. + dev_err(rmi4_data->pdev->dev.parent,
  29110. + "%s: Flash size mismatch\n",
  29111. + __func__);
  29112. + retval = -EINVAL;
  29113. + goto exit;
  29114. + }
  29115. +
  29116. + if (fwu->bl_version != fwu->img.bl_version) {
  29117. + dev_err(rmi4_data->pdev->dev.parent,
  29118. + "%s: Bootloader version mismatch\n",
  29119. + __func__);
  29120. + retval = -EINVAL;
  29121. + goto exit;
  29122. + }
  29123. +
  29124. + retval = fwu_read_flash_status();
  29125. + if (retval < 0)
  29126. + goto exit;
  29127. +
  29128. + if (fwu->in_bl_mode) {
  29129. + fwu->bl_mode_device = true;
  29130. + dev_info(rmi4_data->pdev->dev.parent,
  29131. + "%s: Device in bootloader mode\n",
  29132. + __func__);
  29133. + } else {
  29134. + fwu->bl_mode_device = false;
  29135. + }
  29136. +
  29137. + flash_area = fwu_go_nogo();
  29138. +
  29139. + if (flash_area != NONE) {
  29140. + retval = fwu_enter_flash_prog();
  29141. + if (retval < 0) {
  29142. + rmi4_data->reset_device(rmi4_data, false);
  29143. + goto exit;
  29144. + }
  29145. + }
  29146. +
  29147. +#ifdef F51_DISCRETE_FORCE
  29148. + if (flash_area != NONE && !fwu->bl_mode_device) {
  29149. + fwu->config_size = fwu->block_size * fwu->blkcount.ui_config;
  29150. + fwu->config_area = UI_CONFIG_AREA;
  29151. +
  29152. + retval = fwu_allocate_read_config_buf(fwu->config_size);
  29153. + if (retval < 0) {
  29154. + rmi4_data->reset_device(rmi4_data, false);
  29155. + goto exit;
  29156. + }
  29157. +
  29158. + retval = fwu_read_f34_blocks(fwu->blkcount.ui_config,
  29159. + CMD_READ_CONFIG);
  29160. + if (retval < 0) {
  29161. + rmi4_data->reset_device(rmi4_data, false);
  29162. + goto exit;
  29163. + }
  29164. +
  29165. + retval = secure_memcpy(fwu->cal_data, fwu->cal_data_buf_size,
  29166. + &fwu->read_config_buf[fwu->cal_data_off],
  29167. + fwu->cal_data_size, fwu->cal_data_size);
  29168. + if (retval < 0) {
  29169. + dev_err(rmi4_data->pdev->dev.parent,
  29170. + "%s: Failed to save calibration data\n",
  29171. + __func__);
  29172. + rmi4_data->reset_device(rmi4_data, false);
  29173. + goto exit;
  29174. + }
  29175. + }
  29176. +#endif
  29177. +
  29178. + switch (flash_area) {
  29179. + case UI_FIRMWARE:
  29180. + do_rebuild = true;
  29181. + retval = fwu_do_reflash();
  29182. +#ifdef F51_DISCRETE_FORCE
  29183. + if (retval < 0)
  29184. + break;
  29185. +
  29186. + if (fwu->has_utility_param || fwu->img.contains_utility_param)
  29187. + break;
  29188. +
  29189. + rmi4_data->reset_device(rmi4_data, false);
  29190. +
  29191. + if (fwu->bl_mode_device || fwu->in_bl_mode) {
  29192. + dev_info(rmi4_data->pdev->dev.parent,
  29193. + "%s: Device in bootloader mode, skipping calibration data restoration\n",
  29194. + __func__);
  29195. + break;
  29196. + }
  29197. +
  29198. + retval = fwu_do_restore_f51_cal_data();
  29199. +#endif
  29200. + break;
  29201. + case UI_CONFIG:
  29202. + do_rebuild = true;
  29203. + retval = fwu_check_ui_configuration_size();
  29204. + if (retval < 0)
  29205. + break;
  29206. + fwu->config_area = UI_CONFIG_AREA;
  29207. + retval = fwu_erase_configuration();
  29208. + if (retval < 0)
  29209. + break;
  29210. + retval = fwu_write_ui_configuration();
  29211. +#ifdef F51_DISCRETE_FORCE
  29212. + if (retval < 0)
  29213. + break;
  29214. +
  29215. + if (fwu->has_utility_param)
  29216. + break;
  29217. +
  29218. + retval = fwu_do_restore_f51_cal_data();
  29219. +#endif
  29220. + break;
  29221. + case NONE:
  29222. + default:
  29223. + break;
  29224. + }
  29225. +
  29226. + if (retval < 0) {
  29227. + do_rebuild = false;
  29228. + rmi4_data->reset_device(rmi4_data, false);
  29229. + pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
  29230. + dev_err(rmi4_data->pdev->dev.parent,
  29231. + "%s: Failed to do reflash\n",
  29232. + __func__);
  29233. + goto exit;
  29234. + }
  29235. +
  29236. + if (fwu->do_lockdown && (fwu->img.lockdown.data != NULL)) {
  29237. + switch (fwu->bl_version) {
  29238. + case BL_V5:
  29239. + case BL_V6:
  29240. + retval = fwu_do_lockdown_v5v6();
  29241. + if (retval < 0) {
  29242. + dev_err(rmi4_data->pdev->dev.parent,
  29243. + "%s: Failed to do lockdown\n",
  29244. + __func__);
  29245. + }
  29246. + rmi4_data->reset_device(rmi4_data, false);
  29247. + break;
  29248. + case BL_V7:
  29249. + case BL_V8:
  29250. + retval = fwu_do_lockdown_v7();
  29251. + if (retval < 0) {
  29252. + dev_err(rmi4_data->pdev->dev.parent,
  29253. + "%s: Failed to do lockdown\n",
  29254. + __func__);
  29255. + }
  29256. + rmi4_data->reset_device(rmi4_data, false);
  29257. + break;
  29258. + default:
  29259. + break;
  29260. + }
  29261. + }
  29262. +
  29263. +exit:
  29264. + if (fw_entry)
  29265. + release_firmware(fw_entry);
  29266. +
  29267. + if (do_rebuild)
  29268. + rmi4_data->reset_device(rmi4_data, true);
  29269. +
  29270. + pr_notice("%s: End of reflash process\n", __func__);
  29271. +
  29272. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  29273. +
  29274. + rmi4_data->stay_awake = false;
  29275. +
  29276. + return retval;
  29277. +}
  29278. +
  29279. +static int fwu_recovery_check_status(void)
  29280. +{
  29281. + int retval;
  29282. + unsigned char data_base;
  29283. + unsigned char status;
  29284. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29285. +
  29286. + data_base = fwu->f35_fd.data_base_addr;
  29287. +
  29288. + retval = synaptics_rmi4_reg_read(rmi4_data,
  29289. + data_base + F35_ERROR_CODE_OFFSET,
  29290. + &status,
  29291. + 1);
  29292. + if (retval < 0) {
  29293. + dev_err(rmi4_data->pdev->dev.parent,
  29294. + "%s: Failed to read status\n",
  29295. + __func__);
  29296. + return retval;
  29297. + }
  29298. +
  29299. + status = status & MASK_5BIT;
  29300. +
  29301. + if (status != 0x00) {
  29302. + dev_err(rmi4_data->pdev->dev.parent,
  29303. + "%s: Recovery mode status = %d\n",
  29304. + __func__, status);
  29305. + return -EINVAL;
  29306. + }
  29307. +
  29308. + return 0;
  29309. +}
  29310. +
  29311. +static int fwu_recovery_erase_completion(void)
  29312. +{
  29313. + int retval;
  29314. + unsigned char data_base;
  29315. + unsigned char command;
  29316. + unsigned char status;
  29317. + unsigned int timeout = F35_ERASE_ALL_WAIT_MS / 20;
  29318. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29319. +
  29320. + data_base = fwu->f35_fd.data_base_addr;
  29321. +
  29322. + do {
  29323. + command = 0x01;
  29324. + retval = synaptics_rmi4_reg_write(rmi4_data,
  29325. + fwu->f35_fd.cmd_base_addr,
  29326. + &command,
  29327. + sizeof(command));
  29328. + if (retval < 0) {
  29329. + dev_err(rmi4_data->pdev->dev.parent,
  29330. + "%s: Failed to issue command\n",
  29331. + __func__);
  29332. + return retval;
  29333. + }
  29334. +
  29335. + do {
  29336. + retval = synaptics_rmi4_reg_read(rmi4_data,
  29337. + fwu->f35_fd.cmd_base_addr,
  29338. + &command,
  29339. + sizeof(command));
  29340. + if (retval < 0) {
  29341. + dev_err(rmi4_data->pdev->dev.parent,
  29342. + "%s: Failed to read command status\n",
  29343. + __func__);
  29344. + return retval;
  29345. + }
  29346. +
  29347. + if ((command & 0x01) == 0x00)
  29348. + break;
  29349. +
  29350. + msleep(20);
  29351. + timeout--;
  29352. + } while (timeout > 0);
  29353. +
  29354. + if (timeout == 0)
  29355. + goto exit;
  29356. +
  29357. + retval = synaptics_rmi4_reg_read(rmi4_data,
  29358. + data_base + F35_FLASH_STATUS_OFFSET,
  29359. + &status,
  29360. + sizeof(status));
  29361. + if (retval < 0) {
  29362. + dev_err(rmi4_data->pdev->dev.parent,
  29363. + "%s: Failed to read flash status\n",
  29364. + __func__);
  29365. + return retval;
  29366. + }
  29367. +
  29368. + if ((status & 0x01) == 0x00)
  29369. + break;
  29370. +
  29371. + msleep(20);
  29372. + timeout--;
  29373. + } while (timeout > 0);
  29374. +
  29375. +exit:
  29376. + if (timeout == 0) {
  29377. + dev_err(rmi4_data->pdev->dev.parent,
  29378. + "%s: Timed out waiting for flash erase completion\n",
  29379. + __func__);
  29380. + return -ETIMEDOUT;
  29381. + }
  29382. +
  29383. + return 0;
  29384. +}
  29385. +
  29386. +static int fwu_recovery_erase_all(void)
  29387. +{
  29388. + int retval;
  29389. + unsigned char ctrl_base;
  29390. + unsigned char command = CMD_F35_ERASE_ALL;
  29391. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29392. +
  29393. + ctrl_base = fwu->f35_fd.ctrl_base_addr;
  29394. +
  29395. + retval = synaptics_rmi4_reg_write(rmi4_data,
  29396. + ctrl_base + F35_CHUNK_COMMAND_OFFSET,
  29397. + &command,
  29398. + sizeof(command));
  29399. + if (retval < 0) {
  29400. + dev_err(rmi4_data->pdev->dev.parent,
  29401. + "%s: Failed to issue erase all command\n",
  29402. + __func__);
  29403. + return retval;
  29404. + }
  29405. +
  29406. + if (fwu->f35_fd.cmd_base_addr) {
  29407. + retval = fwu_recovery_erase_completion();
  29408. + if (retval < 0)
  29409. + return retval;
  29410. + } else {
  29411. + msleep(F35_ERASE_ALL_WAIT_MS);
  29412. + }
  29413. +
  29414. + retval = fwu_recovery_check_status();
  29415. + if (retval < 0)
  29416. + return retval;
  29417. +
  29418. + return 0;
  29419. +}
  29420. +
  29421. +static int fwu_recovery_write_chunk(void)
  29422. +{
  29423. + int retval;
  29424. + unsigned char ctrl_base;
  29425. + unsigned char chunk_number[] = {0, 0};
  29426. + unsigned char chunk_spare;
  29427. + unsigned char chunk_size;
  29428. + unsigned char buf[F35_CHUNK_SIZE + 1];
  29429. + unsigned short chunk;
  29430. + unsigned short chunk_total;
  29431. + unsigned short bytes_written = 0;
  29432. + unsigned char *chunk_ptr = (unsigned char *)fwu->image;
  29433. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29434. +
  29435. + ctrl_base = fwu->f35_fd.ctrl_base_addr;
  29436. +
  29437. + retval = synaptics_rmi4_reg_write(rmi4_data,
  29438. + ctrl_base + F35_CHUNK_NUM_LSB_OFFSET,
  29439. + chunk_number,
  29440. + sizeof(chunk_number));
  29441. + if (retval < 0) {
  29442. + dev_err(rmi4_data->pdev->dev.parent,
  29443. + "%s: Failed to write chunk number\n",
  29444. + __func__);
  29445. + return retval;
  29446. + }
  29447. +
  29448. + buf[sizeof(buf) - 1] = CMD_F35_WRITE_CHUNK;
  29449. +
  29450. + chunk_total = fwu->image_size / F35_CHUNK_SIZE;
  29451. + chunk_spare = fwu->image_size % F35_CHUNK_SIZE;
  29452. + if (chunk_spare)
  29453. + chunk_total++;
  29454. +
  29455. + for (chunk = 0; chunk < chunk_total; chunk++) {
  29456. + if (chunk_spare && chunk == chunk_total - 1)
  29457. + chunk_size = chunk_spare;
  29458. + else
  29459. + chunk_size = F35_CHUNK_SIZE;
  29460. +
  29461. + memset(buf, 0x00, F35_CHUNK_SIZE);
  29462. + secure_memcpy(buf, sizeof(buf), chunk_ptr,
  29463. + fwu->image_size - bytes_written,
  29464. + chunk_size);
  29465. +
  29466. + retval = synaptics_rmi4_reg_write(rmi4_data,
  29467. + ctrl_base + F35_CHUNK_DATA_OFFSET,
  29468. + buf,
  29469. + sizeof(buf));
  29470. + if (retval < 0) {
  29471. + dev_err(rmi4_data->pdev->dev.parent,
  29472. + "%s: Failed to write chunk data (chunk %d)\n",
  29473. + __func__, chunk);
  29474. + return retval;
  29475. + }
  29476. + chunk_ptr += chunk_size;
  29477. + bytes_written += chunk_size;
  29478. + }
  29479. +
  29480. + retval = fwu_recovery_check_status();
  29481. + if (retval < 0) {
  29482. + dev_err(rmi4_data->pdev->dev.parent,
  29483. + "%s: Failed to write chunk data\n",
  29484. + __func__);
  29485. + return retval;
  29486. + }
  29487. +
  29488. + return 0;
  29489. +}
  29490. +
  29491. +static int fwu_recovery_reset(void)
  29492. +{
  29493. + int retval;
  29494. + unsigned char ctrl_base;
  29495. + unsigned char command = CMD_F35_RESET;
  29496. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29497. +
  29498. + ctrl_base = fwu->f35_fd.ctrl_base_addr;
  29499. +
  29500. + retval = synaptics_rmi4_reg_write(rmi4_data,
  29501. + ctrl_base + F35_CHUNK_COMMAND_OFFSET,
  29502. + &command,
  29503. + sizeof(command));
  29504. + if (retval < 0) {
  29505. + dev_err(rmi4_data->pdev->dev.parent,
  29506. + "%s: Failed to issue reset command\n",
  29507. + __func__);
  29508. + return retval;
  29509. + }
  29510. +
  29511. + msleep(F35_RESET_WAIT_MS);
  29512. +
  29513. + return 0;
  29514. +}
  29515. +
  29516. +static int fwu_start_recovery(void)
  29517. +{
  29518. + int retval;
  29519. + const struct firmware *fw_entry = NULL;
  29520. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29521. +
  29522. + if (rmi4_data->sensor_sleep) {
  29523. + dev_err(rmi4_data->pdev->dev.parent,
  29524. + "%s: Sensor sleeping\n",
  29525. + __func__);
  29526. + return -ENODEV;
  29527. + }
  29528. +
  29529. + rmi4_data->stay_awake = true;
  29530. +
  29531. + mutex_lock(&rmi4_data->rmi4_exp_init_mutex);
  29532. +
  29533. + pr_notice("%s: Start of recovery process\n", __func__);
  29534. +
  29535. + if (fwu->image == NULL) {
  29536. + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN,
  29537. + FW_IHEX_NAME, sizeof(FW_IHEX_NAME),
  29538. + sizeof(FW_IHEX_NAME));
  29539. + if (retval < 0) {
  29540. + dev_err(rmi4_data->pdev->dev.parent,
  29541. + "%s: Failed to copy ihex file name\n",
  29542. + __func__);
  29543. + goto exit;
  29544. + }
  29545. + dev_dbg(rmi4_data->pdev->dev.parent,
  29546. + "%s: Requesting firmware ihex %s\n",
  29547. + __func__, fwu->image_name);
  29548. +
  29549. + retval = request_firmware(&fw_entry, fwu->image_name,
  29550. + rmi4_data->pdev->dev.parent);
  29551. + if (retval != 0) {
  29552. + dev_err(rmi4_data->pdev->dev.parent,
  29553. + "%s: Firmware ihex %s not available\n",
  29554. + __func__, fwu->image_name);
  29555. + retval = -EINVAL;
  29556. + goto exit;
  29557. + }
  29558. +
  29559. + dev_dbg(rmi4_data->pdev->dev.parent,
  29560. + "%s: Firmware image size = %d\n",
  29561. + __func__, (unsigned int)fw_entry->size);
  29562. +
  29563. + fwu->image = fw_entry->data;
  29564. + fwu->image_size = fw_entry->size;
  29565. + }
  29566. +
  29567. + retval = rmi4_data->irq_enable(rmi4_data, false, false);
  29568. + if (retval < 0) {
  29569. + dev_err(rmi4_data->pdev->dev.parent,
  29570. + "%s: Failed to disable interrupt\n",
  29571. + __func__);
  29572. + goto exit;
  29573. + }
  29574. +
  29575. + retval = fwu_recovery_erase_all();
  29576. + if (retval < 0) {
  29577. + dev_err(rmi4_data->pdev->dev.parent,
  29578. + "%s: Failed to do erase all in recovery mode\n",
  29579. + __func__);
  29580. + goto exit;
  29581. + }
  29582. +
  29583. + pr_notice("%s: External flash erased\n", __func__);
  29584. +
  29585. + retval = fwu_recovery_write_chunk();
  29586. + if (retval < 0) {
  29587. + dev_err(rmi4_data->pdev->dev.parent,
  29588. + "%s: Failed to write chunk data in recovery mode\n",
  29589. + __func__);
  29590. + goto exit;
  29591. + }
  29592. +
  29593. + pr_notice("%s: Chunk data programmed\n", __func__);
  29594. +
  29595. + retval = fwu_recovery_reset();
  29596. + if (retval < 0) {
  29597. + dev_err(rmi4_data->pdev->dev.parent,
  29598. + "%s: Failed to reset device in recovery mode\n",
  29599. + __func__);
  29600. + goto exit;
  29601. + }
  29602. +
  29603. + pr_notice("%s: Recovery mode reset issued\n", __func__);
  29604. +
  29605. + rmi4_data->reset_device(rmi4_data, true);
  29606. +
  29607. + retval = 0;
  29608. +
  29609. +exit:
  29610. + if (fw_entry)
  29611. + release_firmware(fw_entry);
  29612. +
  29613. + pr_notice("%s: End of recovery process\n", __func__);
  29614. +
  29615. + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex);
  29616. +
  29617. + rmi4_data->stay_awake = false;
  29618. +
  29619. + return retval;
  29620. +}
  29621. +
  29622. +int synaptics_fw_updater_force(const unsigned char *fw_data)
  29623. +{
  29624. + int retval;
  29625. +
  29626. + if (!fwu)
  29627. + return -ENODEV;
  29628. +
  29629. + if (!fwu->initialized)
  29630. + return -ENODEV;
  29631. +
  29632. + if (fwu->in_ub_mode)
  29633. + return -ENODEV;
  29634. +
  29635. + fwu->rmi4_data->fw_updating = true;
  29636. + fwu->image = fw_data;
  29637. +
  29638. + retval = fwu_start_reflash();
  29639. +
  29640. + fwu->image = NULL;
  29641. + fwu->rmi4_data->fw_updating = false;
  29642. +
  29643. + return retval;
  29644. +}
  29645. +EXPORT_SYMBOL(synaptics_fw_updater_force);
  29646. +
  29647. +#ifdef DO_STARTUP_FW_UPDATE
  29648. +static void fwu_startup_fw_update_work(struct work_struct *work)
  29649. +{
  29650. + static unsigned char do_once = 1;
  29651. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29652. +
  29653. +#ifdef WAIT_FOR_FB_READY
  29654. + unsigned int timeout;
  29655. +#endif
  29656. + if (!do_once)
  29657. + return;
  29658. + do_once = 0;
  29659. +#ifdef WAIT_FOR_FB_READY
  29660. + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1;
  29661. +
  29662. + while (!rmi4_data->fb_ready) {
  29663. + msleep(FB_READY_WAIT_MS);
  29664. + timeout--;
  29665. + if (timeout == 0) {
  29666. + dev_err(rmi4_data->pdev->dev.parent,
  29667. + "%s: Timed out waiting for FB ready\n",
  29668. + __func__);
  29669. + return;
  29670. + }
  29671. + }
  29672. +#endif
  29673. +
  29674. + synaptics_fw_updater_force(NULL);
  29675. +
  29676. + if (rmi4_data->chip_is_tddi)
  29677. + firmware_force_update(rmi4_data);
  29678. +
  29679. + return;
  29680. +}
  29681. +#endif
  29682. +
  29683. +static ssize_t fwu_sysfs_show_image(struct file *data_file,
  29684. + struct kobject *kobj, struct bin_attribute *attributes,
  29685. + char *buf, loff_t pos, size_t count)
  29686. +{
  29687. + int retval;
  29688. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29689. +
  29690. + if (count < fwu->config_size) {
  29691. + dev_err(rmi4_data->pdev->dev.parent,
  29692. + "%s: Not enough space (%ld bytes) in buffer\n",
  29693. + __func__, count);
  29694. + return -EINVAL;
  29695. + }
  29696. +
  29697. + retval = secure_memcpy(buf, count, fwu->read_config_buf,
  29698. + fwu->read_config_buf_size, fwu->config_size);
  29699. + if (retval < 0) {
  29700. + dev_err(rmi4_data->pdev->dev.parent,
  29701. + "%s: Failed to copy config data\n",
  29702. + __func__);
  29703. + return retval;
  29704. + }
  29705. +
  29706. + return fwu->config_size;
  29707. +}
  29708. +
  29709. +static ssize_t fwu_sysfs_store_image(struct file *data_file,
  29710. + struct kobject *kobj, struct bin_attribute *attributes,
  29711. + char *buf, loff_t pos, size_t count)
  29712. +{
  29713. + int retval;
  29714. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29715. +
  29716. + retval = secure_memcpy(&fwu->ext_data_source[fwu->data_pos],
  29717. + fwu->image_size - fwu->data_pos, buf, count, count);
  29718. + if (retval < 0) {
  29719. + dev_err(rmi4_data->pdev->dev.parent,
  29720. + "%s: Failed to copy image data\n",
  29721. + __func__);
  29722. + return retval;
  29723. + }
  29724. +
  29725. + fwu->data_pos += count;
  29726. +
  29727. + return count;
  29728. +}
  29729. +
  29730. +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev,
  29731. + struct device_attribute *attr, const char *buf, size_t count)
  29732. +{
  29733. + int retval;
  29734. + unsigned int input;
  29735. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29736. +
  29737. + if (sscanf(buf, "%u", &input) != 1) {
  29738. + retval = -EINVAL;
  29739. + goto exit;
  29740. + }
  29741. +
  29742. + retval = fwu_scan_pdt();
  29743. + if (retval < 0)
  29744. + goto exit;
  29745. +
  29746. + pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
  29747. +
  29748. + if (!fwu->in_ub_mode) {
  29749. + dev_err(rmi4_data->pdev->dev.parent,
  29750. + "%s: Not in microbootloader mode\n",
  29751. + __func__);
  29752. + retval = -EINVAL;
  29753. + goto exit;
  29754. + }
  29755. +
  29756. + if (!fwu->ext_data_source)
  29757. + return -EINVAL;
  29758. + else
  29759. + fwu->image = fwu->ext_data_source;
  29760. +
  29761. + retval = fwu_start_recovery();
  29762. + if (retval < 0) {
  29763. + dev_err(rmi4_data->pdev->dev.parent,
  29764. + "%s: Failed to do recovery\n",
  29765. + __func__);
  29766. + goto exit;
  29767. + }
  29768. +
  29769. + retval = count;
  29770. +
  29771. +exit:
  29772. + kfree(fwu->ext_data_source);
  29773. + fwu->ext_data_source = NULL;
  29774. + fwu->image = NULL;
  29775. + return retval;
  29776. +}
  29777. +
  29778. +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
  29779. + struct device_attribute *attr, const char *buf, size_t count)
  29780. +{
  29781. + int retval;
  29782. + unsigned int input;
  29783. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29784. +
  29785. + if (sscanf(buf, "%u", &input) != 1) {
  29786. + retval = -EINVAL;
  29787. + goto exit;
  29788. + }
  29789. +
  29790. + if (fwu->in_ub_mode) {
  29791. + dev_err(rmi4_data->pdev->dev.parent,
  29792. + "%s: In microbootloader mode\n",
  29793. + __func__);
  29794. + retval = -EINVAL;
  29795. + goto exit;
  29796. + }
  29797. +
  29798. + if (!fwu->ext_data_source)
  29799. + return -EINVAL;
  29800. + else
  29801. + fwu->image = fwu->ext_data_source;
  29802. +
  29803. + if (input & LOCKDOWN) {
  29804. + fwu->do_lockdown = true;
  29805. + input &= ~LOCKDOWN;
  29806. + }
  29807. +
  29808. + if ((input != NORMAL) && (input != FORCE)) {
  29809. + retval = -EINVAL;
  29810. + goto exit;
  29811. + }
  29812. +
  29813. + if (input == FORCE)
  29814. + fwu->force_update = true;
  29815. +
  29816. + retval = synaptics_fw_updater_force(fwu->image);
  29817. + if (retval < 0) {
  29818. + dev_err(rmi4_data->pdev->dev.parent,
  29819. + "%s: Failed to do reflash\n",
  29820. + __func__);
  29821. + goto exit;
  29822. + }
  29823. +
  29824. + retval = count;
  29825. +
  29826. +exit:
  29827. + kfree(fwu->ext_data_source);
  29828. + fwu->ext_data_source = NULL;
  29829. + fwu->image = NULL;
  29830. + fwu->force_update = FORCE_UPDATE;
  29831. + fwu->do_lockdown = DO_LOCKDOWN;
  29832. + return retval;
  29833. +}
  29834. +
  29835. +static ssize_t fwu_sysfs_write_config_store(struct device *dev,
  29836. + struct device_attribute *attr, const char *buf, size_t count)
  29837. +{
  29838. + int retval;
  29839. + unsigned int input;
  29840. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29841. +
  29842. + if (sscanf(buf, "%u", &input) != 1) {
  29843. + retval = -EINVAL;
  29844. + goto exit;
  29845. + }
  29846. +
  29847. + if (input != 1) {
  29848. + retval = -EINVAL;
  29849. + goto exit;
  29850. + }
  29851. +
  29852. + if (fwu->in_ub_mode) {
  29853. + dev_err(rmi4_data->pdev->dev.parent,
  29854. + "%s: In microbootloader mode\n",
  29855. + __func__);
  29856. + retval = -EINVAL;
  29857. + goto exit;
  29858. + }
  29859. +
  29860. + if (!fwu->ext_data_source)
  29861. + return -EINVAL;
  29862. + else
  29863. + fwu->image = fwu->ext_data_source;
  29864. +
  29865. + retval = fwu_start_write_config();
  29866. + if (retval < 0) {
  29867. + dev_err(rmi4_data->pdev->dev.parent,
  29868. + "%s: Failed to write config\n",
  29869. + __func__);
  29870. + goto exit;
  29871. + }
  29872. +
  29873. + retval = count;
  29874. +
  29875. +exit:
  29876. + kfree(fwu->ext_data_source);
  29877. + fwu->ext_data_source = NULL;
  29878. + fwu->image = NULL;
  29879. + return retval;
  29880. +}
  29881. +
  29882. +static ssize_t fwu_sysfs_read_config_store(struct device *dev,
  29883. + struct device_attribute *attr, const char *buf, size_t count)
  29884. +{
  29885. + int retval;
  29886. + unsigned int input;
  29887. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29888. +
  29889. + if (sscanf(buf, "%u", &input) != 1)
  29890. + return -EINVAL;
  29891. +
  29892. + if (input != 1)
  29893. + return -EINVAL;
  29894. +
  29895. + if (fwu->in_ub_mode) {
  29896. + dev_err(rmi4_data->pdev->dev.parent,
  29897. + "%s: In microbootloader mode\n",
  29898. + __func__);
  29899. + return -EINVAL;
  29900. + }
  29901. +
  29902. + retval = fwu_do_read_config();
  29903. + if (retval < 0) {
  29904. + dev_err(rmi4_data->pdev->dev.parent,
  29905. + "%s: Failed to read config\n",
  29906. + __func__);
  29907. + return retval;
  29908. + }
  29909. +
  29910. + return count;
  29911. +}
  29912. +
  29913. +static ssize_t fwu_sysfs_config_area_store(struct device *dev,
  29914. + struct device_attribute *attr, const char *buf, size_t count)
  29915. +{
  29916. + int retval;
  29917. + unsigned long config_area;
  29918. +
  29919. + retval = sstrtoul(buf, 10, &config_area);
  29920. + if (retval)
  29921. + return retval;
  29922. +
  29923. + fwu->config_area = config_area;
  29924. +
  29925. + return count;
  29926. +}
  29927. +
  29928. +static ssize_t fwu_sysfs_image_name_store(struct device *dev,
  29929. + struct device_attribute *attr, const char *buf, size_t count)
  29930. +{
  29931. + int retval;
  29932. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29933. +
  29934. + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN,
  29935. + buf, count, count);
  29936. + if (retval < 0) {
  29937. + dev_err(rmi4_data->pdev->dev.parent,
  29938. + "%s: Failed to copy image file name\n",
  29939. + __func__);
  29940. + return retval;
  29941. + }
  29942. +
  29943. + return count;
  29944. +}
  29945. +
  29946. +static ssize_t fwu_sysfs_image_size_store(struct device *dev,
  29947. + struct device_attribute *attr, const char *buf, size_t count)
  29948. +{
  29949. + int retval;
  29950. + unsigned long size;
  29951. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  29952. +
  29953. + retval = sstrtoul(buf, 10, &size);
  29954. + if (retval)
  29955. + return retval;
  29956. +
  29957. + fwu->image_size = size;
  29958. + fwu->data_pos = 0;
  29959. +
  29960. + kfree(fwu->ext_data_source);
  29961. + fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
  29962. + if (!fwu->ext_data_source) {
  29963. + dev_err(rmi4_data->pdev->dev.parent,
  29964. + "%s: Failed to alloc mem for image data\n",
  29965. + __func__);
  29966. + return -ENOMEM;
  29967. + }
  29968. +
  29969. + return count;
  29970. +}
  29971. +
  29972. +static ssize_t fwu_sysfs_block_size_show(struct device *dev,
  29973. + struct device_attribute *attr, char *buf)
  29974. +{
  29975. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
  29976. +}
  29977. +
  29978. +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
  29979. + struct device_attribute *attr, char *buf)
  29980. +{
  29981. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_firmware);
  29982. +}
  29983. +
  29984. +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
  29985. + struct device_attribute *attr, char *buf)
  29986. +{
  29987. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_config);
  29988. +}
  29989. +
  29990. +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
  29991. + struct device_attribute *attr, char *buf)
  29992. +{
  29993. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.dp_config);
  29994. +}
  29995. +
  29996. +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
  29997. + struct device_attribute *attr, char *buf)
  29998. +{
  29999. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.pm_config);
  30000. +}
  30001. +
  30002. +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
  30003. + struct device_attribute *attr, char *buf)
  30004. +{
  30005. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.bl_config);
  30006. +}
  30007. +
  30008. +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev,
  30009. + struct device_attribute *attr, char *buf)
  30010. +{
  30011. + return snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.guest_code);
  30012. +}
  30013. +
  30014. +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev,
  30015. + struct device_attribute *attr, const char *buf, size_t count)
  30016. +{
  30017. + int retval;
  30018. + unsigned int input;
  30019. + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
  30020. +
  30021. + if (sscanf(buf, "%u", &input) != 1) {
  30022. + retval = -EINVAL;
  30023. + goto exit;
  30024. + }
  30025. +
  30026. + if (input != 1) {
  30027. + retval = -EINVAL;
  30028. + goto exit;
  30029. + }
  30030. +
  30031. + if (fwu->in_ub_mode) {
  30032. + dev_err(rmi4_data->pdev->dev.parent,
  30033. + "%s: In microbootloader mode\n",
  30034. + __func__);
  30035. + retval = -EINVAL;
  30036. + goto exit;
  30037. + }
  30038. +
  30039. + if (!fwu->ext_data_source)
  30040. + return -EINVAL;
  30041. + else
  30042. + fwu->image = fwu->ext_data_source;
  30043. +
  30044. + retval = fwu_start_write_guest_code();
  30045. + if (retval < 0) {
  30046. + dev_err(rmi4_data->pdev->dev.parent,
  30047. + "%s: Failed to write guest code\n",
  30048. + __func__);
  30049. + goto exit;
  30050. + }
  30051. +
  30052. + retval = count;
  30053. +
  30054. +exit:
  30055. + kfree(fwu->ext_data_source);
  30056. + fwu->ext_data_source = NULL;
  30057. + fwu->image = NULL;
  30058. + return retval;
  30059. +}
  30060. +
  30061. +static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
  30062. + unsigned char intr_mask)
  30063. +{
  30064. + if (!fwu)
  30065. + return;
  30066. +
  30067. + if (fwu->intr_mask & intr_mask)
  30068. + fwu_read_flash_status();
  30069. +
  30070. + return;
  30071. +}
  30072. +
  30073. +static void firmware_force_update(struct synaptics_rmi4_data *rmi4_data)
  30074. +{
  30075. + int retval;
  30076. + const struct firmware *fw_entry = NULL;
  30077. + const struct synaptics_dsx_board_data *bdata = rmi4_data->hw_if->board_data;
  30078. + if (!fwu->in_ub_mode)
  30079. + return;
  30080. +
  30081. + retval = request_firmware(&fw_entry, bdata->backup_fw_name,
  30082. + rmi4_data->pdev->dev.parent);
  30083. + if (retval != 0) {
  30084. + dev_err(rmi4_data->pdev->dev.parent,
  30085. + "%s: Firmware image %s not available\n",
  30086. + __func__, fwu->image_name);
  30087. + return;
  30088. + }
  30089. +
  30090. + fwu->image = fw_entry->data;
  30091. + fwu->image_size = fw_entry->size;
  30092. +
  30093. + retval = fwu_start_recovery();
  30094. + if (retval < 0) {
  30095. + dev_err(rmi4_data->pdev->dev.parent,
  30096. + "%s: Failed to do recovery\n",
  30097. + __func__);
  30098. + release_firmware(fw_entry);
  30099. + return;
  30100. + }
  30101. +
  30102. + release_firmware(fw_entry);
  30103. +
  30104. + return;
  30105. +}
  30106. +
  30107. +static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
  30108. +{
  30109. + int retval;
  30110. + unsigned char attr_count;
  30111. + struct pdt_properties pdt_props;
  30112. +
  30113. + if (fwu) {
  30114. + dev_dbg(rmi4_data->pdev->dev.parent,
  30115. + "%s: Handle already exists\n",
  30116. + __func__);
  30117. + return 0;
  30118. + }
  30119. +
  30120. + fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
  30121. + if (!fwu) {
  30122. + dev_err(rmi4_data->pdev->dev.parent,
  30123. + "%s: Failed to alloc mem for fwu\n",
  30124. + __func__);
  30125. + retval = -ENOMEM;
  30126. + goto exit;
  30127. + }
  30128. +
  30129. + fwu->image_name = kzalloc(MAX_IMAGE_NAME_LEN, GFP_KERNEL);
  30130. + if (!fwu->image_name) {
  30131. + dev_err(rmi4_data->pdev->dev.parent,
  30132. + "%s: Failed to alloc mem for image name\n",
  30133. + __func__);
  30134. + retval = -ENOMEM;
  30135. + goto exit_free_fwu;
  30136. + }
  30137. +
  30138. + fwu->rmi4_data = rmi4_data;
  30139. +
  30140. + retval = synaptics_rmi4_reg_read(rmi4_data,
  30141. + PDT_PROPS,
  30142. + pdt_props.data,
  30143. + sizeof(pdt_props.data));
  30144. + if (retval < 0) {
  30145. + dev_dbg(rmi4_data->pdev->dev.parent,
  30146. + "%s: Failed to read PDT properties, assuming 0x00\n",
  30147. + __func__);
  30148. + } else if (pdt_props.has_bsr) {
  30149. + dev_err(rmi4_data->pdev->dev.parent,
  30150. + "%s: Reflash for LTS not currently supported\n",
  30151. + __func__);
  30152. + retval = -ENODEV;
  30153. + goto exit_free_mem;
  30154. + }
  30155. +
  30156. + retval = fwu_scan_pdt();
  30157. + if (retval < 0)
  30158. + goto exit_free_mem;
  30159. +
  30160. + pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
  30161. +
  30162. + if (!fwu->in_ub_mode) {
  30163. + retval = fwu_read_f34_queries();
  30164. + if (retval < 0)
  30165. + goto exit_free_mem;
  30166. +
  30167. + retval = fwu_get_device_config_id();
  30168. + if (retval < 0) {
  30169. + dev_err(rmi4_data->pdev->dev.parent,
  30170. + "%s: Failed to read device config ID\n",
  30171. + __func__);
  30172. + goto exit_free_mem;
  30173. + }
  30174. + }
  30175. +
  30176. + fwu->force_update = FORCE_UPDATE;
  30177. + fwu->do_lockdown = DO_LOCKDOWN;
  30178. + fwu->initialized = true;
  30179. +
  30180. + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
  30181. + &dev_attr_data);
  30182. + if (retval < 0) {
  30183. + dev_err(rmi4_data->pdev->dev.parent,
  30184. + "%s: Failed to create sysfs bin file\n",
  30185. + __func__);
  30186. + goto exit_free_mem;
  30187. + }
  30188. +
  30189. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  30190. + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
  30191. + &attrs[attr_count].attr);
  30192. + if (retval < 0) {
  30193. + dev_err(rmi4_data->pdev->dev.parent,
  30194. + "%s: Failed to create sysfs attributes\n",
  30195. + __func__);
  30196. + retval = -ENODEV;
  30197. + goto exit_remove_attrs;
  30198. + }
  30199. + }
  30200. +
  30201. +#ifdef DO_STARTUP_FW_UPDATE
  30202. + fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue");
  30203. + INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work);
  30204. + queue_work(fwu->fwu_workqueue,
  30205. + &fwu->fwu_work);
  30206. +#endif
  30207. +
  30208. +#ifdef F51_DISCRETE_FORCE
  30209. + fwu_read_flash_status();
  30210. + if (!fwu->in_bl_mode) {
  30211. + retval = fwu_f51_force_data_init();
  30212. + if (retval < 0)
  30213. + goto exit_remove_attrs;
  30214. + }
  30215. +#endif
  30216. +
  30217. + return 0;
  30218. +
  30219. +exit_remove_attrs:
  30220. + for (attr_count--; attr_count >= 0; attr_count--) {
  30221. + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
  30222. + &attrs[attr_count].attr);
  30223. + }
  30224. +
  30225. + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
  30226. +
  30227. +exit_free_mem:
  30228. + kfree(fwu->image_name);
  30229. +
  30230. +exit_free_fwu:
  30231. + kfree(fwu);
  30232. + fwu = NULL;
  30233. +
  30234. +exit:
  30235. + return retval;
  30236. +}
  30237. +
  30238. +static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
  30239. +{
  30240. + unsigned char attr_count;
  30241. +
  30242. + if (!fwu)
  30243. + goto exit;
  30244. +
  30245. +#ifdef DO_STARTUP_FW_UPDATE
  30246. + cancel_work_sync(&fwu->fwu_work);
  30247. + flush_workqueue(fwu->fwu_workqueue);
  30248. + destroy_workqueue(fwu->fwu_workqueue);
  30249. +#endif
  30250. +
  30251. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  30252. + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
  30253. + &attrs[attr_count].attr);
  30254. + }
  30255. +
  30256. + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
  30257. +
  30258. +#ifdef F51_DISCRETE_FORCE
  30259. + kfree(fwu->cal_data);
  30260. +#endif
  30261. + kfree(fwu->read_config_buf);
  30262. + kfree(fwu->image_name);
  30263. + kfree(fwu);
  30264. + fwu = NULL;
  30265. +
  30266. +exit:
  30267. + complete(&fwu_remove_complete_force);
  30268. +
  30269. + return;
  30270. +}
  30271. +
  30272. +static void synaptics_rmi4_fwu_reset(struct synaptics_rmi4_data *rmi4_data)
  30273. +{
  30274. + int retval;
  30275. +
  30276. + if (!fwu) {
  30277. + synaptics_rmi4_fwu_init(rmi4_data);
  30278. + return;
  30279. + }
  30280. +
  30281. + retval = fwu_scan_pdt();
  30282. + if (retval < 0)
  30283. + return;
  30284. +
  30285. + pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
  30286. +
  30287. + if (!fwu->in_ub_mode)
  30288. + fwu_read_f34_queries();
  30289. +
  30290. +#ifdef F51_DISCRETE_FORCE
  30291. + fwu_read_flash_status();
  30292. + if (!fwu->in_bl_mode)
  30293. + fwu_f51_force_data_init();
  30294. +#endif
  30295. +
  30296. + return;
  30297. +}
  30298. +
  30299. +#if 0
  30300. +static void synaptics_rmi4_fwu_resume(struct synaptics_rmi4_data *rmi4_data)
  30301. +{
  30302. + int retval;
  30303. +
  30304. + if (!fwu)
  30305. + return;
  30306. +
  30307. + retval = fwu_scan_pdt();
  30308. + if (retval < 0)
  30309. + return;
  30310. +
  30311. + pr_err("%s: fwu->in_ub_mode = %d\n", __func__, fwu->in_ub_mode);
  30312. +
  30313. + if (!fwu->in_ub_mode)
  30314. + fwu_read_f34_queries();
  30315. +
  30316. + return;
  30317. +}
  30318. +#endif
  30319. +
  30320. +static struct synaptics_rmi4_exp_fn fwu_module = {
  30321. + .fn_type = RMI_FW_UPDATER,
  30322. + .init = synaptics_rmi4_fwu_init,
  30323. + .remove = synaptics_rmi4_fwu_remove,
  30324. + .reset = synaptics_rmi4_fwu_reset,
  30325. + .reinit = NULL,
  30326. + .early_suspend = NULL,
  30327. + .suspend = NULL,
  30328. + .resume = NULL,
  30329. + .late_resume = NULL,
  30330. + .attn = synaptics_rmi4_fwu_attn,
  30331. +};
  30332. +
  30333. +static int __init rmi4_fw_update_module_init(void)
  30334. +{
  30335. + synaptics_rmi4_new_function_force(&fwu_module, true);
  30336. +
  30337. + return 0;
  30338. +}
  30339. +
  30340. +static void __exit rmi4_fw_update_module_exit(void)
  30341. +{
  30342. + synaptics_rmi4_new_function_force(&fwu_module, false);
  30343. +
  30344. + wait_for_completion(&fwu_remove_complete_force);
  30345. +
  30346. + return;
  30347. +}
  30348. +
  30349. +module_init(rmi4_fw_update_module_init);
  30350. +module_exit(rmi4_fw_update_module_exit);
  30351. +
  30352. +MODULE_AUTHOR("Synaptics, Inc.");
  30353. +MODULE_DESCRIPTION("Synaptics DSX FW Update Module");
  30354. +MODULE_LICENSE("GPL v2");
  30355. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_gesture.c b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_gesture.c
  30356. new file mode 100644
  30357. index 0000000..9ec8235
  30358. --- /dev/null
  30359. +++ b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_gesture.c
  30360. @@ -0,0 +1,2312 @@
  30361. +/*
  30362. + * Synaptics DSX touchscreen driver
  30363. + *
  30364. + * Copyright (C) 2012-2015 Synaptics Incorporated. All rights reserved.
  30365. + *
  30366. + * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
  30367. + * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
  30368. + * Copyright (C) 2017 XiaoMi, Inc.
  30369. + *
  30370. + * This program is free software; you can redistribute it and/or modify
  30371. + * it under the terms of the GNU General Public License as published by
  30372. + * the Free Software Foundation; either version 2 of the License, or
  30373. + * (at your option) any later version.
  30374. + *
  30375. + * This program is distributed in the hope that it will be useful,
  30376. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30377. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30378. + * GNU General Public License for more details.
  30379. + *
  30380. + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  30381. + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  30382. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  30383. + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  30384. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  30385. + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  30386. + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  30387. + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  30388. + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  30389. + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  30390. + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  30391. + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  30392. + * DOLLARS.
  30393. + */
  30394. +
  30395. +#include <linux/kernel.h>
  30396. +#include <linux/module.h>
  30397. +#include <linux/slab.h>
  30398. +#include <linux/interrupt.h>
  30399. +#include <linux/delay.h>
  30400. +#include <linux/input.h>
  30401. +#include <linux/platform_device.h>
  30402. +#include <linux/input/synaptics_dsx.h>
  30403. +#include "synaptics_dsx_core.h"
  30404. +
  30405. +#define GESTURE_PHYS_NAME "synaptics_dsx/gesture"
  30406. +
  30407. +#define TUNING_SYSFS_DIR_NAME "tuning"
  30408. +
  30409. +#define STORE_GESTURES
  30410. +#ifdef STORE_GESTURES
  30411. +#define GESTURES_TO_STORE 10
  30412. +#endif
  30413. +
  30414. +#define CTRL23_FINGER_REPORT_ENABLE_BIT 0
  30415. +#define CTRL27_UDG_ENABLE_BIT 4
  30416. +#define WAKEUP_GESTURE_MODE 0x02
  30417. +
  30418. +static ssize_t udg_sysfs_engine_enable_store(struct device *dev,
  30419. + struct device_attribute *attr, const char *buf, size_t count);
  30420. +
  30421. +static ssize_t udg_sysfs_detection_enable_store(struct device *dev,
  30422. + struct device_attribute *attr, const char *buf, size_t count);
  30423. +
  30424. +static ssize_t udg_sysfs_detection_score_show(struct device *dev,
  30425. + struct device_attribute *attr, char *buf);
  30426. +
  30427. +static ssize_t udg_sysfs_detection_index_show(struct device *dev,
  30428. + struct device_attribute *attr, char *buf);
  30429. +
  30430. +static ssize_t udg_sysfs_registration_enable_store(struct device *dev,
  30431. + struct device_attribute *attr, const char *buf, size_t count);
  30432. +
  30433. +static ssize_t udg_sysfs_registration_begin_store(struct device *dev,
  30434. + struct device_attribute *attr, const char *buf, size_t count);
  30435. +
  30436. +static ssize_t udg_sysfs_registration_status_show(struct device *dev,
  30437. + struct device_attribute *attr, char *buf);
  30438. +
  30439. +static ssize_t udg_sysfs_template_size_show(struct device *dev,
  30440. + struct device_attribute *attr, char *buf);
  30441. +
  30442. +static ssize_t udg_sysfs_template_max_index_show(struct device *dev,
  30443. + struct device_attribute *attr, char *buf);
  30444. +
  30445. +static ssize_t udg_sysfs_template_detection_show(struct device *dev,
  30446. + struct device_attribute *attr, char *buf);
  30447. +
  30448. +static ssize_t udg_sysfs_template_index_store(struct device *dev,
  30449. + struct device_attribute *attr, const char *buf, size_t count);
  30450. +
  30451. +static ssize_t udg_sysfs_template_valid_show(struct device *dev,
  30452. + struct device_attribute *attr, char *buf);
  30453. +
  30454. +static ssize_t udg_sysfs_template_valid_store(struct device *dev,
  30455. + struct device_attribute *attr, const char *buf, size_t count);
  30456. +
  30457. +static ssize_t udg_sysfs_template_clear_store(struct device *dev,
  30458. + struct device_attribute *attr, const char *buf, size_t count);
  30459. +
  30460. +static ssize_t udg_sysfs_trace_size_show(struct device *dev,
  30461. + struct device_attribute *attr, char *buf);
  30462. +
  30463. +static ssize_t udg_sysfs_template_data_show(struct file *data_file,
  30464. + struct kobject *kobj, struct bin_attribute *attributes,
  30465. + char *buf, loff_t pos, size_t count);
  30466. +
  30467. +static ssize_t udg_sysfs_template_data_store(struct file *data_file,
  30468. + struct kobject *kobj, struct bin_attribute *attributes,
  30469. + char *buf, loff_t pos, size_t count);
  30470. +
  30471. +static ssize_t udg_sysfs_trace_data_show(struct file *data_file,
  30472. + struct kobject *kobj, struct bin_attribute *attributes,
  30473. + char *buf, loff_t pos, size_t count);
  30474. +
  30475. +static ssize_t udg_sysfs_template_displacement_show(struct device *dev,
  30476. + struct device_attribute *attr, char *buf);
  30477. +
  30478. +static ssize_t udg_sysfs_template_displacement_store(struct device *dev,
  30479. + struct device_attribute *attr, const char *buf, size_t count);
  30480. +
  30481. +static ssize_t udg_sysfs_rotation_invariance_show(struct device *dev,
  30482. + struct device_attribute *attr, char *buf);
  30483. +
  30484. +static ssize_t udg_sysfs_rotation_invariance_store(struct device *dev,
  30485. + struct device_attribute *attr, const char *buf, size_t count);
  30486. +
  30487. +static ssize_t udg_sysfs_scale_invariance_show(struct device *dev,
  30488. + struct device_attribute *attr, char *buf);
  30489. +
  30490. +static ssize_t udg_sysfs_scale_invariance_store(struct device *dev,
  30491. + struct device_attribute *attr, const char *buf, size_t count);
  30492. +
  30493. +static ssize_t udg_sysfs_threshold_factor_show(struct device *dev,
  30494. + struct device_attribute *attr, char *buf);
  30495. +
  30496. +static ssize_t udg_sysfs_threshold_factor_store(struct device *dev,
  30497. + struct device_attribute *attr, const char *buf, size_t count);
  30498. +
  30499. +static ssize_t udg_sysfs_match_metric_threshold_show(struct device *dev,
  30500. + struct device_attribute *attr, char *buf);
  30501. +
  30502. +static ssize_t udg_sysfs_match_metric_threshold_store(struct device *dev,
  30503. + struct device_attribute *attr, const char *buf, size_t count);
  30504. +
  30505. +static ssize_t udg_sysfs_max_inter_stroke_time_show(struct device *dev,
  30506. + struct device_attribute *attr, char *buf);
  30507. +
  30508. +static ssize_t udg_sysfs_max_inter_stroke_time_store(struct device *dev,
  30509. + struct device_attribute *attr, const char *buf, size_t count);
  30510. +
  30511. +static int udg_read_tuning_params(void);
  30512. +
  30513. +static int udg_write_tuning_params(void);
  30514. +
  30515. +static int udg_detection_enable(bool enable);
  30516. +
  30517. +static int udg_engine_enable(bool enable);
  30518. +
  30519. +static int udg_set_index(unsigned char index);
  30520. +
  30521. +#ifdef STORE_GESTURES
  30522. +static int udg_read_valid_data(void);
  30523. +static int udg_write_valid_data(void);
  30524. +static int udg_read_template_data(unsigned char index);
  30525. +static int udg_write_template_data(void);
  30526. +#endif
  30527. +
  30528. +enum gesture_type {
  30529. + DETECTION = 0x0f,
  30530. + REGISTRATION = 0x10,
  30531. +};
  30532. +
  30533. +struct udg_tuning {
  30534. + union {
  30535. + struct {
  30536. + unsigned char maximum_number_of_templates;
  30537. + unsigned char template_size;
  30538. + unsigned char template_disp_lsb;
  30539. + unsigned char template_disp_msb;
  30540. + unsigned char rotation_inv_lsb;
  30541. + unsigned char rotation_inv_msb;
  30542. + unsigned char scale_inv_lsb;
  30543. + unsigned char scale_inv_msb;
  30544. + unsigned char thres_factor_lsb;
  30545. + unsigned char thres_factor_msb;
  30546. + unsigned char metric_thres_lsb;
  30547. + unsigned char metric_thres_msb;
  30548. + unsigned char inter_stroke_lsb;
  30549. + unsigned char inter_stroke_msb;
  30550. + } __packed;
  30551. + unsigned char data[14];
  30552. + };
  30553. +};
  30554. +
  30555. +struct udg_addr {
  30556. + unsigned short data_4;
  30557. + unsigned short ctrl_18;
  30558. + unsigned short ctrl_20;
  30559. + unsigned short ctrl_23;
  30560. + unsigned short ctrl_27;
  30561. + unsigned short ctrl_41;
  30562. + unsigned short trace_x;
  30563. + unsigned short trace_y;
  30564. + unsigned short trace_segment;
  30565. + unsigned short template_helper;
  30566. + unsigned short template_data;
  30567. + unsigned short template_flags;
  30568. +};
  30569. +
  30570. +struct synaptics_rmi4_f12_query_0 {
  30571. + union {
  30572. + struct {
  30573. + struct {
  30574. + unsigned char has_register_descriptors:1;
  30575. + unsigned char has_closed_cover:1;
  30576. + unsigned char has_fast_glove_detect:1;
  30577. + unsigned char has_dribble:1;
  30578. + unsigned char has_4p4_jitter_filter_strength:1;
  30579. + unsigned char f12_query0_s0_b5__7:3;
  30580. + } __packed;
  30581. + struct {
  30582. + unsigned char max_num_templates:4;
  30583. + unsigned char f12_query0_s1_b4__7:4;
  30584. + unsigned char template_size_lsb;
  30585. + unsigned char template_size_msb;
  30586. + } __packed;
  30587. + };
  30588. + unsigned char data[4];
  30589. + };
  30590. +};
  30591. +
  30592. +struct synaptics_rmi4_f12_query_5 {
  30593. + union {
  30594. + struct {
  30595. + unsigned char size_of_query6;
  30596. + struct {
  30597. + unsigned char ctrl0_is_present:1;
  30598. + unsigned char ctrl1_is_present:1;
  30599. + unsigned char ctrl2_is_present:1;
  30600. + unsigned char ctrl3_is_present:1;
  30601. + unsigned char ctrl4_is_present:1;
  30602. + unsigned char ctrl5_is_present:1;
  30603. + unsigned char ctrl6_is_present:1;
  30604. + unsigned char ctrl7_is_present:1;
  30605. + } __packed;
  30606. + struct {
  30607. + unsigned char ctrl8_is_present:1;
  30608. + unsigned char ctrl9_is_present:1;
  30609. + unsigned char ctrl10_is_present:1;
  30610. + unsigned char ctrl11_is_present:1;
  30611. + unsigned char ctrl12_is_present:1;
  30612. + unsigned char ctrl13_is_present:1;
  30613. + unsigned char ctrl14_is_present:1;
  30614. + unsigned char ctrl15_is_present:1;
  30615. + } __packed;
  30616. + struct {
  30617. + unsigned char ctrl16_is_present:1;
  30618. + unsigned char ctrl17_is_present:1;
  30619. + unsigned char ctrl18_is_present:1;
  30620. + unsigned char ctrl19_is_present:1;
  30621. + unsigned char ctrl20_is_present:1;
  30622. + unsigned char ctrl21_is_present:1;
  30623. + unsigned char ctrl22_is_present:1;
  30624. + unsigned char ctrl23_is_present:1;
  30625. + } __packed;
  30626. + struct {
  30627. + unsigned char ctrl24_is_present:1;
  30628. + unsigned char ctrl25_is_present:1;
  30629. + unsigned char ctrl26_is_present:1;
  30630. + unsigned char ctrl27_is_present:1;
  30631. + unsigned char ctrl28_is_present:1;
  30632. + unsigned char ctrl29_is_present:1;
  30633. + unsigned char ctrl30_is_present:1;
  30634. + unsigned char ctrl31_is_present:1;
  30635. + } __packed;
  30636. + struct {
  30637. + unsigned char ctrl32_is_present:1;
  30638. + unsigned char ctrl33_is_present:1;
  30639. + unsigned char ctrl34_is_present:1;
  30640. + unsigned char ctrl35_is_present:1;
  30641. + unsigned char ctrl36_is_present:1;
  30642. + unsigned char ctrl37_is_present:1;
  30643. + unsigned char ctrl38_is_present:1;
  30644. + unsigned char ctrl39_is_present:1;
  30645. + } __packed;
  30646. + struct {
  30647. + unsigned char ctrl40_is_present:1;
  30648. + unsigned char ctrl41_is_present:1;
  30649. + unsigned char ctrl42_is_present:1;
  30650. + unsigned char ctrl43_is_present:1;
  30651. + unsigned char ctrl44_is_present:1;
  30652. + unsigned char ctrl45_is_present:1;
  30653. + unsigned char ctrl46_is_present:1;
  30654. + unsigned char ctrl47_is_present:1;
  30655. + } __packed;
  30656. + };
  30657. + unsigned char data[7];
  30658. + };
  30659. +};
  30660. +
  30661. +struct synaptics_rmi4_f12_query_8 {
  30662. + union {
  30663. + struct {
  30664. + unsigned char size_of_query9;
  30665. + struct {
  30666. + unsigned char data0_is_present:1;
  30667. + unsigned char data1_is_present:1;
  30668. + unsigned char data2_is_present:1;
  30669. + unsigned char data3_is_present:1;
  30670. + unsigned char data4_is_present:1;
  30671. + unsigned char data5_is_present:1;
  30672. + unsigned char data6_is_present:1;
  30673. + unsigned char data7_is_present:1;
  30674. + } __packed;
  30675. + struct {
  30676. + unsigned char data8_is_present:1;
  30677. + unsigned char data9_is_present:1;
  30678. + unsigned char data10_is_present:1;
  30679. + unsigned char data11_is_present:1;
  30680. + unsigned char data12_is_present:1;
  30681. + unsigned char data13_is_present:1;
  30682. + unsigned char data14_is_present:1;
  30683. + unsigned char data15_is_present:1;
  30684. + } __packed;
  30685. + struct {
  30686. + unsigned char data16_is_present:1;
  30687. + unsigned char data17_is_present:1;
  30688. + unsigned char data18_is_present:1;
  30689. + unsigned char data19_is_present:1;
  30690. + unsigned char data20_is_present:1;
  30691. + unsigned char data21_is_present:1;
  30692. + unsigned char data22_is_present:1;
  30693. + unsigned char data23_is_present:1;
  30694. + } __packed;
  30695. + };
  30696. + unsigned char data[4];
  30697. + };
  30698. +};
  30699. +
  30700. +struct synaptics_rmi4_f12_control_41 {
  30701. + union {
  30702. + struct {
  30703. + unsigned char enable_registration:1;
  30704. + unsigned char template_index:4;
  30705. + unsigned char begin:1;
  30706. + unsigned char f12_ctrl41_b6__7:2;
  30707. + } __packed;
  30708. + unsigned char data[1];
  30709. + };
  30710. +};
  30711. +
  30712. +struct synaptics_rmi4_udg_handle {
  30713. + atomic_t attn_event;
  30714. + unsigned char intr_mask;
  30715. + unsigned char report_flags;
  30716. + unsigned char object_type_enable1;
  30717. + unsigned char object_type_enable2;
  30718. + unsigned char trace_size;
  30719. + unsigned char template_index;
  30720. + unsigned char max_num_templates;
  30721. + unsigned char detection_score;
  30722. + unsigned char detection_index;
  30723. + unsigned char detection_status;
  30724. + unsigned char registration_status;
  30725. + unsigned char *ctrl_buf;
  30726. + unsigned char *trace_data_buf;
  30727. + unsigned char *template_data_buf;
  30728. +#ifdef STORE_GESTURES
  30729. + unsigned char gestures_to_store;
  30730. + unsigned char *storage_buf;
  30731. + unsigned char valid_buf[2];
  30732. +#endif
  30733. + unsigned short trace_data_buf_size;
  30734. + unsigned short template_size;
  30735. + unsigned short template_data_size;
  30736. + unsigned short query_base_addr;
  30737. + unsigned short control_base_addr;
  30738. + unsigned short data_base_addr;
  30739. + unsigned short command_base_addr;
  30740. + unsigned short ctrl_18_sub10_off;
  30741. + unsigned short ctrl_20_sub1_off;
  30742. + unsigned short ctrl_23_sub3_off;
  30743. + unsigned short ctrl_27_sub5_off;
  30744. + struct input_dev *udg_dev;
  30745. + struct kobject *tuning_dir;
  30746. + struct udg_addr addr;
  30747. + struct udg_tuning tuning;
  30748. + struct synaptics_rmi4_data *rmi4_data;
  30749. +};
  30750. +
  30751. +static struct device_attribute attrs[] = {
  30752. + __ATTR(engine_enable, S_IWUSR,
  30753. + synaptics_rmi4_show_error,
  30754. + udg_sysfs_engine_enable_store),
  30755. + __ATTR(detection_enable, S_IWUSR,
  30756. + synaptics_rmi4_show_error,
  30757. + udg_sysfs_detection_enable_store),
  30758. + __ATTR(detection_score, S_IRUGO,
  30759. + udg_sysfs_detection_score_show,
  30760. + synaptics_rmi4_store_error),
  30761. + __ATTR(detection_index, S_IRUGO,
  30762. + udg_sysfs_detection_index_show,
  30763. + synaptics_rmi4_store_error),
  30764. + __ATTR(registration_enable, S_IWUSR,
  30765. + synaptics_rmi4_show_error,
  30766. + udg_sysfs_registration_enable_store),
  30767. + __ATTR(registration_begin, S_IWUSR,
  30768. + synaptics_rmi4_show_error,
  30769. + udg_sysfs_registration_begin_store),
  30770. + __ATTR(registration_status, S_IRUGO,
  30771. + udg_sysfs_registration_status_show,
  30772. + synaptics_rmi4_store_error),
  30773. + __ATTR(template_size, S_IRUGO,
  30774. + udg_sysfs_template_size_show,
  30775. + synaptics_rmi4_store_error),
  30776. + __ATTR(template_max_index, S_IRUGO,
  30777. + udg_sysfs_template_max_index_show,
  30778. + synaptics_rmi4_store_error),
  30779. + __ATTR(template_detection, S_IRUGO,
  30780. + udg_sysfs_template_detection_show,
  30781. + synaptics_rmi4_store_error),
  30782. + __ATTR(template_index, S_IWUSR,
  30783. + synaptics_rmi4_show_error,
  30784. + udg_sysfs_template_index_store),
  30785. + __ATTR(template_valid, (S_IRUGO | S_IWUSR),
  30786. + udg_sysfs_template_valid_show,
  30787. + udg_sysfs_template_valid_store),
  30788. + __ATTR(template_clear, S_IWUSR,
  30789. + synaptics_rmi4_show_error,
  30790. + udg_sysfs_template_clear_store),
  30791. + __ATTR(trace_size, S_IRUGO,
  30792. + udg_sysfs_trace_size_show,
  30793. + synaptics_rmi4_store_error),
  30794. +};
  30795. +
  30796. +static struct bin_attribute template_data = {
  30797. + .attr = {
  30798. + .name = "template_data",
  30799. + .mode = (S_IRUGO | S_IWUSR),
  30800. + },
  30801. + .size = 0,
  30802. + .read = udg_sysfs_template_data_show,
  30803. + .write = udg_sysfs_template_data_store,
  30804. +};
  30805. +
  30806. +static struct bin_attribute trace_data = {
  30807. + .attr = {
  30808. + .name = "trace_data",
  30809. + .mode = S_IRUGO,
  30810. + },
  30811. + .size = 0,
  30812. + .read = udg_sysfs_trace_data_show,
  30813. + .write = NULL,
  30814. +};
  30815. +
  30816. +static struct device_attribute params[] = {
  30817. + __ATTR(template_displacement, (S_IRUGO | S_IWUSR),
  30818. + udg_sysfs_template_displacement_show,
  30819. + udg_sysfs_template_displacement_store),
  30820. + __ATTR(rotation_invariance, (S_IRUGO | S_IWUSR),
  30821. + udg_sysfs_rotation_invariance_show,
  30822. + udg_sysfs_rotation_invariance_store),
  30823. + __ATTR(scale_invariance, (S_IRUGO | S_IWUSR),
  30824. + udg_sysfs_scale_invariance_show,
  30825. + udg_sysfs_scale_invariance_store),
  30826. + __ATTR(threshold_factor, (S_IRUGO | S_IWUSR),
  30827. + udg_sysfs_threshold_factor_show,
  30828. + udg_sysfs_threshold_factor_store),
  30829. + __ATTR(match_metric_threshold, (S_IRUGO | S_IWUSR),
  30830. + udg_sysfs_match_metric_threshold_show,
  30831. + udg_sysfs_match_metric_threshold_store),
  30832. + __ATTR(max_inter_stroke_time, (S_IRUGO | S_IWUSR),
  30833. + udg_sysfs_max_inter_stroke_time_show,
  30834. + udg_sysfs_max_inter_stroke_time_store),
  30835. +};
  30836. +
  30837. +static struct synaptics_rmi4_udg_handle *udg;
  30838. +
  30839. +static unsigned char ctrl_18_sub_size[] = {10, 10, 10, 2, 3, 4, 3, 3, 1, 1};
  30840. +static unsigned char ctrl_20_sub_size[] = {2};
  30841. +static unsigned char ctrl_23_sub_size[] = {1, 1, 1};
  30842. +static unsigned char ctrl_27_sub_size[] = {1, 5, 2, 1, 7};
  30843. +
  30844. +DECLARE_COMPLETION(udg_remove_complete);
  30845. +
  30846. +static ssize_t udg_sysfs_engine_enable_store(struct device *dev,
  30847. + struct device_attribute *attr, const char *buf, size_t count)
  30848. +{
  30849. + int retval;
  30850. + bool enable;
  30851. + unsigned int input;
  30852. +
  30853. + if (sscanf(buf, "%u", &input) != 1)
  30854. + return -EINVAL;
  30855. +
  30856. + if (input == 1)
  30857. + enable = true;
  30858. + else if (input == 0)
  30859. + enable = false;
  30860. + else
  30861. + return -EINVAL;
  30862. +
  30863. + retval = udg_engine_enable(enable);
  30864. + if (retval < 0)
  30865. + return retval;
  30866. +
  30867. + return count;
  30868. +}
  30869. +
  30870. +static ssize_t udg_sysfs_detection_enable_store(struct device *dev,
  30871. + struct device_attribute *attr, const char *buf, size_t count)
  30872. +{
  30873. + int retval;
  30874. + bool enable;
  30875. + unsigned int input;
  30876. +
  30877. + if (sscanf(buf, "%u", &input) != 1)
  30878. + return -EINVAL;
  30879. +
  30880. + if (input == 1)
  30881. + enable = true;
  30882. + else if (input == 0)
  30883. + enable = false;
  30884. + else
  30885. + return -EINVAL;
  30886. +
  30887. + udg->detection_status = 0;
  30888. +
  30889. + retval = udg_detection_enable(enable);
  30890. + if (retval < 0)
  30891. + return retval;
  30892. +
  30893. + return count;
  30894. +}
  30895. +
  30896. +static ssize_t udg_sysfs_detection_score_show(struct device *dev,
  30897. + struct device_attribute *attr, char *buf)
  30898. +{
  30899. + return snprintf(buf, PAGE_SIZE, "%u\n", udg->detection_score);
  30900. +}
  30901. +
  30902. +static ssize_t udg_sysfs_detection_index_show(struct device *dev,
  30903. + struct device_attribute *attr, char *buf)
  30904. +{
  30905. + return snprintf(buf, PAGE_SIZE, "%u\n", udg->detection_index);
  30906. +}
  30907. +
  30908. +static ssize_t udg_sysfs_registration_enable_store(struct device *dev,
  30909. + struct device_attribute *attr, const char *buf, size_t count)
  30910. +{
  30911. + int retval;
  30912. + bool enable;
  30913. + unsigned int input;
  30914. + struct synaptics_rmi4_f12_control_41 control_41;
  30915. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  30916. +
  30917. + if (sscanf(buf, "%u", &input) != 1)
  30918. + return -EINVAL;
  30919. +
  30920. + if (input == 1)
  30921. + enable = true;
  30922. + else if (input == 0)
  30923. + enable = false;
  30924. + else
  30925. + return -EINVAL;
  30926. +
  30927. + if (enable) {
  30928. + retval = synaptics_rmi4_reg_read(rmi4_data,
  30929. + udg->addr.ctrl_23,
  30930. + udg->ctrl_buf,
  30931. + udg->ctrl_23_sub3_off + 1);
  30932. + if (retval < 0)
  30933. + return retval;
  30934. +
  30935. + udg->ctrl_buf[0] = 0;
  30936. + udg->ctrl_buf[0] |= (1 << CTRL23_FINGER_REPORT_ENABLE_BIT);
  30937. + if (udg->ctrl_23_sub3_off)
  30938. + udg->ctrl_buf[udg->ctrl_23_sub3_off] = 0;
  30939. +
  30940. + retval = synaptics_rmi4_reg_write(rmi4_data,
  30941. + udg->addr.ctrl_23,
  30942. + udg->ctrl_buf,
  30943. + udg->ctrl_23_sub3_off + 1);
  30944. + if (retval < 0)
  30945. + return retval;
  30946. + } else {
  30947. + retval = synaptics_rmi4_reg_read(rmi4_data,
  30948. + udg->addr.ctrl_23,
  30949. + udg->ctrl_buf,
  30950. + udg->ctrl_23_sub3_off + 1);
  30951. + if (retval < 0)
  30952. + return retval;
  30953. +
  30954. + udg->ctrl_buf[0] = udg->object_type_enable1;
  30955. + if (udg->ctrl_23_sub3_off) {
  30956. + udg->ctrl_buf[udg->ctrl_23_sub3_off] =
  30957. + udg->object_type_enable2;
  30958. + }
  30959. +
  30960. + retval = synaptics_rmi4_reg_write(rmi4_data,
  30961. + udg->addr.ctrl_23,
  30962. + udg->ctrl_buf,
  30963. + udg->ctrl_23_sub3_off + 1);
  30964. + if (retval < 0)
  30965. + return retval;
  30966. + }
  30967. +
  30968. + retval = synaptics_rmi4_reg_read(rmi4_data,
  30969. + udg->addr.ctrl_41,
  30970. + control_41.data,
  30971. + sizeof(control_41.data));
  30972. + if (retval < 0)
  30973. + return retval;
  30974. +
  30975. + control_41.enable_registration = enable ? 1 : 0;
  30976. +
  30977. + retval = synaptics_rmi4_reg_write(rmi4_data,
  30978. + udg->addr.ctrl_41,
  30979. + control_41.data,
  30980. + sizeof(control_41.data));
  30981. + if (retval < 0)
  30982. + return retval;
  30983. +
  30984. + return count;
  30985. +}
  30986. +
  30987. +static ssize_t udg_sysfs_registration_begin_store(struct device *dev,
  30988. + struct device_attribute *attr, const char *buf, size_t count)
  30989. +{
  30990. + int retval;
  30991. + bool begin;
  30992. + unsigned int input;
  30993. + struct synaptics_rmi4_f12_control_41 control_41;
  30994. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  30995. +
  30996. + if (sscanf(buf, "%u", &input) != 1)
  30997. + return -EINVAL;
  30998. +
  30999. + if (input == 1)
  31000. + begin = true;
  31001. + else if (input == 0)
  31002. + begin = false;
  31003. + else
  31004. + return -EINVAL;
  31005. +
  31006. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31007. + udg->addr.ctrl_41,
  31008. + control_41.data,
  31009. + sizeof(control_41.data));
  31010. + if (retval < 0)
  31011. + return retval;
  31012. +
  31013. + control_41.begin = begin ? 1 : 0;
  31014. +
  31015. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31016. + udg->addr.ctrl_41,
  31017. + control_41.data,
  31018. + sizeof(control_41.data));
  31019. + if (retval < 0)
  31020. + return retval;
  31021. +
  31022. + return count;
  31023. +}
  31024. +
  31025. +static ssize_t udg_sysfs_registration_status_show(struct device *dev,
  31026. + struct device_attribute *attr, char *buf)
  31027. +{
  31028. + return snprintf(buf, PAGE_SIZE, "0x%02x\n", udg->registration_status);
  31029. +}
  31030. +
  31031. +static ssize_t udg_sysfs_template_size_show(struct device *dev,
  31032. + struct device_attribute *attr, char *buf)
  31033. +{
  31034. + return snprintf(buf, PAGE_SIZE, "%u\n", udg->template_size);
  31035. +}
  31036. +
  31037. +static ssize_t udg_sysfs_template_max_index_show(struct device *dev,
  31038. + struct device_attribute *attr, char *buf)
  31039. +{
  31040. + return snprintf(buf, PAGE_SIZE, "%u\n", udg->max_num_templates - 1);
  31041. +}
  31042. +
  31043. +static ssize_t udg_sysfs_template_detection_show(struct device *dev,
  31044. + struct device_attribute *attr, char *buf)
  31045. +{
  31046. + int retval;
  31047. + int attn_event;
  31048. + unsigned char detection_status;
  31049. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31050. +
  31051. + attn_event = atomic_read(&udg->attn_event);
  31052. + atomic_set(&udg->attn_event, 0);
  31053. +
  31054. + if (attn_event == 0)
  31055. + return snprintf(buf, PAGE_SIZE, "0\n");
  31056. +
  31057. + if (udg->detection_status == 0) {
  31058. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31059. + udg->addr.data_4,
  31060. + rmi4_data->gesture_detection,
  31061. + sizeof(rmi4_data->gesture_detection));
  31062. + if (retval < 0)
  31063. + return retval;
  31064. +
  31065. + udg->detection_status = rmi4_data->gesture_detection[0];
  31066. + }
  31067. +
  31068. + detection_status = udg->detection_status;
  31069. + udg->detection_status = 0;
  31070. +
  31071. + switch (detection_status) {
  31072. + case DETECTION:
  31073. + udg->detection_score = rmi4_data->gesture_detection[1];
  31074. + udg->detection_index = rmi4_data->gesture_detection[4];
  31075. + udg->trace_size = rmi4_data->gesture_detection[3];
  31076. + break;
  31077. + case REGISTRATION:
  31078. + udg->registration_status = rmi4_data->gesture_detection[1];
  31079. + udg->trace_size = rmi4_data->gesture_detection[3];
  31080. + break;
  31081. + default:
  31082. + return snprintf(buf, PAGE_SIZE, "0\n");
  31083. + }
  31084. +
  31085. + return snprintf(buf, PAGE_SIZE, "0x%02x\n", detection_status);
  31086. +}
  31087. +
  31088. +static ssize_t udg_sysfs_template_index_store(struct device *dev,
  31089. + struct device_attribute *attr, const char *buf, size_t count)
  31090. +{
  31091. + int retval;
  31092. + unsigned long index;
  31093. +
  31094. + retval = sstrtoul(buf, 10, &index);
  31095. + if (retval)
  31096. + return retval;
  31097. +
  31098. + retval = udg_set_index((unsigned char)index);
  31099. + if (retval < 0)
  31100. + return retval;
  31101. +
  31102. + return count;
  31103. +}
  31104. +
  31105. +static ssize_t udg_sysfs_template_valid_show(struct device *dev,
  31106. + struct device_attribute *attr, char *buf)
  31107. +{
  31108. + int retval;
  31109. + unsigned char valid;
  31110. + unsigned char offset;
  31111. + unsigned char byte_num;
  31112. + unsigned char template_flags[2];
  31113. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31114. +
  31115. + byte_num = udg->template_index / 8;
  31116. + offset = udg->template_index % 8;
  31117. +
  31118. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31119. + udg->addr.template_flags,
  31120. + template_flags,
  31121. + sizeof(template_flags));
  31122. + if (retval < 0)
  31123. + return retval;
  31124. +
  31125. + valid = (template_flags[byte_num] & (1 << offset)) >> offset;
  31126. +
  31127. + return snprintf(buf, PAGE_SIZE, "%u\n", valid);
  31128. +}
  31129. +
  31130. +static ssize_t udg_sysfs_template_valid_store(struct device *dev,
  31131. + struct device_attribute *attr, const char *buf, size_t count)
  31132. +{
  31133. + int retval;
  31134. + unsigned long valid;
  31135. + unsigned char offset;
  31136. + unsigned char byte_num;
  31137. + unsigned char template_flags[2];
  31138. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31139. +
  31140. + retval = sstrtoul(buf, 10, &valid);
  31141. + if (retval)
  31142. + return retval;
  31143. +
  31144. + if (valid > 0)
  31145. + valid = 1;
  31146. +
  31147. + byte_num = udg->template_index / 8;
  31148. + offset = udg->template_index % 8;
  31149. +
  31150. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31151. + udg->addr.template_flags,
  31152. + template_flags,
  31153. + sizeof(template_flags));
  31154. + if (retval < 0)
  31155. + return retval;
  31156. +
  31157. + if (valid)
  31158. + template_flags[byte_num] |= (1 << offset);
  31159. + else
  31160. + template_flags[byte_num] &= ~(1 << offset);
  31161. +
  31162. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31163. + udg->addr.template_flags,
  31164. + template_flags,
  31165. + sizeof(template_flags));
  31166. + if (retval < 0)
  31167. + return retval;
  31168. +
  31169. +#ifdef STORE_GESTURES
  31170. + udg_read_valid_data();
  31171. +#endif
  31172. +
  31173. + return count;
  31174. +}
  31175. +
  31176. +static ssize_t udg_sysfs_template_clear_store(struct device *dev,
  31177. + struct device_attribute *attr, const char *buf, size_t count)
  31178. +{
  31179. + int retval;
  31180. + unsigned int input;
  31181. + const char cmd[] = {'0', 0};
  31182. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31183. +
  31184. + if (sscanf(buf, "%u", &input) != 1)
  31185. + return -EINVAL;
  31186. +
  31187. + if (input != 1)
  31188. + return -EINVAL;
  31189. +
  31190. + memset(udg->template_data_buf, 0x00, udg->template_data_size);
  31191. +
  31192. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31193. + udg->addr.template_data,
  31194. + udg->template_data_buf,
  31195. + udg->template_data_size);
  31196. + if (retval < 0) {
  31197. + dev_err(rmi4_data->pdev->dev.parent,
  31198. + "%s: Failed to clear template data\n",
  31199. + __func__);
  31200. + return retval;
  31201. + }
  31202. +
  31203. + retval = udg_sysfs_template_valid_store(dev, attr, cmd, 1);
  31204. + if (retval < 0) {
  31205. + dev_err(rmi4_data->pdev->dev.parent,
  31206. + "%s: Failed to clear valid bit\n",
  31207. + __func__);
  31208. + return retval;
  31209. + }
  31210. +
  31211. +#ifdef STORE_GESTURES
  31212. + udg_read_template_data(udg->template_index);
  31213. + udg_read_valid_data();
  31214. +#endif
  31215. +
  31216. + return count;
  31217. +}
  31218. +
  31219. +static ssize_t udg_sysfs_trace_size_show(struct device *dev,
  31220. + struct device_attribute *attr, char *buf)
  31221. +{
  31222. + return snprintf(buf, PAGE_SIZE, "%u\n", udg->trace_size);
  31223. +}
  31224. +
  31225. +static ssize_t udg_sysfs_trace_data_show(struct file *data_file,
  31226. + struct kobject *kobj, struct bin_attribute *attributes,
  31227. + char *buf, loff_t pos, size_t count)
  31228. +{
  31229. + int retval;
  31230. + unsigned short index = 0;
  31231. + unsigned short trace_data_size;
  31232. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31233. +
  31234. + trace_data_size = udg->trace_size * 5;
  31235. +
  31236. + if (trace_data_size == 0)
  31237. + return -EINVAL;
  31238. +
  31239. + if (count < trace_data_size) {
  31240. +// dev_err(rmi4_data->pdev->dev.parent,
  31241. +// "%s: Not enough space (%d bytes) in buffer\n",
  31242. +// __func__, count);
  31243. + return -EINVAL;
  31244. + }
  31245. +
  31246. + if (udg->trace_data_buf_size < trace_data_size) {
  31247. + if (udg->trace_data_buf_size)
  31248. + kfree(udg->trace_data_buf);
  31249. + udg->trace_data_buf = kzalloc(trace_data_size, GFP_KERNEL);
  31250. + if (!udg->trace_data_buf) {
  31251. + dev_err(rmi4_data->pdev->dev.parent,
  31252. + "%s: Failed to alloc mem for trace data buffer\n",
  31253. + __func__);
  31254. + udg->trace_data_buf_size = 0;
  31255. + return -ENOMEM;
  31256. + }
  31257. + udg->trace_data_buf_size = trace_data_size;
  31258. + }
  31259. +
  31260. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31261. + udg->addr.trace_x,
  31262. + &udg->trace_data_buf[index],
  31263. + udg->trace_size * 2);
  31264. + if (retval < 0) {
  31265. + dev_err(rmi4_data->pdev->dev.parent,
  31266. + "%s: Failed to read trace X data\n",
  31267. + __func__);
  31268. + return retval;
  31269. + } else {
  31270. + index += udg->trace_size * 2;
  31271. + }
  31272. +
  31273. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31274. + udg->addr.trace_y,
  31275. + &udg->trace_data_buf[index],
  31276. + udg->trace_size * 2);
  31277. + if (retval < 0) {
  31278. + dev_err(rmi4_data->pdev->dev.parent,
  31279. + "%s: Failed to read trace Y data\n",
  31280. + __func__);
  31281. + return retval;
  31282. + } else {
  31283. + index += udg->trace_size * 2;
  31284. + }
  31285. +
  31286. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31287. + udg->addr.trace_segment,
  31288. + &udg->trace_data_buf[index],
  31289. + udg->trace_size);
  31290. + if (retval < 0) {
  31291. + dev_err(rmi4_data->pdev->dev.parent,
  31292. + "%s: Failed to read trace segment data\n",
  31293. + __func__);
  31294. + return retval;
  31295. + }
  31296. +
  31297. + retval = secure_memcpy(buf, count, udg->trace_data_buf,
  31298. + udg->trace_data_buf_size, trace_data_size);
  31299. + if (retval < 0) {
  31300. + dev_err(rmi4_data->pdev->dev.parent,
  31301. + "%s: Failed to copy trace data\n",
  31302. + __func__);
  31303. + return retval;
  31304. + }
  31305. +
  31306. + return trace_data_size;
  31307. +}
  31308. +
  31309. +static ssize_t udg_sysfs_template_data_show(struct file *data_file,
  31310. + struct kobject *kobj, struct bin_attribute *attributes,
  31311. + char *buf, loff_t pos, size_t count)
  31312. +{
  31313. + int retval;
  31314. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31315. +
  31316. + if (count < udg->template_data_size) {
  31317. +// dev_err(rmi4_data->pdev->dev.parent,
  31318. +// "%s: Not enough space (%d bytes) in buffer\n",
  31319. +// __func__, count);
  31320. + return -EINVAL;
  31321. + }
  31322. +
  31323. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31324. + udg->addr.template_data,
  31325. + udg->template_data_buf,
  31326. + udg->template_data_size);
  31327. + if (retval < 0) {
  31328. + dev_err(rmi4_data->pdev->dev.parent,
  31329. + "%s: Failed to read template data\n",
  31330. + __func__);
  31331. + return retval;
  31332. + }
  31333. +
  31334. + retval = secure_memcpy(buf, count, udg->template_data_buf,
  31335. + udg->template_data_size, udg->template_data_size);
  31336. + if (retval < 0) {
  31337. + dev_err(rmi4_data->pdev->dev.parent,
  31338. + "%s: Failed to copy template data\n",
  31339. + __func__);
  31340. + return retval;
  31341. + }
  31342. +
  31343. +#ifdef STORE_GESTURES
  31344. + udg_read_template_data(udg->template_index);
  31345. + udg_read_valid_data();
  31346. +#endif
  31347. +
  31348. + return udg->template_data_size;
  31349. +}
  31350. +
  31351. +static ssize_t udg_sysfs_template_data_store(struct file *data_file,
  31352. + struct kobject *kobj, struct bin_attribute *attributes,
  31353. + char *buf, loff_t pos, size_t count)
  31354. +{
  31355. + int retval;
  31356. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31357. +
  31358. + retval = secure_memcpy(udg->template_data_buf, udg->template_data_size,
  31359. + buf, count, count);
  31360. + if (retval < 0) {
  31361. + dev_err(rmi4_data->pdev->dev.parent,
  31362. + "%s: Failed to copy template data\n",
  31363. + __func__);
  31364. + return retval;
  31365. + }
  31366. +
  31367. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31368. + udg->addr.template_data,
  31369. + udg->template_data_buf,
  31370. + count);
  31371. + if (retval < 0) {
  31372. + dev_err(rmi4_data->pdev->dev.parent,
  31373. + "%s: Failed to write template data\n",
  31374. + __func__);
  31375. + return retval;
  31376. + }
  31377. +
  31378. +#ifdef STORE_GESTURES
  31379. + udg_read_template_data(udg->template_index);
  31380. + udg_read_valid_data();
  31381. +#endif
  31382. +
  31383. + return count;
  31384. +}
  31385. +
  31386. +static ssize_t udg_sysfs_template_displacement_show(struct device *dev,
  31387. + struct device_attribute *attr, char *buf)
  31388. +{
  31389. + int retval;
  31390. + unsigned short template_displacement;
  31391. +
  31392. + retval = udg_read_tuning_params();
  31393. + if (retval < 0)
  31394. + return retval;
  31395. +
  31396. + template_displacement =
  31397. + ((unsigned short)udg->tuning.template_disp_lsb << 0) |
  31398. + ((unsigned short)udg->tuning.template_disp_msb << 8);
  31399. +
  31400. + return snprintf(buf, PAGE_SIZE, "%u\n", template_displacement);
  31401. +}
  31402. +
  31403. +static ssize_t udg_sysfs_template_displacement_store(struct device *dev,
  31404. + struct device_attribute *attr, const char *buf, size_t count)
  31405. +{
  31406. + int retval;
  31407. + unsigned long input;
  31408. +
  31409. + retval = sstrtoul(buf, 10, &input);
  31410. + if (retval)
  31411. + return retval;
  31412. +
  31413. + retval = udg_read_tuning_params();
  31414. + if (retval < 0)
  31415. + return retval;
  31416. +
  31417. + udg->tuning.template_disp_lsb = (unsigned char)(input >> 0);
  31418. + udg->tuning.template_disp_msb = (unsigned char)(input >> 8);
  31419. +
  31420. + retval = udg_write_tuning_params();
  31421. + if (retval < 0)
  31422. + return retval;
  31423. +
  31424. + return count;
  31425. +}
  31426. +
  31427. +static ssize_t udg_sysfs_rotation_invariance_show(struct device *dev,
  31428. + struct device_attribute *attr, char *buf)
  31429. +{
  31430. + int retval;
  31431. + unsigned short rotation_invariance;
  31432. +
  31433. + retval = udg_read_tuning_params();
  31434. + if (retval < 0)
  31435. + return retval;
  31436. +
  31437. + rotation_invariance =
  31438. + ((unsigned short)udg->tuning.rotation_inv_lsb << 0) |
  31439. + ((unsigned short)udg->tuning.rotation_inv_msb << 8);
  31440. +
  31441. + return snprintf(buf, PAGE_SIZE, "%u\n", rotation_invariance);
  31442. +}
  31443. +
  31444. +static ssize_t udg_sysfs_rotation_invariance_store(struct device *dev,
  31445. + struct device_attribute *attr, const char *buf, size_t count)
  31446. +{
  31447. + int retval;
  31448. + unsigned long input;
  31449. +
  31450. + retval = sstrtoul(buf, 10, &input);
  31451. + if (retval)
  31452. + return retval;
  31453. +
  31454. + retval = udg_read_tuning_params();
  31455. + if (retval < 0)
  31456. + return retval;
  31457. +
  31458. + udg->tuning.rotation_inv_lsb = (unsigned char)(input >> 0);
  31459. + udg->tuning.rotation_inv_msb = (unsigned char)(input >> 8);
  31460. +
  31461. + retval = udg_write_tuning_params();
  31462. + if (retval < 0)
  31463. + return retval;
  31464. +
  31465. + return count;
  31466. +}
  31467. +
  31468. +static ssize_t udg_sysfs_scale_invariance_show(struct device *dev,
  31469. + struct device_attribute *attr, char *buf)
  31470. +{
  31471. + int retval;
  31472. + unsigned short scale_invariance;
  31473. +
  31474. + retval = udg_read_tuning_params();
  31475. + if (retval < 0)
  31476. + return retval;
  31477. +
  31478. + scale_invariance =
  31479. + ((unsigned short)udg->tuning.scale_inv_lsb << 0) |
  31480. + ((unsigned short)udg->tuning.scale_inv_msb << 8);
  31481. +
  31482. + return snprintf(buf, PAGE_SIZE, "%u\n", scale_invariance);
  31483. +}
  31484. +
  31485. +static ssize_t udg_sysfs_scale_invariance_store(struct device *dev,
  31486. + struct device_attribute *attr, const char *buf, size_t count)
  31487. +{
  31488. + int retval;
  31489. + unsigned long input;
  31490. +
  31491. + retval = sstrtoul(buf, 10, &input);
  31492. + if (retval)
  31493. + return retval;
  31494. +
  31495. + retval = udg_read_tuning_params();
  31496. + if (retval < 0)
  31497. + return retval;
  31498. +
  31499. + udg->tuning.scale_inv_lsb = (unsigned char)(input >> 0);
  31500. + udg->tuning.scale_inv_msb = (unsigned char)(input >> 8);
  31501. +
  31502. + retval = udg_write_tuning_params();
  31503. + if (retval < 0)
  31504. + return retval;
  31505. +
  31506. + return count;
  31507. +}
  31508. +
  31509. +static ssize_t udg_sysfs_threshold_factor_show(struct device *dev,
  31510. + struct device_attribute *attr, char *buf)
  31511. +{
  31512. + int retval;
  31513. + unsigned short threshold_factor;
  31514. +
  31515. + retval = udg_read_tuning_params();
  31516. + if (retval < 0)
  31517. + return retval;
  31518. +
  31519. + threshold_factor =
  31520. + ((unsigned short)udg->tuning.thres_factor_lsb << 0) |
  31521. + ((unsigned short)udg->tuning.thres_factor_msb << 8);
  31522. +
  31523. + return snprintf(buf, PAGE_SIZE, "%u\n", threshold_factor);
  31524. +}
  31525. +
  31526. +static ssize_t udg_sysfs_threshold_factor_store(struct device *dev,
  31527. + struct device_attribute *attr, const char *buf, size_t count)
  31528. +{
  31529. + int retval;
  31530. + unsigned long input;
  31531. +
  31532. + retval = sstrtoul(buf, 10, &input);
  31533. + if (retval)
  31534. + return retval;
  31535. +
  31536. + retval = udg_read_tuning_params();
  31537. + if (retval < 0)
  31538. + return retval;
  31539. +
  31540. + udg->tuning.thres_factor_lsb = (unsigned char)(input >> 0);
  31541. + udg->tuning.thres_factor_msb = (unsigned char)(input >> 8);
  31542. +
  31543. + retval = udg_write_tuning_params();
  31544. + if (retval < 0)
  31545. + return retval;
  31546. +
  31547. + return count;
  31548. +}
  31549. +
  31550. +static ssize_t udg_sysfs_match_metric_threshold_show(struct device *dev,
  31551. + struct device_attribute *attr, char *buf)
  31552. +{
  31553. + int retval;
  31554. + unsigned short match_metric_threshold;
  31555. +
  31556. + retval = udg_read_tuning_params();
  31557. + if (retval < 0)
  31558. + return retval;
  31559. +
  31560. + match_metric_threshold =
  31561. + ((unsigned short)udg->tuning.metric_thres_lsb << 0) |
  31562. + ((unsigned short)udg->tuning.metric_thres_msb << 8);
  31563. +
  31564. + return snprintf(buf, PAGE_SIZE, "%u\n", match_metric_threshold);
  31565. +}
  31566. +
  31567. +static ssize_t udg_sysfs_match_metric_threshold_store(struct device *dev,
  31568. + struct device_attribute *attr, const char *buf, size_t count)
  31569. +{
  31570. + int retval;
  31571. + unsigned long input;
  31572. +
  31573. + retval = sstrtoul(buf, 10, &input);
  31574. + if (retval)
  31575. + return retval;
  31576. +
  31577. + retval = udg_read_tuning_params();
  31578. + if (retval < 0)
  31579. + return retval;
  31580. +
  31581. + udg->tuning.metric_thres_lsb = (unsigned char)(input >> 0);
  31582. + udg->tuning.metric_thres_msb = (unsigned char)(input >> 8);
  31583. +
  31584. + retval = udg_write_tuning_params();
  31585. + if (retval < 0)
  31586. + return retval;
  31587. +
  31588. + return count;
  31589. +}
  31590. +
  31591. +static ssize_t udg_sysfs_max_inter_stroke_time_show(struct device *dev,
  31592. + struct device_attribute *attr, char *buf)
  31593. +{
  31594. + int retval;
  31595. + unsigned short max_inter_stroke_time;
  31596. +
  31597. + retval = udg_read_tuning_params();
  31598. + if (retval < 0)
  31599. + return retval;
  31600. +
  31601. + max_inter_stroke_time =
  31602. + ((unsigned short)udg->tuning.inter_stroke_lsb << 0) |
  31603. + ((unsigned short)udg->tuning.inter_stroke_msb << 8);
  31604. +
  31605. + return snprintf(buf, PAGE_SIZE, "%u\n", max_inter_stroke_time);
  31606. +}
  31607. +
  31608. +static ssize_t udg_sysfs_max_inter_stroke_time_store(struct device *dev,
  31609. + struct device_attribute *attr, const char *buf, size_t count)
  31610. +{
  31611. + int retval;
  31612. + unsigned long input;
  31613. +
  31614. + retval = sstrtoul(buf, 10, &input);
  31615. + if (retval)
  31616. + return retval;
  31617. +
  31618. + retval = udg_read_tuning_params();
  31619. + if (retval < 0)
  31620. + return retval;
  31621. +
  31622. + udg->tuning.inter_stroke_lsb = (unsigned char)(input >> 0);
  31623. + udg->tuning.inter_stroke_msb = (unsigned char)(input >> 8);
  31624. +
  31625. + retval = udg_write_tuning_params();
  31626. + if (retval < 0)
  31627. + return retval;
  31628. +
  31629. + return count;
  31630. +}
  31631. +
  31632. +static int udg_ctrl_subpacket(unsigned char ctrlreg,
  31633. + unsigned char subpacket,
  31634. + struct synaptics_rmi4_f12_query_5 *query_5)
  31635. +{
  31636. + int retval;
  31637. + unsigned char cnt;
  31638. + unsigned char regnum;
  31639. + unsigned char bitnum;
  31640. + unsigned char q5_index;
  31641. + unsigned char q6_index;
  31642. + unsigned char offset;
  31643. + unsigned char max_ctrlreg;
  31644. + unsigned char *query_6;
  31645. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31646. +
  31647. + max_ctrlreg = (sizeof(query_5->data) - 1) * 8 - 1;
  31648. +
  31649. + if (ctrlreg > max_ctrlreg) {
  31650. + dev_err(rmi4_data->pdev->dev.parent,
  31651. + "%s: Control register number (%d) over limit\n",
  31652. + __func__, ctrlreg);
  31653. + return -EINVAL;
  31654. + }
  31655. +
  31656. + q5_index = ctrlreg / 8 + 1;
  31657. + bitnum = ctrlreg % 8;
  31658. + if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00) {
  31659. + dev_err(rmi4_data->pdev->dev.parent,
  31660. + "%s: Control %d is not present\n",
  31661. + __func__, ctrlreg);
  31662. + return -EINVAL;
  31663. + }
  31664. +
  31665. + query_6 = kmalloc(query_5->size_of_query6, GFP_KERNEL);
  31666. + if (!query_6) {
  31667. + dev_err(rmi4_data->pdev->dev.parent,
  31668. + "%s: Failed to alloc mem for query 6\n",
  31669. + __func__);
  31670. + return -ENOMEM;
  31671. + }
  31672. +
  31673. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31674. + udg->query_base_addr + 6,
  31675. + query_6,
  31676. + query_5->size_of_query6);
  31677. + if (retval < 0)
  31678. + goto exit;
  31679. +
  31680. + q6_index = 0;
  31681. +
  31682. + for (regnum = 0; regnum < ctrlreg; regnum++) {
  31683. + q5_index = regnum / 8 + 1;
  31684. + bitnum = regnum % 8;
  31685. + if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00)
  31686. + continue;
  31687. +
  31688. + if (query_6[q6_index] == 0x00)
  31689. + q6_index += 3;
  31690. + else
  31691. + q6_index++;
  31692. +
  31693. + while (query_6[q6_index] & ~MASK_7BIT)
  31694. + q6_index++;
  31695. +
  31696. + q6_index++;
  31697. + }
  31698. +
  31699. + cnt = 0;
  31700. + q6_index++;
  31701. + offset = subpacket / 7;
  31702. + bitnum = subpacket % 7;
  31703. +
  31704. + do {
  31705. + if (cnt == offset) {
  31706. + if (query_6[q6_index + cnt] & (1 << bitnum))
  31707. + retval = 1;
  31708. + else
  31709. + retval = 0;
  31710. + goto exit;
  31711. + }
  31712. + cnt++;
  31713. + } while (query_6[q6_index + cnt - 1] & ~MASK_7BIT);
  31714. +
  31715. + retval = 0;
  31716. +
  31717. +exit:
  31718. + kfree(query_6);
  31719. +
  31720. + return retval;
  31721. +}
  31722. +
  31723. +static int udg_read_tuning_params(void)
  31724. +{
  31725. + int retval;
  31726. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31727. +
  31728. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31729. + udg->addr.ctrl_18,
  31730. + udg->ctrl_buf,
  31731. + udg->ctrl_18_sub10_off + sizeof(struct udg_tuning));
  31732. + if (retval < 0)
  31733. + return retval;
  31734. +
  31735. + secure_memcpy(udg->tuning.data,
  31736. + sizeof(udg->tuning.data),
  31737. + (unsigned char *)&udg->ctrl_buf[udg->ctrl_18_sub10_off],
  31738. + sizeof(struct udg_tuning),
  31739. + sizeof(struct udg_tuning));
  31740. +
  31741. + return 0;
  31742. +}
  31743. +
  31744. +static int udg_write_tuning_params(void)
  31745. +{
  31746. + int retval;
  31747. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31748. +
  31749. + secure_memcpy((unsigned char *)&udg->ctrl_buf[udg->ctrl_18_sub10_off],
  31750. + sizeof(struct udg_tuning),
  31751. + udg->tuning.data,
  31752. + sizeof(udg->tuning.data),
  31753. + sizeof(struct udg_tuning));
  31754. +
  31755. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31756. + udg->addr.ctrl_18,
  31757. + udg->ctrl_buf,
  31758. + udg->ctrl_18_sub10_off + sizeof(struct udg_tuning));
  31759. + if (retval < 0)
  31760. + return retval;
  31761. +
  31762. + return 0;
  31763. +}
  31764. +
  31765. +static int udg_detection_enable(bool enable)
  31766. +{
  31767. + int retval;
  31768. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31769. +
  31770. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31771. + udg->addr.ctrl_20,
  31772. + udg->ctrl_buf,
  31773. + udg->ctrl_20_sub1_off + 1);
  31774. + if (retval < 0)
  31775. + return retval;
  31776. +
  31777. + if (enable)
  31778. + udg->ctrl_buf[udg->ctrl_20_sub1_off] = WAKEUP_GESTURE_MODE;
  31779. + else
  31780. + udg->ctrl_buf[udg->ctrl_20_sub1_off] = udg->report_flags;
  31781. +
  31782. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31783. + udg->addr.ctrl_20,
  31784. + udg->ctrl_buf,
  31785. + udg->ctrl_20_sub1_off + 1);
  31786. + if (retval < 0)
  31787. + return retval;
  31788. +
  31789. + return 0;
  31790. +}
  31791. +
  31792. +static int udg_engine_enable(bool enable)
  31793. +{
  31794. + int retval;
  31795. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31796. +
  31797. + if (enable) {
  31798. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31799. + udg->addr.ctrl_27,
  31800. + udg->ctrl_buf,
  31801. + udg->ctrl_27_sub5_off + 1);
  31802. + if (retval < 0)
  31803. + return retval;
  31804. +
  31805. + udg->ctrl_buf[udg->ctrl_27_sub5_off] |=
  31806. + (1 << CTRL27_UDG_ENABLE_BIT);
  31807. +
  31808. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31809. + udg->addr.ctrl_27,
  31810. + udg->ctrl_buf,
  31811. + udg->ctrl_27_sub5_off + 1);
  31812. + if (retval < 0)
  31813. + return retval;
  31814. + } else {
  31815. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31816. + udg->addr.ctrl_27,
  31817. + udg->ctrl_buf,
  31818. + udg->ctrl_27_sub5_off + 1);
  31819. + if (retval < 0)
  31820. + return retval;
  31821. +
  31822. + udg->ctrl_buf[udg->ctrl_27_sub5_off] &=
  31823. + ~(1 << CTRL27_UDG_ENABLE_BIT);
  31824. +
  31825. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31826. + udg->addr.ctrl_27,
  31827. + udg->ctrl_buf,
  31828. + udg->ctrl_27_sub5_off + 1);
  31829. + if (retval < 0)
  31830. + return retval;
  31831. + }
  31832. +
  31833. + return 0;
  31834. +}
  31835. +
  31836. +static void udg_report(void)
  31837. +{
  31838. + int retval;
  31839. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31840. +
  31841. + atomic_set(&udg->attn_event, 1);
  31842. +
  31843. + if (rmi4_data->suspend) {
  31844. + if (rmi4_data->gesture_detection[0] == 0) {
  31845. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31846. + udg->addr.data_4,
  31847. + rmi4_data->gesture_detection,
  31848. + sizeof(rmi4_data->gesture_detection));
  31849. + if (retval < 0) {
  31850. + dev_err(rmi4_data->pdev->dev.parent,
  31851. + "%s: Failed to read gesture detection\n",
  31852. + __func__);
  31853. + return;
  31854. + }
  31855. + }
  31856. +
  31857. + udg->detection_status = rmi4_data->gesture_detection[0];
  31858. + rmi4_data->gesture_detection[0] = 0;
  31859. +
  31860. + if (udg->detection_status == DETECTION) {
  31861. + input_report_key(udg->udg_dev, KEY_WAKEUP, 1);
  31862. + input_sync(udg->udg_dev);
  31863. + input_report_key(udg->udg_dev, KEY_WAKEUP, 0);
  31864. + input_sync(udg->udg_dev);
  31865. + rmi4_data->suspend = false;
  31866. + }
  31867. + }
  31868. +
  31869. + return;
  31870. +}
  31871. +
  31872. +static int udg_set_index(unsigned char index)
  31873. +{
  31874. + int retval;
  31875. + struct synaptics_rmi4_f12_control_41 control_41;
  31876. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31877. +
  31878. + if (index >= udg->max_num_templates)
  31879. + return -EINVAL;
  31880. +
  31881. + udg->template_index = index;
  31882. +
  31883. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31884. + udg->addr.ctrl_41,
  31885. + control_41.data,
  31886. + sizeof(control_41.data));
  31887. + if (retval < 0)
  31888. + return retval;
  31889. +
  31890. + control_41.template_index = udg->template_index;
  31891. +
  31892. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31893. + udg->addr.ctrl_41,
  31894. + control_41.data,
  31895. + sizeof(control_41.data));
  31896. + if (retval < 0)
  31897. + return retval;
  31898. +
  31899. + return 0;
  31900. +}
  31901. +
  31902. +#ifdef STORE_GESTURES
  31903. +static int udg_read_valid_data(void)
  31904. +{
  31905. + int retval;
  31906. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31907. +
  31908. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31909. + udg->addr.template_flags,
  31910. + udg->valid_buf,
  31911. + sizeof(udg->valid_buf));
  31912. + if (retval < 0)
  31913. + return retval;
  31914. +
  31915. + return 0;
  31916. +}
  31917. +
  31918. +static int udg_write_valid_data(void)
  31919. +{
  31920. + int retval;
  31921. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31922. +
  31923. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31924. + udg->addr.template_flags,
  31925. + udg->valid_buf,
  31926. + sizeof(udg->valid_buf));
  31927. + if (retval < 0)
  31928. + return retval;
  31929. +
  31930. + return 0;
  31931. +}
  31932. +
  31933. +static int udg_read_template_data(unsigned char index)
  31934. +{
  31935. + int retval;
  31936. + unsigned char *storage;
  31937. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31938. +
  31939. + udg_set_index(index);
  31940. + storage = &(udg->storage_buf[index * udg->template_data_size]);
  31941. +
  31942. + retval = synaptics_rmi4_reg_read(rmi4_data,
  31943. + udg->addr.template_data,
  31944. + storage,
  31945. + udg->template_data_size);
  31946. + if (retval < 0) {
  31947. + dev_err(rmi4_data->pdev->dev.parent,
  31948. + "%s: Failed to read template data\n",
  31949. + __func__);
  31950. + return retval;
  31951. + }
  31952. +
  31953. + return 0;
  31954. +}
  31955. +
  31956. +static int udg_write_template_data(void)
  31957. +{
  31958. + int retval;
  31959. + unsigned char ii;
  31960. + unsigned char *storage;
  31961. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31962. +
  31963. + for (ii = 0; ii < udg->gestures_to_store; ii++) {
  31964. + udg_set_index(ii);
  31965. + storage = &(udg->storage_buf[ii * udg->template_data_size]);
  31966. +
  31967. + retval = synaptics_rmi4_reg_write(rmi4_data,
  31968. + udg->addr.template_data,
  31969. + storage,
  31970. + udg->template_data_size);
  31971. + if (retval < 0) {
  31972. + dev_err(rmi4_data->pdev->dev.parent,
  31973. + "%s: Failed to write template data\n",
  31974. + __func__);
  31975. + return retval;
  31976. + }
  31977. + }
  31978. +
  31979. + return 0;
  31980. +}
  31981. +#endif
  31982. +
  31983. +static int udg_reg_init(void)
  31984. +{
  31985. + int retval;
  31986. + unsigned char ii;
  31987. + unsigned char data_offset;
  31988. + unsigned char size_of_query;
  31989. + unsigned char ctrl_18_offset;
  31990. + unsigned char ctrl_20_offset;
  31991. + unsigned char ctrl_23_offset;
  31992. + unsigned char ctrl_27_offset;
  31993. + unsigned char ctrl_41_offset;
  31994. + struct synaptics_rmi4_f12_query_0 query_0;
  31995. + struct synaptics_rmi4_f12_query_5 query_5;
  31996. + struct synaptics_rmi4_f12_query_8 query_8;
  31997. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  31998. +
  31999. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32000. + udg->query_base_addr + 7,
  32001. + &size_of_query,
  32002. + sizeof(size_of_query));
  32003. + if (retval < 0)
  32004. + return retval;
  32005. +
  32006. + if (size_of_query < 4) {
  32007. + dev_err(rmi4_data->pdev->dev.parent,
  32008. + "%s: User defined gesture support unavailable "
  32009. + "(missing data registers)\n",
  32010. + __func__);
  32011. + retval = -ENODEV;
  32012. + return retval;
  32013. + }
  32014. +
  32015. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32016. + udg->query_base_addr + 8,
  32017. + query_8.data,
  32018. + sizeof(query_8.data));
  32019. + if (retval < 0)
  32020. + return retval;
  32021. +
  32022. + if ((query_8.data16_is_present) &&
  32023. + (query_8.data17_is_present) &&
  32024. + (query_8.data18_is_present) &&
  32025. + (query_8.data19_is_present) &&
  32026. + (query_8.data20_is_present) &&
  32027. + (query_8.data21_is_present)) {
  32028. + data_offset = query_8.data0_is_present +
  32029. + query_8.data1_is_present +
  32030. + query_8.data2_is_present +
  32031. + query_8.data3_is_present;
  32032. + udg->addr.data_4 = udg->data_base_addr + data_offset;
  32033. + data_offset = data_offset +
  32034. + query_8.data4_is_present +
  32035. + query_8.data5_is_present +
  32036. + query_8.data6_is_present +
  32037. + query_8.data7_is_present +
  32038. + query_8.data8_is_present +
  32039. + query_8.data9_is_present +
  32040. + query_8.data10_is_present +
  32041. + query_8.data11_is_present +
  32042. + query_8.data12_is_present +
  32043. + query_8.data13_is_present +
  32044. + query_8.data14_is_present +
  32045. + query_8.data15_is_present;
  32046. + udg->addr.trace_x = udg->data_base_addr + data_offset;
  32047. + udg->addr.trace_y = udg->addr.trace_x + 1;
  32048. + udg->addr.trace_segment = udg->addr.trace_y + 1;
  32049. + udg->addr.template_helper = udg->addr.trace_segment + 1;
  32050. + udg->addr.template_data = udg->addr.template_helper + 1;
  32051. + udg->addr.template_flags = udg->addr.template_data + 1;
  32052. + } else {
  32053. + dev_err(rmi4_data->pdev->dev.parent,
  32054. + "%s: User defined gesture support unavailable "
  32055. + "(missing data registers)\n",
  32056. + __func__);
  32057. + retval = -ENODEV;
  32058. + return retval;
  32059. + }
  32060. +
  32061. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32062. + udg->query_base_addr + 4,
  32063. + &size_of_query,
  32064. + sizeof(size_of_query));
  32065. + if (retval < 0)
  32066. + return retval;
  32067. +
  32068. + if (size_of_query < 7) {
  32069. + dev_err(rmi4_data->pdev->dev.parent,
  32070. + "%s: User defined gesture support unavailable "
  32071. + "(missing control registers)\n",
  32072. + __func__);
  32073. + retval = -ENODEV;
  32074. + return retval;
  32075. + }
  32076. +
  32077. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32078. + udg->query_base_addr + 5,
  32079. + query_5.data,
  32080. + sizeof(query_5.data));
  32081. + if (retval < 0)
  32082. + return retval;
  32083. +
  32084. + ctrl_18_offset = query_5.ctrl0_is_present +
  32085. + query_5.ctrl1_is_present +
  32086. + query_5.ctrl2_is_present +
  32087. + query_5.ctrl3_is_present +
  32088. + query_5.ctrl4_is_present +
  32089. + query_5.ctrl5_is_present +
  32090. + query_5.ctrl6_is_present +
  32091. + query_5.ctrl7_is_present +
  32092. + query_5.ctrl8_is_present +
  32093. + query_5.ctrl9_is_present +
  32094. + query_5.ctrl10_is_present +
  32095. + query_5.ctrl11_is_present +
  32096. + query_5.ctrl12_is_present +
  32097. + query_5.ctrl13_is_present +
  32098. + query_5.ctrl14_is_present +
  32099. + query_5.ctrl15_is_present +
  32100. + query_5.ctrl16_is_present +
  32101. + query_5.ctrl17_is_present;
  32102. +
  32103. + ctrl_20_offset = ctrl_18_offset +
  32104. + query_5.ctrl18_is_present +
  32105. + query_5.ctrl19_is_present;
  32106. +
  32107. + ctrl_23_offset = ctrl_20_offset +
  32108. + query_5.ctrl20_is_present +
  32109. + query_5.ctrl21_is_present +
  32110. + query_5.ctrl22_is_present;
  32111. +
  32112. + ctrl_27_offset = ctrl_23_offset+
  32113. + query_5.ctrl23_is_present +
  32114. + query_5.ctrl24_is_present +
  32115. + query_5.ctrl25_is_present +
  32116. + query_5.ctrl26_is_present;
  32117. +
  32118. + ctrl_41_offset = ctrl_27_offset+
  32119. + query_5.ctrl27_is_present +
  32120. + query_5.ctrl28_is_present +
  32121. + query_5.ctrl29_is_present +
  32122. + query_5.ctrl30_is_present +
  32123. + query_5.ctrl31_is_present +
  32124. + query_5.ctrl32_is_present +
  32125. + query_5.ctrl33_is_present +
  32126. + query_5.ctrl34_is_present +
  32127. + query_5.ctrl35_is_present +
  32128. + query_5.ctrl36_is_present +
  32129. + query_5.ctrl37_is_present +
  32130. + query_5.ctrl38_is_present +
  32131. + query_5.ctrl39_is_present +
  32132. + query_5.ctrl40_is_present;
  32133. +
  32134. + udg->addr.ctrl_18 = udg->control_base_addr + ctrl_18_offset;
  32135. + udg->addr.ctrl_20 = udg->control_base_addr + ctrl_20_offset;
  32136. + udg->addr.ctrl_23 = udg->control_base_addr + ctrl_23_offset;
  32137. + udg->addr.ctrl_27 = udg->control_base_addr + ctrl_27_offset;
  32138. + udg->addr.ctrl_41 = udg->control_base_addr + ctrl_41_offset;
  32139. +
  32140. + udg->ctrl_18_sub10_off = 0;
  32141. + for (ii = 0; ii < 10; ii++) {
  32142. + retval = udg_ctrl_subpacket(18, ii, &query_5);
  32143. + if (retval == 1)
  32144. + udg->ctrl_18_sub10_off += ctrl_18_sub_size[ii];
  32145. + else if (retval < 0)
  32146. + return retval;
  32147. + }
  32148. +
  32149. + udg->ctrl_20_sub1_off = 0;
  32150. + for (ii = 0; ii < 1; ii++) {
  32151. + retval = udg_ctrl_subpacket(20, ii, &query_5);
  32152. + if (retval == 1)
  32153. + udg->ctrl_20_sub1_off += ctrl_20_sub_size[ii];
  32154. + else if (retval < 0)
  32155. + return retval;
  32156. + }
  32157. +
  32158. + udg->ctrl_23_sub3_off = 0;
  32159. + for (ii = 0; ii < 3; ii++) {
  32160. + retval = udg_ctrl_subpacket(23, ii, &query_5);
  32161. + if (retval == 1)
  32162. + udg->ctrl_23_sub3_off += ctrl_23_sub_size[ii];
  32163. + else if (retval < 0)
  32164. + return retval;
  32165. + }
  32166. +
  32167. + retval = udg_ctrl_subpacket(23, 3, &query_5);
  32168. + if (retval == 0)
  32169. + udg->ctrl_23_sub3_off = 0;
  32170. + else if (retval < 0)
  32171. + return retval;
  32172. +
  32173. + udg->ctrl_27_sub5_off = 0;
  32174. + for (ii = 0; ii < 5; ii++) {
  32175. + retval = udg_ctrl_subpacket(27, ii, &query_5);
  32176. + if (retval == 1)
  32177. + udg->ctrl_27_sub5_off += ctrl_27_sub_size[ii];
  32178. + else if (retval < 0)
  32179. + return retval;
  32180. + }
  32181. +
  32182. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32183. + udg->query_base_addr + 0,
  32184. + query_0.data,
  32185. + sizeof(query_0.data));
  32186. + if (retval < 0)
  32187. + return retval;
  32188. +
  32189. + udg->max_num_templates = query_0.max_num_templates;
  32190. + udg->template_size =
  32191. + ((unsigned short)query_0.template_size_lsb << 0) |
  32192. + ((unsigned short)query_0.template_size_msb << 8);
  32193. + udg->template_data_size = udg->template_size * 4 * 2 + 4 + 1;
  32194. +
  32195. +#ifdef STORE_GESTURES
  32196. + udg->gestures_to_store = udg->max_num_templates;
  32197. + if (GESTURES_TO_STORE < udg->gestures_to_store)
  32198. + udg->gestures_to_store = GESTURES_TO_STORE;
  32199. +#endif
  32200. +
  32201. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32202. + udg->addr.ctrl_20,
  32203. + udg->ctrl_buf,
  32204. + udg->ctrl_20_sub1_off + 1);
  32205. + if (retval < 0)
  32206. + return retval;
  32207. +
  32208. + udg->report_flags = udg->ctrl_buf[udg->ctrl_20_sub1_off];
  32209. +
  32210. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32211. + udg->addr.ctrl_23,
  32212. + udg->ctrl_buf,
  32213. + udg->ctrl_23_sub3_off + 1);
  32214. + if (retval < 0)
  32215. + return retval;
  32216. +
  32217. + udg->object_type_enable1 = udg->ctrl_buf[0];
  32218. + if (udg->ctrl_23_sub3_off)
  32219. + udg->object_type_enable2 = udg->ctrl_buf[udg->ctrl_23_sub3_off];
  32220. +
  32221. + return retval;
  32222. +}
  32223. +
  32224. +static int udg_scan_pdt(void)
  32225. +{
  32226. + int retval;
  32227. + unsigned char ii;
  32228. + unsigned char page;
  32229. + unsigned char intr_count = 0;
  32230. + unsigned char intr_off;
  32231. + unsigned char intr_src;
  32232. + unsigned short addr;
  32233. + struct synaptics_rmi4_fn_desc fd;
  32234. + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data;
  32235. +
  32236. + for (page = 0; page < PAGES_TO_SERVICE; page++) {
  32237. + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
  32238. + addr |= (page << 8);
  32239. +
  32240. + retval = synaptics_rmi4_reg_read(rmi4_data,
  32241. + addr,
  32242. + (unsigned char *)&fd,
  32243. + sizeof(fd));
  32244. + if (retval < 0)
  32245. + return retval;
  32246. +
  32247. + addr &= ~(MASK_8BIT << 8);
  32248. +
  32249. + if (fd.fn_number) {
  32250. + dev_dbg(rmi4_data->pdev->dev.parent,
  32251. + "%s: Found F%02x\n",
  32252. + __func__, fd.fn_number);
  32253. + switch (fd.fn_number) {
  32254. + case SYNAPTICS_RMI4_F12:
  32255. + goto f12_found;
  32256. + break;
  32257. + }
  32258. + } else {
  32259. + break;
  32260. + }
  32261. +
  32262. + intr_count += fd.intr_src_count;
  32263. + }
  32264. + }
  32265. +
  32266. + dev_err(rmi4_data->pdev->dev.parent,
  32267. + "%s: Failed to find F12\n",
  32268. + __func__);
  32269. + return -EINVAL;
  32270. +
  32271. +f12_found:
  32272. + udg->query_base_addr = fd.query_base_addr | (page << 8);
  32273. + udg->control_base_addr = fd.ctrl_base_addr | (page << 8);
  32274. + udg->data_base_addr = fd.data_base_addr | (page << 8);
  32275. + udg->command_base_addr = fd.cmd_base_addr | (page << 8);
  32276. +
  32277. + retval = udg_reg_init();
  32278. + if (retval < 0) {
  32279. + dev_err(rmi4_data->pdev->dev.parent,
  32280. + "%s: Failed to initialize user defined gesture registers\n",
  32281. + __func__);
  32282. + return retval;
  32283. + }
  32284. +
  32285. + udg->intr_mask = 0;
  32286. + intr_src = fd.intr_src_count;
  32287. + intr_off = intr_count % 8;
  32288. + for (ii = intr_off;
  32289. + ii < (intr_src + intr_off);
  32290. + ii++) {
  32291. + udg->intr_mask |= 1 << ii;
  32292. + }
  32293. +
  32294. + rmi4_data->intr_mask[0] |= udg->intr_mask;
  32295. +
  32296. + addr = rmi4_data->f01_ctrl_base_addr + 1;
  32297. +
  32298. + retval = synaptics_rmi4_reg_write(rmi4_data,
  32299. + addr,
  32300. + &rmi4_data->intr_mask[0],
  32301. + sizeof(rmi4_data->intr_mask[0]));
  32302. + if (retval < 0) {
  32303. + dev_err(rmi4_data->pdev->dev.parent,
  32304. + "%s: Failed to set interrupt enable bit\n",
  32305. + __func__);
  32306. + return retval;
  32307. + }
  32308. +
  32309. + return 0;
  32310. +}
  32311. +
  32312. +static void synaptics_rmi4_udg_attn(struct synaptics_rmi4_data *rmi4_data,
  32313. + unsigned char intr_mask)
  32314. +{
  32315. + if (!udg)
  32316. + return;
  32317. +
  32318. + if (udg->intr_mask & intr_mask)
  32319. + udg_report();
  32320. +
  32321. + return;
  32322. +}
  32323. +
  32324. +static int synaptics_rmi4_udg_init(struct synaptics_rmi4_data *rmi4_data)
  32325. +{
  32326. + int retval;
  32327. + unsigned char ii;
  32328. + unsigned char size;
  32329. + unsigned char attr_count;
  32330. + unsigned char param_count;
  32331. +
  32332. + if (udg) {
  32333. + dev_dbg(rmi4_data->pdev->dev.parent,
  32334. + "%s: Handle already exists\n",
  32335. + __func__);
  32336. + return 0;
  32337. + }
  32338. +
  32339. + udg = kzalloc(sizeof(*udg), GFP_KERNEL);
  32340. + if (!udg) {
  32341. + dev_err(rmi4_data->pdev->dev.parent,
  32342. + "%s: Failed to alloc mem for udg\n",
  32343. + __func__);
  32344. + retval = -ENOMEM;
  32345. + goto exit;
  32346. + }
  32347. +
  32348. + size = 0;
  32349. + for (ii = 0; ii < sizeof(ctrl_18_sub_size); ii++)
  32350. + size += ctrl_18_sub_size[ii];
  32351. + size += sizeof(struct udg_tuning);
  32352. + udg->ctrl_buf = kzalloc(size, GFP_KERNEL);
  32353. + if (!udg->ctrl_buf) {
  32354. + dev_err(rmi4_data->pdev->dev.parent,
  32355. + "%s: Failed to alloc mem for ctrl_buf\n",
  32356. + __func__);
  32357. + retval = -ENOMEM;
  32358. + goto exit_free_udg;
  32359. + }
  32360. +
  32361. + udg->rmi4_data = rmi4_data;
  32362. +
  32363. + retval = udg_scan_pdt();
  32364. + if (retval < 0)
  32365. + goto exit_free_ctrl_buf;
  32366. +
  32367. + udg->template_data_buf = kzalloc(udg->template_data_size, GFP_KERNEL);
  32368. + if (!udg->template_data_buf) {
  32369. + dev_err(rmi4_data->pdev->dev.parent,
  32370. + "%s: Failed to alloc mem for template_data_buf\n",
  32371. + __func__);
  32372. + retval = -ENOMEM;
  32373. + goto exit_free_ctrl_buf;
  32374. + }
  32375. +
  32376. +#ifdef STORE_GESTURES
  32377. + udg->storage_buf = kzalloc(
  32378. + udg->template_data_size * udg->gestures_to_store,
  32379. + GFP_KERNEL);
  32380. + if (!udg->storage_buf) {
  32381. + dev_err(rmi4_data->pdev->dev.parent,
  32382. + "%s: Failed to alloc mem for storage_buf\n",
  32383. + __func__);
  32384. + kfree(udg->template_data_buf);
  32385. + retval = -ENOMEM;
  32386. + goto exit_free_ctrl_buf;
  32387. + }
  32388. +#endif
  32389. +
  32390. + udg->udg_dev = input_allocate_device();
  32391. + if (udg->udg_dev == NULL) {
  32392. + dev_err(rmi4_data->pdev->dev.parent,
  32393. + "%s: Failed to allocate gesture device\n",
  32394. + __func__);
  32395. + retval = -ENOMEM;
  32396. + goto exit_free_template_data_buf;
  32397. + }
  32398. +
  32399. + udg->udg_dev->name = GESTURE_DRIVER_NAME;
  32400. + udg->udg_dev->phys = GESTURE_PHYS_NAME;
  32401. + udg->udg_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
  32402. + udg->udg_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION;
  32403. + udg->udg_dev->dev.parent = rmi4_data->pdev->dev.parent;
  32404. + input_set_drvdata(udg->udg_dev, rmi4_data);
  32405. +
  32406. + set_bit(EV_KEY, udg->udg_dev->evbit);
  32407. + set_bit(KEY_WAKEUP, udg->udg_dev->keybit);
  32408. + input_set_capability(udg->udg_dev, EV_KEY, KEY_WAKEUP);
  32409. +
  32410. + retval = input_register_device(udg->udg_dev);
  32411. + if (retval) {
  32412. + dev_err(rmi4_data->pdev->dev.parent,
  32413. + "%s: Failed to register gesture device\n",
  32414. + __func__);
  32415. + input_free_device(udg->udg_dev);
  32416. + goto exit_free_template_data_buf;
  32417. + }
  32418. +
  32419. + udg->tuning_dir = kobject_create_and_add(TUNING_SYSFS_DIR_NAME,
  32420. + &udg->udg_dev->dev.kobj);
  32421. + if (!udg->tuning_dir) {
  32422. + dev_err(rmi4_data->pdev->dev.parent,
  32423. + "%s: Failed to create tuning sysfs directory\n",
  32424. + __func__);
  32425. + goto exit_unregister_input_device;
  32426. + }
  32427. +
  32428. + retval = sysfs_create_bin_file(&udg->udg_dev->dev.kobj, &template_data);
  32429. + if (retval < 0) {
  32430. + dev_err(rmi4_data->pdev->dev.parent,
  32431. + "%s: Failed to create template data bin file\n",
  32432. + __func__);
  32433. + goto exit_remove_sysfs_directory;
  32434. + }
  32435. +
  32436. + retval = sysfs_create_bin_file(&udg->udg_dev->dev.kobj, &trace_data);
  32437. + if (retval < 0) {
  32438. + dev_err(rmi4_data->pdev->dev.parent,
  32439. + "%s: Failed to create trace data bin file\n",
  32440. + __func__);
  32441. + goto exit_remove_bin_file;
  32442. + }
  32443. +
  32444. + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
  32445. + retval = sysfs_create_file(&udg->udg_dev->dev.kobj,
  32446. + &attrs[attr_count].attr);
  32447. + if (retval < 0) {
  32448. + dev_err(rmi4_data->pdev->dev.parent,
  32449. + "%s: Failed to create sysfs attributes\n",
  32450. + __func__);
  32451. + retval = -ENODEV;
  32452. + goto exit_remove_attrs;
  32453. + }
  32454. + }
  32455. +
  32456. + for (param_count = 0; param_count < ARRAY_SIZE(params); param_count++) {
  32457. + retval = sysfs_create_file(udg->tuning_dir,
  32458. + &params[param_count].attr);
  32459. + if (retval < 0) {
  32460. + dev_err(rmi4_data->pdev->dev.parent,
  32461. + "%s: Failed to create tuning parameters\n",
  32462. + __func__);
  32463. + retval = -ENODEV;
  32464. + goto exit_remove_params;
  32465. + }
  32466. + }
  32467. +
  32468. + retval = udg_engine_enable(true);
  32469. + if (retval < 0) {
  32470. + dev_err(rmi4_data->pdev->dev.parent,
  32471. + "%s: Failed to enable gesture engine\n",
  32472. + __func__);
  32473. + goto exit_remove_params;
  32474. + }
  32475. +
  32476. + return 0;
  32477. +
  32478. +exit_remove_params:
  32479. + for (param_count--; param_count >= 0; param_count--) {
  32480. + sysfs_remove_file(udg->tuning_dir,
  32481. + &params[param_count].attr);
  32482. + }
  32483. +
  32484. +exit_remove_attrs:
  32485. + for (attr_count--; attr_count >= 0; attr_count--) {
  32486. + sysfs_remove_file(&udg->udg_dev->dev.kobj,
  32487. + &attrs[attr_count].attr);
  32488. + }
  32489. +
  32490. + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &trace_data);
  32491. +
  32492. +exit_remove_bin_file:
  32493. + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &template_data);
  32494. +
  32495. +exit_remove_sysfs_directory:
  32496. + kobject_put(udg->tuning_dir);
  32497. +
  32498. +exit_unregister_input_device:
  32499. + input_unregister_device(udg->udg_dev);
  32500. +
  32501. +exit_free_template_data_buf:
  32502. +#ifdef STORE_GESTURES
  32503. + kfree(udg->storage_buf);
  32504. +#endif
  32505. + kfree(udg->template_data_buf);
  32506. +
  32507. +exit_free_ctrl_buf:
  32508. + kfree(udg->ctrl_buf);
  32509. +
  32510. +exit_free_udg:
  32511. + kfree(udg);
  32512. + udg = NULL;
  32513. +
  32514. +exit:
  32515. + return retval;
  32516. +}
  32517. +
  32518. +static void synaptics_rmi4_udg_remove(struct synaptics_rmi4_data *rmi4_data)
  32519. +{
  32520. + unsigned char count;
  32521. +
  32522. + if (!udg)
  32523. + goto exit;
  32524. +
  32525. + for (count = 0; count < ARRAY_SIZE(params); count++) {
  32526. + sysfs_remove_file(udg->tuning_dir,
  32527. + &params[count].attr);
  32528. + }
  32529. +
  32530. + for (count = 0; count < ARRAY_SIZE(attrs); count++) {
  32531. + sysfs_remove_file(&udg->udg_dev->dev.kobj,
  32532. + &attrs[count].attr);
  32533. + }
  32534. +
  32535. + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &trace_data);
  32536. + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &template_data);
  32537. + kobject_put(udg->tuning_dir);
  32538. +
  32539. + input_unregister_device(udg->udg_dev);
  32540. +#ifdef STORE_GESTURES
  32541. + kfree(udg->storage_buf);
  32542. +#endif
  32543. + kfree(udg->template_data_buf);
  32544. + kfree(udg->trace_data_buf);
  32545. + kfree(udg->ctrl_buf);
  32546. + kfree(udg);
  32547. + udg = NULL;
  32548. +
  32549. +exit:
  32550. + complete(&udg_remove_complete);
  32551. +
  32552. + return;
  32553. +}
  32554. +
  32555. +static void synaptics_rmi4_udg_reset(struct synaptics_rmi4_data *rmi4_data)
  32556. +{
  32557. + if (!udg) {
  32558. + synaptics_rmi4_udg_init(rmi4_data);
  32559. + return;
  32560. + }
  32561. +
  32562. + udg_scan_pdt();
  32563. + udg_engine_enable(true);
  32564. +#ifdef STORE_GESTURES
  32565. + udg_write_template_data();
  32566. + udg_write_valid_data();
  32567. +#endif
  32568. +
  32569. + return;
  32570. +}
  32571. +
  32572. +static void synaptics_rmi4_udg_reinit(struct synaptics_rmi4_data *rmi4_data)
  32573. +{
  32574. + if (!udg)
  32575. + return;
  32576. +
  32577. + udg_engine_enable(true);
  32578. +#ifdef STORE_GESTURES
  32579. + udg_write_template_data();
  32580. + udg_write_valid_data();
  32581. +#endif
  32582. +
  32583. + return;
  32584. +}
  32585. +
  32586. +static void synaptics_rmi4_udg_e_suspend(struct synaptics_rmi4_data *rmi4_data)
  32587. +{
  32588. + if (!udg)
  32589. + return;
  32590. +
  32591. + rmi4_data->sleep_enable(rmi4_data, false);
  32592. + rmi4_data->irq_enable(rmi4_data, true, false);
  32593. + enable_irq_wake(rmi4_data->irq);
  32594. +
  32595. + udg_engine_enable(true);
  32596. + udg_detection_enable(true);
  32597. +
  32598. + return;
  32599. +}
  32600. +
  32601. +static void synaptics_rmi4_udg_suspend(struct synaptics_rmi4_data *rmi4_data)
  32602. +{
  32603. + if (!udg)
  32604. + return;
  32605. +
  32606. + rmi4_data->sleep_enable(rmi4_data, false);
  32607. + rmi4_data->irq_enable(rmi4_data, true, false);
  32608. + enable_irq_wake(rmi4_data->irq);
  32609. +
  32610. + udg_engine_enable(true);
  32611. + udg_detection_enable(true);
  32612. +
  32613. + return;
  32614. +}
  32615. +
  32616. +static void synaptics_rmi4_udg_resume(struct synaptics_rmi4_data *rmi4_data)
  32617. +{
  32618. + if (!udg)
  32619. + return;
  32620. +
  32621. + disable_irq_wake(rmi4_data->irq);
  32622. + udg_detection_enable(false);
  32623. +
  32624. + return;
  32625. +}
  32626. +
  32627. +static void synaptics_rmi4_udg_l_resume(struct synaptics_rmi4_data *rmi4_data)
  32628. +{
  32629. + if (!udg)
  32630. + return;
  32631. +
  32632. + disable_irq_wake(rmi4_data->irq);
  32633. + udg_detection_enable(false);
  32634. +
  32635. + return;
  32636. +}
  32637. +
  32638. +static struct synaptics_rmi4_exp_fn gesture_module = {
  32639. + .fn_type = RMI_GESTURE,
  32640. + .init = synaptics_rmi4_udg_init,
  32641. + .remove = synaptics_rmi4_udg_remove,
  32642. + .reset = synaptics_rmi4_udg_reset,
  32643. + .reinit = synaptics_rmi4_udg_reinit,
  32644. + .early_suspend = synaptics_rmi4_udg_e_suspend,
  32645. + .suspend = synaptics_rmi4_udg_suspend,
  32646. + .resume = synaptics_rmi4_udg_resume,
  32647. + .late_resume = synaptics_rmi4_udg_l_resume,
  32648. + .attn = synaptics_rmi4_udg_attn,
  32649. +};
  32650. +
  32651. +static int __init rmi4_gesture_module_init(void)
  32652. +{
  32653. + synaptics_rmi4_new_function_force(&gesture_module, true);
  32654. +
  32655. + return 0;
  32656. +}
  32657. +
  32658. +static void __exit rmi4_gesture_module_exit(void)
  32659. +{
  32660. + synaptics_rmi4_new_function_force(&gesture_module, false);
  32661. +
  32662. + wait_for_completion(&udg_remove_complete);
  32663. +
  32664. + return;
  32665. +}
  32666. +
  32667. +module_init(rmi4_gesture_module_init);
  32668. +module_exit(rmi4_gesture_module_exit);
  32669. +
  32670. +MODULE_AUTHOR("Synaptics, Inc.");
  32671. +MODULE_DESCRIPTION("Synaptics DSX User Defined Gesture Module");
  32672. +MODULE_LICENSE("GPL v2");
  32673. diff --git a/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_i2c.c
  32674. new file mode 100644
  32675. index 0000000..ca13bdf
  32676. --- /dev/null
  32677. +++ b/drivers/input/touchscreen/synaptics_dsx_force/synaptics_dsx_i2c.c
  32678. @@ -0,0 +1,901 @@
  32679. +/*
  32680. + * Synaptics DSX touchscreen driver
  32681. + *
  32682. + * Copyright (C) 2012-2015 Synaptics Incorporated. All rights reserved.
  32683. + *
  32684. + * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
  32685. + * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
  32686. + * Copyright (C) 2017 XiaoMi, Inc.
  32687. + *
  32688. + * This program is free software; you can redistribute it and/or modify
  32689. + * it under the terms of the GNU General Public License as published by
  32690. + * the Free Software Foundation; either version 2 of the License, or
  32691. + * (at your option) any later version.
  32692. + *
  32693. + * This program is distributed in the hope that it will be useful,
  32694. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32695. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  32696. + * GNU General Public License for more details.
  32697. + *
  32698. + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  32699. + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  32700. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  32701. + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  32702. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32703. + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  32704. + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  32705. + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  32706. + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  32707. + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  32708. + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  32709. + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  32710. + * DOLLARS.
  32711. + */
  32712. +
  32713. +#include <linux/kernel.h>
  32714. +#include <linux/module.h>
  32715. +#include <linux/slab.h>
  32716. +#include <linux/i2c.h>
  32717. +#include <linux/delay.h>
  32718. +#include <linux/input.h>
  32719. +#include <linux/types.h>
  32720. +#include <linux/of_gpio.h>
  32721. +#include <linux/platform_device.h>
  32722. +#include <linux/input/synaptics_dsx.h>
  32723. +#include "synaptics_dsx_core.h"
  32724. +
  32725. +#define SYN_I2C_RETRY_TIMES 4
  32726. +
  32727. +#define I2C_BURST_LIMIT 2048
  32728. +
  32729. +#define MAX_WRITE_SIZE 4096
  32730. +
  32731. +static unsigned char *wr_buf;
  32732. +
  32733. +static struct synaptics_dsx_hw_interface hw_if;
  32734. +
  32735. +static struct platform_device *synaptics_dsx_i2c_device;
  32736. +
  32737. +#ifdef CONFIG_OF
  32738. +static void dump_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
  32739. +{
  32740. +}
  32741. +
  32742. +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata)
  32743. +{
  32744. + int retval;
  32745. + u32 value;
  32746. + const char *name;
  32747. + struct synaptics_dsx_config_info *config_info;
  32748. + struct property *prop;
  32749. + struct device_node *temp, *np = dev->of_node;
  32750. +
  32751. + bdata->irq_gpio = of_get_named_gpio_flags(np,
  32752. + "synaptics,irq-gpio", 0, NULL);
  32753. + if (bdata->irq_gpio < 0)
  32754. + return -EINVAL;
  32755. +
  32756. + retval = of_property_read_u32(np, "synaptics,irq-on-state",
  32757. + &value);
  32758. + if (retval < 0)
  32759. + bdata->irq_on_state = 0;
  32760. + else
  32761. + bdata->irq_on_state = value;
  32762. +
  32763. + retval = of_property_read_u32(np, "synaptics,irq-flags", &value);
  32764. + if (retval < 0)
  32765. + return retval;
  32766. + else
  32767. + bdata->irq_flags = value;
  32768. +
  32769. + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name);
  32770. + if (retval == -EINVAL)
  32771. + bdata->pwr_reg_name = NULL;
  32772. + else if (retval < 0)
  32773. + return retval;
  32774. + else
  32775. + bdata->pwr_reg_name = name;
  32776. +
  32777. + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name);
  32778. + if (retval == -EINVAL)
  32779. + bdata->bus_reg_name = NULL;
  32780. + else if (retval < 0)
  32781. + return retval;
  32782. + else
  32783. + bdata->bus_reg_name = name;
  32784. +
  32785. + bdata->panel_is_incell = of_property_read_bool(np, "synaptics,panel-is-incell");
  32786. +
  32787. + if (bdata->panel_is_incell) {
  32788. + retval = of_property_read_string(np, "synaptics,lab-reg-name", &name);
  32789. + if (retval == -EINVAL)
  32790. + bdata->lab_reg_name = NULL;
  32791. + else if (retval < 0)
  32792. + return retval;
  32793. + else
  32794. + bdata->lab_reg_name = name;
  32795. +
  32796. + retval = of_property_read_string(np, "synaptics,ibb-reg-name", &name);
  32797. + if (retval == -EINVAL)
  32798. + bdata->ibb_reg_name = NULL;
  32799. + else if (retval < 0)
  32800. + return retval;
  32801. + else
  32802. + bdata->ibb_reg_name = name;
  32803. +
  32804. + retval = of_property_read_string(np, "synaptics,disp-reg-name", &name);
  32805. + if (retval == -EINVAL)
  32806. + bdata->disp_reg_name = NULL;
  32807. + else if (retval < 0)
  32808. + return retval;
  32809. + else
  32810. + bdata->disp_reg_name = name;
  32811. + }
  32812. +
  32813. + retval = of_property_read_string(np, "synaptics,power-gpio-name", &name);
  32814. + if (retval == -EINVAL)
  32815. + bdata->power_gpio_name = NULL;
  32816. + else if (retval < 0)
  32817. + return retval;
  32818. + else
  32819. + bdata->power_gpio_name = name;
  32820. +
  32821. + retval = of_property_read_string(np, "synaptics,reset-gpio-name", &name);
  32822. + if (retval == -EINVAL)
  32823. + bdata->reset_gpio_name = NULL;
  32824. + else if (retval < 0)
  32825. + return retval;
  32826. + else
  32827. + bdata->reset_gpio_name = name;
  32828. +
  32829. + retval = of_property_read_string(np, "synaptics,irq-gpio-name", &name);
  32830. + if (retval == -EINVAL)
  32831. + bdata->irq_gpio_name = NULL;
  32832. + else if (retval < 0)
  32833. + return retval;
  32834. + else
  32835. + bdata->irq_gpio_name = name;
  32836. +
  32837. + bdata->cut_off_power = of_property_read_bool(np, "synaptics,cut-off-power");
  32838. +
  32839. + bdata->power_gpio = of_get_named_gpio_flags(np,
  32840. + "synaptics,power-gpio", 0, NULL);
  32841. + if (bdata->power_gpio >= 0) {
  32842. + retval = of_property_read_u32(np, "synaptics,power-on-state",
  32843. + &value);
  32844. + if (retval < 0)
  32845. + return retval;
  32846. + else
  32847. + bdata->power_on_state = value;
  32848. + } else
  32849. + bdata->power_gpio = -1;
  32850. +
  32851. + retval = of_property_read_u32(np, "synaptics,power-delay-ms",
  32852. + &value);
  32853. + if (retval < 0)
  32854. + bdata->power_delay_ms = 0; /* No power delay by default */
  32855. + else
  32856. + bdata->power_delay_ms = value;
  32857. +
  32858. + bdata->mdss_reset = of_get_named_gpio_flags(np,
  32859. + "synaptics,mdss-dsi-reset", 0, NULL);
  32860. + if (bdata->mdss_reset >= 0) {
  32861. + retval = of_property_read_u32(np, "synaptics,mdss-reset-state",
  32862. + &value);
  32863. + if (retval < 0)
  32864. + return retval;
  32865. + else
  32866. + bdata->mdss_reset_state = value;
  32867. + } else
  32868. + bdata->mdss_reset = -1;
  32869. +
  32870. + bdata->reset_gpio = of_get_named_gpio_flags(np,
  32871. + "synaptics,reset-gpio", 0, NULL);
  32872. + if (bdata->reset_gpio >= 0) {
  32873. + retval = of_property_read_u32(np, "synaptics,reset-on-state",
  32874. + &value);
  32875. + if (retval < 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement