extd_epd.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*****************************************************************************/
  2. /*****************************************************************************/
  3. #include "extd_info.h"
  4. #if defined(CONFIG_MTK_EPD_SUPPORT)
  5. #include <linux/mm.h>
  6. #include <linux/slab.h>
  7. #include <linux/dma-mapping.h>
  8. #include <linux/vmalloc.h>
  9. #include <linux/delay.h>
  10. #include <linux/kthread.h>
  11. /*#include <linux/rtpm_prio.h>*/
  12. #include <linux/atomic.h>
  13. #include <linux/io.h>
  14. /*#include "mach/eint.h"*/
  15. #include "mach/irqs.h"
  16. #include "ddp_irq.h"
  17. #include "ddp_info.h"
  18. #include "mtkfb_fence.h"
  19. #include "mtkfb_info.h"
  20. #include "epd_drv.h"
  21. #include "external_display.h"
  22. #include "extd_log.h"
  23. #include "extd_platform.h"
  24. /* ~~~~~~~~~~~~~~~~~~~~~~~the static variable~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  25. static int epd_layer_num;
  26. atomic_t epd_state = ATOMIC_INIT(0);
  27. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  28. /* ~~~~~~~~~~~~~~~~~~~~~~~the gloable variable~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  29. LCM_EPD_PARAMS EPD_Params;
  30. disp_ddp_path_config extd_epd_params;
  31. struct task_struct *epd_fence_release_task = NULL;
  32. wait_queue_head_t epd_fence_release_wq;
  33. atomic_t epd_fence_release_event = ATOMIC_INIT(0);
  34. wait_queue_head_t epd_vsync_wq;
  35. atomic_t epd_vsync_event = ATOMIC_INIT(0);
  36. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  37. /* ~~~~~~~~~~~~~~~~~~~~~~~the definition~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  38. enum EPD_POWER_STATE {
  39. EPD_STATE_OFF = 0,
  40. EPD_STATE_ON,
  41. EPD_STATE_STANDBY,
  42. };
  43. #define IS_EPD_ON() (EPD_STATE_ON == atomic_read(&epd_state))
  44. #define IS_EPD_OFF() (EPD_STATE_OFF == atomic_read(&epd_state))
  45. #define IS_EPD_STANDBY() (EPD_STATE_STANDBY == atomic_read(&epd_state))
  46. #define SET_EPD_ON() atomic_set(&epd_state, EPD_STATE_ON)
  47. #define SET_EPD_OFF() atomic_set(&epd_state, EPD_STATE_OFF)
  48. #define SET_EPD_STANDBY() atomic_set(&epd_state, EPD_STATE_STANDBY)
  49. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  50. /* ~~~~~~~~~~~~~~~~~~~~~~~~extern declare~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  51. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  52. static void _epd_rdma_irq_handler(DISP_MODULE_ENUM module, unsigned int param)
  53. {
  54. /*RET_VOID_IF_NOLOG(!IS_EPD_ON());*/
  55. if (!IS_EPD_ON())
  56. return;
  57. if (param & 0x2) { /* start */
  58. atomic_set(&epd_fence_release_event, 1);
  59. wake_up_interruptible(&epd_fence_release_wq);
  60. /* vsync */
  61. atomic_set(&epd_vsync_event, 1);
  62. wake_up_interruptible(&epd_vsync_wq);
  63. }
  64. }
  65. /* extern int ddp_dpi_dump(DISP_MODULE_ENUM module, int level); */
  66. static int epd_fence_release_kthread(void *data)
  67. {
  68. struct sched_param param = {.sched_priority = RTPM_PRIO_SCRN_UPDATE };
  69. sched_setscheduler(current, SCHED_RR, &param);
  70. unsigned int session_id = 0;
  71. int fence_idx = 0;
  72. unsigned long input_curr_addr;
  73. for (;;) {
  74. wait_event_interruptible(epd_fence_release_wq, atomic_read(&epd_fence_release_event));
  75. atomic_set(&epd_fence_release_event, 0);
  76. session_id = ext_disp_get_sess_id();
  77. fence_idx = -1;
  78. if (session_id == 0)
  79. continue;
  80. ext_disp_get_curr_addr(&input_curr_addr, 0);
  81. fence_idx = disp_sync_find_fence_idx_by_addr(session_id, 0, input_curr_addr);
  82. mtkfb_release_fence(session_id, 0, fence_idx);
  83. if (kthread_should_stop())
  84. break;
  85. }
  86. return 0;
  87. }
  88. int epd_waitVsync(void)
  89. {
  90. unsigned int session_id = ext_disp_get_sess_id();
  91. disp_session_sync_info *session_info = disp_get_session_sync_info_for_debug(session_id);
  92. if (session_info)
  93. dprec_start(&session_info->event_waitvsync, 0, 0);
  94. if (!IS_EPD_ON()) {
  95. EPD_ERR("[epd]:epd has suspend, return directly\n");
  96. msleep(20);
  97. return 0;
  98. }
  99. if (wait_event_interruptible_timeout(epd_vsync_wq, atomic_read(&epd_vsync_event), HZ / 10) == 0)
  100. EPD_ERR("[epd] Wait VSync timeout. early_suspend=%d\n", IS_EPD_ON());
  101. atomic_set(&epd_vsync_event, 0);
  102. if (session_info)
  103. dprec_done(&session_info->event_waitvsync, 1, 0);
  104. return 0;
  105. }
  106. /*static*/ void epd_suspend(void)
  107. {
  108. EPD_FUNC();
  109. /*RET_VOID_IF(!IS_EPD_ON());*/
  110. if (IS_EPD_ON())
  111. SET_EPD_STANDBY();
  112. }
  113. /*static*/ void epd_resume(void)
  114. {
  115. EPD_FUNC();
  116. /*RET_VOID_IF(!IS_EPD_STANDBY());*/
  117. if (IS_EPD_STANDBY())
  118. SET_EPD_ON();
  119. }
  120. void epd_enable(int enable)
  121. {
  122. EPD_FUNC();
  123. }
  124. void epd_power_enable(int enable)
  125. {
  126. EPD_FUNC();
  127. if (enable) {
  128. /*RET_VOID_IF(!IS_EPD_OFF());*/
  129. /* need add actions */
  130. if (IS_EPD_OFF())
  131. SET_EPD_ON();
  132. } else {
  133. /*RET_VOID_IF(IS_EPD_OFF());*/
  134. /* need add actions */
  135. if (!IS_EPD_OFF())
  136. SET_EPD_OFF();
  137. }
  138. }
  139. int epd_get_dev_info(int is_sf, void *info)
  140. {
  141. int ret = 0;
  142. unsigned int Eink_width = 0;
  143. unsigned int Eink_height = 0;
  144. EPD_DRIVER *epd_drv = (EPD_DRIVER *) EPD_GetDriver();
  145. if (epd_drv == NULL) {
  146. EPD_ERR("[epd]%s, can not get epd driver handle\n", __func__);
  147. return -EFAULT;
  148. }
  149. if (epd_drv->get_screen_size)
  150. epd_drv->get_screen_size(&Eink_width, &Eink_height);
  151. if (is_sf == AP_GET_INFO) {
  152. int displayid = 0;
  153. mtk_dispif_info_t epd_info;
  154. if (!info) {
  155. EPD_ERR("ioctl pointer is NULL\n");
  156. return -EFAULT;
  157. }
  158. if (copy_from_user(&displayid, info, sizeof(displayid))) {
  159. EPD_ERR(": copy_from_user failed! line:%d\n", __LINE__);
  160. return -EAGAIN;
  161. }
  162. memset(&epd_info, 0, sizeof(mtk_dispif_info_t));
  163. epd_info.displayFormat = DISPIF_FORMAT_RGB888;
  164. epd_info.displayHeight = Eink_height;
  165. epd_info.displayWidth = Eink_width;
  166. epd_info.display_id = displayid;
  167. epd_info.isConnected = 1;
  168. epd_info.displayMode = DISP_IF_MODE_VIDEO;
  169. epd_info.displayType = DISP_IF_EPD;
  170. epd_info.vsyncFPS = 60;
  171. epd_info.isHwVsyncAvailable = 1;
  172. if (copy_to_user(info, &epd_info, sizeof(mtk_dispif_info_t))) {
  173. EPD_ERR("copy_to_user failed! line:%d\n", __LINE__);
  174. ret = -EFAULT;
  175. }
  176. HDMI_LOG("DEV_INFO configuration get displayType-%d\n", epd_info.displayType);
  177. } else if (is_sf == SF_GET_INFO) {
  178. disp_session_info *dispif_info = (disp_session_info *) info;
  179. memset((void *)dispif_info, 0, sizeof(disp_session_info));
  180. dispif_info->maxLayerNum = epd_layer_num;
  181. dispif_info->displayFormat = DISPIF_FORMAT_RGB888;
  182. dispif_info->displayHeight = Eink_height;
  183. dispif_info->displayWidth = Eink_width;
  184. dispif_info->displayMode = DISP_IF_MODE_VIDEO;
  185. dispif_info->isConnected = 1;
  186. dispif_info->displayType = DISP_IF_EPD;
  187. dispif_info->vsyncFPS = extd_epd_params.fps;
  188. dispif_info->isHwVsyncAvailable = 1;
  189. EPD_LOG("epd_get_dev_info lays:%d, type:%d, W:%d, H:%d\n", dispif_info->maxLayerNum,
  190. dispif_info->displayType, dispif_info->displayWidth, dispif_info->displayHeight);
  191. }
  192. return ret;
  193. }
  194. int epd_get_device_type(void)
  195. {
  196. int device_type = -1;
  197. device_type = DISP_IF_EPD;
  198. return device_type;
  199. }
  200. void epd_set_layer_num(int layer_num)
  201. {
  202. if (layer_num >= 0)
  203. epd_layer_num = (layer_num == 0 ? 0 : 1);
  204. }
  205. int epd_ioctl(unsigned int ioctl_cmd, int param1, int param2, unsigned long *params)
  206. {
  207. EPD_LOG("epd_ioctl ioctl_cmd:%d\n", ioctl_cmd);
  208. int ret = 0;
  209. switch (ioctl_cmd) {
  210. case RECOMPUTE_BG_CMD:
  211. /* */
  212. break;
  213. case GET_DEV_TYPE_CMD:
  214. ret = epd_get_device_type();
  215. break;
  216. case SET_LAYER_NUM_CMD:
  217. epd_set_layer_num(param1);
  218. break;
  219. default:
  220. EPD_LOG("epd_ioctl unknown command\n");
  221. break;
  222. }
  223. return ret;
  224. }
  225. void epd_init(void)
  226. {
  227. EPD_LOG("epd_init in+!\n");
  228. memset((void *)&EPD_Params, 0, sizeof(LCM_EPD_PARAMS));
  229. memset((void *)&extd_epd_params, 0, sizeof(disp_ddp_path_config));
  230. EPD_DRIVER *epd_drv = (EPD_DRIVER *) EPD_GetDriver();
  231. if (epd_drv == NULL) {
  232. EPD_ERR("[epd]%s, can not get epd driver handle\n", __func__);
  233. return;
  234. }
  235. if (epd_drv->init) {
  236. /* need to remove to power on function Donglei */
  237. epd_drv->init();
  238. }
  239. if (epd_drv->get_params) {
  240. epd_drv->get_params(&EPD_Params);
  241. extd_epd_params.fps = EPD_Params.pannel_frq;
  242. extd_epd_params.dispif_config.dpi.hsync_pulse_width = EPD_Params.hsync_pulse_width;
  243. extd_epd_params.dispif_config.dpi.hsync_back_porch = EPD_Params.hsync_back_porch;
  244. extd_epd_params.dispif_config.dpi.hsync_front_porch = EPD_Params.hsync_front_porch;
  245. extd_epd_params.dispif_config.dpi.vsync_pulse_width = EPD_Params.vsync_pulse_width;
  246. extd_epd_params.dispif_config.dpi.vsync_back_porch = EPD_Params.vsync_back_porch;
  247. extd_epd_params.dispif_config.dpi.vsync_front_porch = EPD_Params.vsync_front_porch;
  248. extd_epd_params.dispif_config.dpi.dpi_clock = EPD_Params.PLL_CLOCK;
  249. extd_epd_params.dispif_config.dpi.clk_pol = EPD_Params.clk_pol;
  250. extd_epd_params.dispif_config.dpi.de_pol = EPD_Params.de_pol;
  251. extd_epd_params.dispif_config.dpi.hsync_pol = EPD_Params.hsync_pol;
  252. extd_epd_params.dispif_config.dpi.vsync_pol = EPD_Params.vsync_pol;
  253. extd_epd_params.dispif_config.dpi.width = EPD_Params.width;
  254. extd_epd_params.dispif_config.dpi.height = EPD_Params.height;
  255. extd_epd_params.dispif_config.dpi.format = LCM_DPI_FORMAT_RGB888;
  256. extd_epd_params.dispif_config.dpi.rgb_order = LCM_COLOR_ORDER_RGB;
  257. extd_epd_params.dispif_config.dpi.i2x_en = EPD_Params.i2x_en;
  258. extd_epd_params.dispif_config.dpi.i2x_edge = EPD_Params.i2x_edge;
  259. extd_epd_params.dispif_config.dpi.embsync = EPD_Params.embsync;
  260. }
  261. ext_disp_set_lcm_param(&(extd_epd_params.dispif_config));
  262. init_waitqueue_head(&epd_fence_release_wq);
  263. init_waitqueue_head(&epd_vsync_wq);
  264. if (!epd_fence_release_task) {
  265. disp_register_module_irq_callback(DISP_MODULE_RDMA, _epd_rdma_irq_handler);
  266. epd_fence_release_task = kthread_create(epd_fence_release_kthread, NULL, "epd_fence_release_kthread");
  267. wake_up_process(epd_fence_release_task);
  268. }
  269. SET_EPD_OFF();
  270. }
  271. #endif
  272. const struct EXTD_DRIVER *EXTD_EPD_Driver(void)
  273. {
  274. static const struct EXTD_DRIVER extd_driver_epd = {
  275. #if defined(CONFIG_MTK_EPD_SUPPORT)
  276. .init = epd_init,
  277. .post_init = NULL,
  278. .deinit = NULL,
  279. .enable = epd_enable,
  280. .power_enable = epd_power_enable,
  281. .set_audio_enable = NULL,
  282. .set_resolution = NULL,
  283. .get_dev_info = epd_get_dev_info,
  284. .get_capability = NULL,
  285. .get_edid = NULL,
  286. .wait_vsync = epd_waitVsync,
  287. .fake_connect = NULL,
  288. .factory_mode_test = NULL,
  289. .ioctl = epd_ioctl
  290. #else
  291. .init = 0,
  292. .post_init = 0
  293. #endif
  294. };
  295. return &extd_driver_epd;
  296. }