ddp_drv.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. #define LOG_TAG "ddp_drv"
  2. #include <linux/kernel.h>
  3. #include <linux/mm.h>
  4. #include <linux/mm_types.h>
  5. #include <linux/module.h>
  6. #include <generated/autoconf.h>
  7. #include <linux/init.h>
  8. #include <linux/types.h>
  9. #include <linux/cdev.h>
  10. #include <linux/kdev_t.h>
  11. #include <linux/delay.h>
  12. #include <linux/ioport.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/dma-mapping.h>
  15. #include <linux/device.h>
  16. #include <linux/fs.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/wait.h>
  19. #include <linux/spinlock.h>
  20. #include <linux/param.h>
  21. #include <linux/uaccess.h>
  22. #include <linux/sched.h>
  23. #include <linux/slab.h>
  24. #include <linux/sched.h>
  25. #include <linux/kthread.h>
  26. #include <linux/timer.h>
  27. /* #include <mach/mt_smi.h> */
  28. #include <linux/proc_fs.h> /* proc file use */
  29. #include <linux/miscdevice.h>
  30. /* ION */
  31. /* #include <linux/ion.h> */
  32. /* #include <linux/ion_drv.h> */
  33. /* #include "m4u.h" */
  34. #include <linux/vmalloc.h>
  35. #include <linux/dma-mapping.h>
  36. #include <linux/of.h>
  37. #include <linux/of_irq.h>
  38. #include <linux/of_address.h>
  39. #include <asm/io.h>
  40. /*#include <mach/irqs.h>*/
  41. /* #include <mach/mt_reg_base.h> */
  42. /* #include <mach/mt_irq.h> */
  43. /* #include <mach/irqs.h> */
  44. #ifdef CONFIG_MTK_CLKMGR
  45. #include <mach/mt_clkmgr.h> /* ???? */
  46. #endif
  47. /* #include <mach/mt_irq.h> */
  48. #include <mt-plat/sync_write.h>
  49. #include "m4u.h"
  50. #include "disp_drv_platform.h"
  51. #include "ddp_drv.h"
  52. #include "ddp_reg.h"
  53. #include "ddp_hal.h"
  54. #include "ddp_log.h"
  55. #include "ddp_irq.h"
  56. #include "ddp_info.h"
  57. #ifndef DISP_NO_DPI
  58. #include "ddp_dpi_reg.h"
  59. #endif
  60. #include "ddp_debug.h"
  61. #include "ddp_path.h"
  62. /* for sysfs */
  63. #include <linux/kobject.h>
  64. #include <linux/sysfs.h>
  65. #define DISP_DEVNAME "DISPSYS"
  66. typedef struct {
  67. pid_t open_pid;
  68. pid_t open_tgid;
  69. struct list_head testList;
  70. spinlock_t node_lock;
  71. } disp_node_struct;
  72. static struct kobject kdispobj;
  73. /*****************************************************************************/
  74. /* sysfs for access information */
  75. /* --------------------------------------// */
  76. static ssize_t disp_kobj_show(struct kobject *kobj, struct attribute *attr, char *buffer)
  77. {
  78. int size = 0x0;
  79. if (0 == strcmp(attr->name, "dbg1"))
  80. size = ddp_dump_reg_to_buf(2, (unsigned long *)buffer); /* DISP_MODULE_RDMA */
  81. else if (0 == strcmp(attr->name, "dbg2"))
  82. size = ddp_dump_reg_to_buf(1, (unsigned long *)buffer); /* DISP_MODULE_OVL */
  83. else if (0 == strcmp(attr->name, "dbg3"))
  84. size = ddp_dump_reg_to_buf(0, (unsigned long *)buffer); /* DISP_MODULE_WDMA0 */
  85. else if (0 == strcmp(attr->name, "dbg4"))
  86. size = ddp_dump_lcm_param_to_buf(0, (unsigned long *)buffer); /* DISP_MODULE_LCM */
  87. return size;
  88. }
  89. /* --------------------------------------// */
  90. static struct kobj_type disp_kobj_ktype = {
  91. .sysfs_ops = &(const struct sysfs_ops){
  92. .show = disp_kobj_show,
  93. .store = NULL
  94. },
  95. .default_attrs = (struct attribute *[]){
  96. &(struct attribute){
  97. .name = "dbg1", /* disp, dbg1 */
  98. .mode = S_IRUGO
  99. },
  100. &(struct attribute){
  101. .name = "dbg2", /* disp, dbg2 */
  102. .mode = S_IRUGO
  103. },
  104. &(struct attribute){
  105. .name = "dbg3", /* disp, dbg3 */
  106. .mode = S_IRUGO
  107. },
  108. &(struct attribute){
  109. .name = "dbg4", /* disp, dbg4 */
  110. .mode = S_IRUGO
  111. },
  112. NULL
  113. }
  114. };
  115. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  116. #include "mobicore_driver_api.h"
  117. #include "tlcApitplay.h"
  118. /* ------------------------------------------------------------------------------ */
  119. /* handle address for t-play */
  120. /* ------------------------------------------------------------------------------ */
  121. static unsigned int *tplay_handle_virt_addr;
  122. static dma_addr_t handle_pa;
  123. /* allocate a fixed physical memory address for storing tplay handle */
  124. void init_tplay_handle(struct device *dev)
  125. {
  126. void *va;
  127. va = dma_alloc_coherent(dev, sizeof(unsigned int), &handle_pa, GFP_KERNEL);
  128. if (NULL != va)
  129. DDPDBG("[SVP] allocate handle_pa[%pa]\n", &va);
  130. else
  131. DDPERR("[SVP] failed to allocate handle_pa\n");
  132. tplay_handle_virt_addr = (unsigned int *)va;
  133. }
  134. static int write_tplay_handle(unsigned int handle_value)
  135. {
  136. if (NULL != tplay_handle_virt_addr) {
  137. DDPDBG("[SVP] write_tplay_handle 0x%x\n", handle_value);
  138. *tplay_handle_virt_addr = handle_value;
  139. return 0;
  140. }
  141. return -EFAULT;
  142. }
  143. static const uint32_t mc_deviceId = MC_DEVICE_ID_DEFAULT;
  144. static const struct mc_uuid_t MC_UUID_TPLAY = {
  145. {0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  146. };
  147. static struct mc_session_handle tplaySessionHandle;
  148. static tplay_tciMessage_t *pTplayTci;
  149. static volatile unsigned int opened_device;
  150. static enum mc_result late_open_mobicore_device(void)
  151. {
  152. enum mc_result mcRet = MC_DRV_OK;
  153. if (0 == opened_device) {
  154. DDPDBG("=============== open mobicore device ===============\n");
  155. /* Open MobiCore device */
  156. mcRet = mc_open_device(mc_deviceId);
  157. if (MC_DRV_ERR_INVALID_OPERATION == mcRet) {
  158. /* skip false alarm when the mc_open_device(mc_deviceId) is called more than once */
  159. DDPDBG("mc_open_device already done\n");
  160. } else if (MC_DRV_OK != mcRet) {
  161. DDPERR("mc_open_device failed: %d @%s line %d\n", mcRet, __func__,
  162. __LINE__);
  163. return mcRet;
  164. }
  165. opened_device = 1;
  166. }
  167. return MC_DRV_OK;
  168. }
  169. static int open_tplay_driver_connection(void)
  170. {
  171. enum mc_result mcRet = MC_DRV_OK;
  172. if (tplaySessionHandle.session_id != 0) {
  173. DDPMSG("tplay TDriver session already created\n");
  174. return 0;
  175. }
  176. DDPDBG("=============== late init tplay TDriver session ===============\n");
  177. do {
  178. late_open_mobicore_device();
  179. /* Allocating WSM for DCI */
  180. mcRet = mc_malloc_wsm(mc_deviceId, 0, sizeof(tplay_tciMessage_t), (uint8_t **) &pTplayTci, 0);
  181. if (MC_DRV_OK != mcRet) {
  182. DDPERR("mc_malloc_wsm failed: %d @%s line %d\n", mcRet, __func__, __LINE__);
  183. return -1;
  184. }
  185. /* Open session the TDriver */
  186. memset(&tplaySessionHandle, 0, sizeof(tplaySessionHandle));
  187. tplaySessionHandle.device_id = mc_deviceId;
  188. mcRet = mc_open_session(&tplaySessionHandle, &MC_UUID_TPLAY, (uint8_t *) pTplayTci,
  189. (uint32_t) sizeof(tplay_tciMessage_t));
  190. if (MC_DRV_OK != mcRet) {
  191. DDPERR("mc_open_session failed: %d @%s line %d\n", mcRet, __func__,
  192. __LINE__);
  193. /* if failed clear session handle */
  194. memset(&tplaySessionHandle, 0, sizeof(tplaySessionHandle));
  195. return -1;
  196. }
  197. } while (0);
  198. return (MC_DRV_OK == mcRet) ? 0 : -1;
  199. }
  200. static int close_tplay_driver_connection(void)
  201. {
  202. enum mc_result mcRet = MC_DRV_OK;
  203. DDPDBG("=============== close tplay TDriver session ===============\n");
  204. /* Close session */
  205. if (tplaySessionHandle.session_id != 0) { /* we have an valid session */
  206. mcRet = mc_close_session(&tplaySessionHandle);
  207. if (MC_DRV_OK != mcRet) {
  208. DDPERR("mc_close_session failed: %d @%s line %d\n", mcRet, __func__,
  209. __LINE__);
  210. memset(&tplaySessionHandle, 0, sizeof(tplaySessionHandle)); /* clear handle value anyway */
  211. return -1;
  212. }
  213. }
  214. memset(&tplaySessionHandle, 0, sizeof(tplaySessionHandle));
  215. mcRet = mc_free_wsm(mc_deviceId, (uint8_t *) pTplayTci);
  216. if (MC_DRV_OK != mcRet) {
  217. DDPERR("mc_free_wsm failed: %d @%s line %d\n", mcRet, __func__, __LINE__);
  218. return -1;
  219. }
  220. return 0;
  221. }
  222. /* return 0 for success and -1 for error */
  223. static int set_tplay_handle_addr_request(void)
  224. {
  225. int ret = 0;
  226. enum mc_result mcRet = MC_DRV_OK;
  227. DDPDBG("[SVP] set_tplay_handle_addr_request\n");
  228. open_tplay_driver_connection();
  229. if (tplaySessionHandle.session_id == 0) {
  230. DDPERR("[SVP] invalid tplay session\n");
  231. return -1;
  232. }
  233. DDPDBG("[SVP] handle_pa=0x%pa\n", &handle_pa);
  234. /* set other TCI parameter */
  235. pTplayTci->tplay_handle_low_addr = (uint32_t) handle_pa;
  236. #ifdef CONFIG_ARM64
  237. pTplayTci->tplay_handle_high_addr = (uint32_t) (handle_pa >> 32);
  238. #else
  239. pTplayTci->tplay_handle_high_addr = 0;
  240. #endif
  241. /* set TCI command */
  242. pTplayTci->cmd.header.commandId = CMD_TPLAY_REQUEST;
  243. /* notify the trustlet */
  244. DDPDBG("[SVP] notify Tlsec trustlet CMD_TPLAY_REQUEST\n");
  245. mcRet = mc_notify(&tplaySessionHandle);
  246. if (MC_DRV_OK != mcRet) {
  247. DDPERR("[SVP] mc_notify failed: %d @%s line %d\n", mcRet, __func__, __LINE__);
  248. ret = -1;
  249. goto _notify_to_trustlet_fail;
  250. }
  251. /* wait for response from the trustlet */
  252. mcRet = mc_wait_notification(&tplaySessionHandle, MC_INFINITE_TIMEOUT);
  253. if (MC_DRV_OK != mcRet) {
  254. DDPERR("[SVP] mc_wait_notification failed: %d @%s line %d\n", mcRet, __func__,
  255. __LINE__);
  256. ret = -1;
  257. goto _notify_from_trustlet_fail;
  258. }
  259. DDPDBG("[SVP] CMD_TPLAY_REQUEST result=%d, return code=%d\n", pTplayTci->result,
  260. pTplayTci->rsp.header.returnCode);
  261. _notify_from_trustlet_fail:
  262. _notify_to_trustlet_fail:
  263. close_tplay_driver_connection();
  264. return ret;
  265. }
  266. #ifdef TPLAY_DUMP_PA_DEBUG
  267. static int dump_tplay_physcial_addr(void)
  268. {
  269. DDPDBG("[SVP] dump_tplay_physcial_addr\n");
  270. int ret = 0;
  271. enum mc_result mcRet = MC_DRV_OK;
  272. open_tplay_driver_connection();
  273. if (tplaySessionHandle.session_id == 0) {
  274. DDPERR("[SVP] invalid tplay session\n");
  275. return -1;
  276. }
  277. /* set TCI command */
  278. pTplayTci->cmd.header.commandId = CMD_TPLAY_DUMP_PHY;
  279. /* notify the trustlet */
  280. DDPMSG("[SVP] notify Tlsec trustlet CMD_TPLAY_DUMP_PHY\n");
  281. mcRet = mc_notify(&tplaySessionHandle);
  282. if (MC_DRV_OK != mcRet) {
  283. DDPERR("[SVP] mc_notify failed: %d @%s line %d\n", mcRet, __func__, __LINE__);
  284. ret = -1;
  285. goto _notify_to_trustlet_fail;
  286. }
  287. /* wait for response from the trustlet */
  288. mcRet = mc_wait_notification(&tplaySessionHandle, MC_INFINITE_TIMEOUT);
  289. if (MC_DRV_OK != mcRet) {
  290. DDPERR("[SVP] mc_wait_notification failed: %d @%s line %d\n", mcRet, __func__,
  291. __LINE__);
  292. ret = -1;
  293. goto _notify_from_trustlet_fail;
  294. }
  295. DDPDBG("[SVP] CMD_TPLAY_DUMP_PHY result=%d, return code=%d\n", pTplayTci->result,
  296. pTplayTci->rsp.header.returnCode);
  297. _notify_from_trustlet_fail:
  298. _notify_to_trustlet_fail:
  299. close_tplay_driver_connection();
  300. return ret;
  301. }
  302. #endif /* TPLAY_DUMP_PA_DEBUG */
  303. static int disp_path_notify_tplay_handle(unsigned int handle_value)
  304. {
  305. int ret;
  306. static int executed; /* this function can execute only once */
  307. if (0 == executed) {
  308. if (set_tplay_handle_addr_request())
  309. return -EFAULT;
  310. executed = 1;
  311. }
  312. ret = write_tplay_handle(handle_value);
  313. #ifdef TPLAY_DUMP_PA_DEBUG
  314. dump_tplay_physcial_addr();
  315. #endif /* TPLAY_DUMP_PA_DEBUG */
  316. return ret;
  317. }
  318. #endif /* defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT) */
  319. static long disp_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  320. {
  321. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  322. if (DISP_IOCTL_SET_TPLAY_HANDLE == cmd) {
  323. unsigned int value;
  324. if (copy_from_user(&value, (void *)arg, sizeof(unsigned int))) {
  325. DDPERR("DISP_IOCTL_SET_TPLAY_HANDLE, copy_from_user failed\n");
  326. return -EFAULT;
  327. }
  328. if (disp_path_notify_tplay_handle(value)) {
  329. DDPERR
  330. ("DISP_IOCTL_SET_TPLAY_HANDLE, disp_path_notify_tplay_handle failed\n");
  331. return -EFAULT;
  332. }
  333. }
  334. #endif
  335. return 0;
  336. }
  337. static long disp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  338. {
  339. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  340. if (DISP_IOCTL_SET_TPLAY_HANDLE == cmd)
  341. return disp_unlocked_ioctl(file, cmd, arg);
  342. #endif
  343. return 0;
  344. }
  345. static int disp_open(struct inode *inode, struct file *file)
  346. {
  347. disp_node_struct *pNode = NULL;
  348. DDPDBG("enter disp_open() process:%s\n", current->comm);
  349. /* Allocate and initialize private data */
  350. file->private_data = kmalloc(sizeof(disp_node_struct), GFP_ATOMIC);
  351. if (NULL == file->private_data) {
  352. DDPMSG("Not enough entry for DDP open operation\n");
  353. return -ENOMEM;
  354. }
  355. pNode = (disp_node_struct *) file->private_data;
  356. pNode->open_pid = current->pid;
  357. pNode->open_tgid = current->tgid;
  358. INIT_LIST_HEAD(&(pNode->testList));
  359. spin_lock_init(&pNode->node_lock);
  360. return 0;
  361. }
  362. static ssize_t disp_read(struct file *file, char __user *data, size_t len, loff_t *ppos)
  363. {
  364. return 0;
  365. }
  366. static int disp_release(struct inode *inode, struct file *file)
  367. {
  368. disp_node_struct *pNode = NULL;
  369. DDPDBG("enter disp_release() process:%s\n", current->comm);
  370. pNode = (disp_node_struct *) file->private_data;
  371. spin_lock(&pNode->node_lock);
  372. spin_unlock(&pNode->node_lock);
  373. if (NULL != file->private_data) {
  374. kfree(file->private_data);
  375. file->private_data = NULL;
  376. }
  377. return 0;
  378. }
  379. static int disp_flush(struct file *file, fl_owner_t a_id)
  380. {
  381. return 0;
  382. }
  383. static int disp_mmap(struct file *file, struct vm_area_struct *a_pstVMArea)
  384. {
  385. return 0;
  386. }
  387. struct dispsys_device {
  388. void __iomem *regs[DISP_REG_NUM];
  389. struct device *dev;
  390. int irq[DISP_REG_NUM];
  391. #ifndef CONFIG_MTK_CLKMGR
  392. struct clk *disp_clk[MAX_DISP_CLK_CNT];
  393. #endif
  394. };
  395. static struct platform_device mydev;
  396. static struct dispsys_device *dispsys_dev;
  397. unsigned int dispsys_irq[DISP_REG_NUM] = { 0 };
  398. unsigned long dispsys_reg[DISP_REG_NUM] = { 0 };
  399. unsigned long mipi_tx_reg = 0;
  400. unsigned long dsi_reg_va = 0;
  401. static int disp_is_intr_enable(DISP_REG_ENUM module)
  402. {
  403. switch (module) {
  404. case DISP_REG_OVL0:
  405. case DISP_REG_OVL1:
  406. case DISP_REG_RDMA0:
  407. case DISP_REG_RDMA1:
  408. case DISP_REG_MUTEX:
  409. case DISP_REG_DSI0:
  410. case DISP_REG_AAL:
  411. case DISP_REG_CONFIG:
  412. return 1;
  413. case DISP_REG_WDMA1: /* FIXME: WDMA1 intr is abonrmal FPGA so mark first, enable after EVB works */
  414. case DISP_REG_COLOR:
  415. case DISP_REG_CCORR:
  416. case DISP_REG_GAMMA:
  417. case DISP_REG_DITHER:
  418. case DISP_REG_UFOE:
  419. case DISP_REG_OD:
  420. case DISP_REG_PWM:
  421. case DISP_REG_DPI0:
  422. case DISP_REG_SMI_LARB0:
  423. case DISP_REG_SMI_COMMON:
  424. case DISP_REG_CONFIG2:
  425. case DISP_REG_CONFIG3:
  426. case DISP_REG_IO_DRIVING1:
  427. case DISP_REG_IO_DRIVING2:
  428. case DISP_REG_IO_DRIVING3:
  429. case DISP_REG_EFUSE:
  430. case DISP_REG_EFUSE_PERMISSION:
  431. case DISP_RGE_EFUSE_KEY:
  432. case DISP_REG_MIPI:
  433. case DISP_RGE_VENCPLL:
  434. return 0;
  435. case DISP_REG_WDMA0:
  436. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  437. return 0;
  438. #else
  439. return 1;
  440. #endif
  441. default:
  442. return 0;
  443. }
  444. }
  445. m4u_callback_ret_t disp_m4u_callback(int port, unsigned int mva, void *data)
  446. {
  447. DISP_MODULE_ENUM module = DISP_MODULE_OVL0;
  448. DDPERR("fault call port=%d, mva=0x%x, data=0x%p\n", port, mva, data);
  449. switch (port) {
  450. case M4U_PORT_DISP_OVL0:
  451. module = DISP_MODULE_OVL0;
  452. break;
  453. case M4U_PORT_DISP_RDMA0:
  454. module = DISP_MODULE_RDMA0;
  455. break;
  456. case M4U_PORT_DISP_WDMA0:
  457. module = DISP_MODULE_WDMA0;
  458. break;
  459. #if defined(MTK_FB_OVL1_SUPPORT)
  460. case M4U_PORT_DISP_OVL1:
  461. module = DISP_MODULE_OVL1;
  462. break;
  463. #endif
  464. #if defined(MTK_FB_RDMA1_SUPPORT)
  465. case M4U_PORT_DISP_RDMA1:
  466. module = DISP_MODULE_RDMA1;
  467. break;
  468. #endif
  469. default:
  470. DDPERR("unknown port=%d\n", port);
  471. }
  472. ddp_dump_analysis(module);
  473. ddp_dump_reg(module);
  474. #if defined(OVL_CASCADE_SUPPORT)
  475. /* always dump 2 OVL */
  476. if (module == DISP_MODULE_OVL0)
  477. ddp_dump_analysis(DISP_MODULE_OVL1);
  478. else if (module == DISP_MODULE_OVL1)
  479. ddp_dump_analysis(DISP_MODULE_OVL0);
  480. #endif
  481. /* disable translation fault after it happens to avoid prinkt too much issues(log is override) */
  482. m4u_enable_tf(port, 0);
  483. return 0;
  484. }
  485. void disp_m4u_tf_disable(void)
  486. {
  487. /* m4u_enable_tf(M4U_PORT_DISP_OVL0, 0); */
  488. #if defined(OVL_CASCADE_SUPPORT)
  489. m4u_enable_tf(M4U_PORT_DISP_OVL1, 0);
  490. #endif
  491. }
  492. struct device *disp_get_device(void)
  493. {
  494. return dispsys_dev->dev;
  495. }
  496. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  497. static struct miscdevice disp_misc_dev;
  498. #endif
  499. /* Kernel interface */
  500. static const struct file_operations disp_fops = {
  501. .owner = THIS_MODULE,
  502. .unlocked_ioctl = disp_unlocked_ioctl,
  503. .compat_ioctl = disp_compat_ioctl,
  504. .open = disp_open,
  505. .release = disp_release,
  506. .flush = disp_flush,
  507. .read = disp_read,
  508. #if 1
  509. .mmap = disp_mmap
  510. #endif
  511. };
  512. #ifndef CONFIG_MTK_CLKMGR
  513. /*
  514. * Note: The name order of the disp_clk_name[] must be synced with
  515. * the enum disp_clk_id in case get the wrong clock.
  516. */
  517. const char *disp_clk_name[MAX_DISP_CLK_CNT] = {
  518. "DISP0_SMI_COMMON",
  519. "DISP0_SMI_LARB0",
  520. "DISP0_DISP_OVL0",
  521. "DISP0_DISP_RDMA0",
  522. "DISP0_DISP_RDMA1",
  523. "DISP0_DISP_WDMA0",
  524. "DISP0_DISP_COLOR",
  525. "DISP0_DISP_CCORR",
  526. "DISP0_DISP_AAL",
  527. "DISP0_DISP_GAMMA",
  528. "DISP0_DISP_DITHER",
  529. "DISP1_DSI_ENGINE",
  530. "DISP1_DSI_DIGITAL",
  531. "DISP1_DPI_ENGINE",
  532. "DISP1_DPI_PIXEL",
  533. "DISP_PWM",
  534. "MUX_DPI0",
  535. "TVDPLL",
  536. "TVDPLL_CK",
  537. "TVDPLL_D2",
  538. "TVDPLL_D4",
  539. "DPI_CK",
  540. "MUX_DISPPWM",
  541. "UNIVPLL2_D4",
  542. "SYSPLL4_D2_D8",
  543. "AD_SYS_26M_CK",
  544. "DISP_MTCMOS_CLK"
  545. };
  546. int ddp_clk_prepare(eDDP_CLK_ID id)
  547. {
  548. int ret = 0;
  549. ret = clk_prepare(dispsys_dev->disp_clk[id]);
  550. if (ret)
  551. pr_err("DISPSYS CLK prepare failed: errno %d\n", ret);
  552. return ret;
  553. }
  554. int ddp_clk_unprepare(eDDP_CLK_ID id)
  555. {
  556. int ret = 0;
  557. clk_unprepare(dispsys_dev->disp_clk[id]);
  558. return ret;
  559. }
  560. int ddp_clk_enable(eDDP_CLK_ID id)
  561. {
  562. int ret = 0;
  563. ret = clk_enable(dispsys_dev->disp_clk[id]);
  564. if (ret)
  565. pr_err("DISPSYS CLK enable failed: errno %d\n", ret);
  566. return ret;
  567. }
  568. int ddp_clk_disable(eDDP_CLK_ID id)
  569. {
  570. int ret = 0;
  571. clk_disable(dispsys_dev->disp_clk[id]);
  572. return ret;
  573. }
  574. int ddp_clk_prepare_enable(eDDP_CLK_ID id)
  575. {
  576. int ret = 0;
  577. ret = clk_prepare_enable(dispsys_dev->disp_clk[id]);
  578. if (ret)
  579. pr_err("DISPSYS CLK prepare failed: errno %d\n", ret);
  580. return ret;
  581. }
  582. int ddp_clk_disable_unprepare(eDDP_CLK_ID id)
  583. {
  584. int ret = 0;
  585. clk_disable_unprepare(dispsys_dev->disp_clk[id]);
  586. return ret;
  587. }
  588. int ddp_clk_set_parent(eDDP_CLK_ID id, eDDP_CLK_ID parent)
  589. {
  590. return clk_set_parent(dispsys_dev->disp_clk[id], dispsys_dev->disp_clk[parent]);
  591. }
  592. int ddp_clk_set_rate(eDDP_CLK_ID id, unsigned long rate)
  593. {
  594. return clk_set_rate(dispsys_dev->disp_clk[id], rate);
  595. }
  596. #endif /* CONFIG_MTK_CLKMGR */
  597. static int disp_probe(struct platform_device *pdev)
  598. {
  599. struct class_device;
  600. #ifndef CONFIG_MTK_CLKMGR
  601. int i;
  602. #endif
  603. static unsigned int disp_probe_cnt;
  604. #if 0
  605. struct resource DT_res1;
  606. struct of_irq DT_res2;
  607. #endif
  608. if (disp_probe_cnt != 0)
  609. return 0;
  610. /* save pdev for disp_probe_1 */
  611. memcpy(&mydev, pdev, sizeof(mydev));
  612. if (dispsys_dev) {
  613. DDPERR("%s: dispsys_dev=0x%p\n", __func__, dispsys_dev);
  614. BUG();
  615. }
  616. dispsys_dev = kmalloc(sizeof(struct dispsys_device), GFP_KERNEL);
  617. if (!dispsys_dev) {
  618. DDPERR("Unable to allocate dispsys_dev\n");
  619. return -ENOMEM;
  620. }
  621. #ifndef CONFIG_MTK_CLKMGR
  622. for (i = 0; i < MAX_DISP_CLK_CNT; i++) {
  623. DDPMSG("DISPSYS get clock %s\n", disp_clk_name[i]);
  624. dispsys_dev->disp_clk[i] = devm_clk_get(&pdev->dev, disp_clk_name[i]);
  625. if (IS_ERR(dispsys_dev->disp_clk[i]))
  626. DDPERR("%s:%d, DISPSYS get %d,%s clock error!!!\n",
  627. __FILE__, __LINE__, i, disp_clk_name[i]);
  628. else {
  629. switch (i) {
  630. case DISP_MTCMOS_CLK:
  631. case DISP0_SMI_COMMON:
  632. case DISP0_SMI_LARB0:
  633. ddp_clk_prepare_enable(i);
  634. break;
  635. default:
  636. ddp_clk_prepare(i);
  637. break;
  638. }
  639. }
  640. }
  641. #endif /* CONFIG_MTK_CLKMGR */
  642. disp_probe_cnt++;
  643. return 0;
  644. }
  645. static int __init disp_probe_1(void)
  646. {
  647. struct class_device;
  648. int ret;
  649. int i;
  650. struct platform_device *pdev = &mydev;
  651. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  652. disp_misc_dev.minor = MISC_DYNAMIC_MINOR;
  653. disp_misc_dev.name = "mtk_disp";
  654. disp_misc_dev.fops = &disp_fops;
  655. disp_misc_dev.parent = NULL;
  656. ret = misc_register(&disp_misc_dev);
  657. if (ret) {
  658. pr_err("disp: fail to create mtk_disp node\n");
  659. return ret;
  660. }
  661. /* secure video path implementation: a physical address is allocated to place a handle for decryption buffer. */
  662. init_tplay_handle(&(pdev->dev)); /* non-zero value for valid VA */
  663. #endif
  664. if (!dispsys_dev) {
  665. DDPERR("%s: dispsys_dev=NULL\n", __func__);
  666. return -ENOMEM;
  667. }
  668. dispsys_dev->dev = &pdev->dev;
  669. /* iomap registers and irq */
  670. for (i = 0; i < DISP_REG_NUM; i++) {
  671. dispsys_dev->regs[i] = of_iomap(pdev->dev.of_node, i);
  672. if (!dispsys_dev->regs[i])
  673. continue; /* skip */
  674. dispsys_reg[i] = (unsigned long)dispsys_dev->regs[i];
  675. /* get IRQ ID and request IRQ */
  676. dispsys_dev->irq[i] = irq_of_parse_and_map(pdev->dev.of_node, i);
  677. dispsys_irq[i] = dispsys_dev->irq[i];
  678. if (!dispsys_dev->irq[i])
  679. continue; /* skip */
  680. #if 0
  681. if (of_address_to_resource(pdev->dev.of_node, i, &DT_res1))
  682. DDPERR("read DT reg table fail\n");
  683. if (of_irq_map_one(pdev->dev.of_node, i, &DT_res2))
  684. DDPERR("read DT irq table fail\n");
  685. if (!(((unsigned int)DT_res1.start == ddp_reg_pa_base[i]) &
  686. (DT_res2.specifier[1] == ddp_irq_num[i])))
  687. DDPERR("DT inconsistent, i=%d, module=%s, DT_addr=%x, DT_irq=%d, reg_pa=0x%x, irq=%d\n",
  688. i, ddp_get_reg_module_name(i), (unsigned int)DT_res1.start,
  689. DT_res2.specifier[1], ddp_reg_pa_base[i], ddp_irq_num[i]);
  690. #endif
  691. if (disp_is_intr_enable(i) == 1) {
  692. /* IRQF_TRIGGER_NONE dose not take effect here, real trigger mode set in dts file */
  693. ret = request_irq(dispsys_dev->irq[i], (irq_handler_t)disp_irq_handler,
  694. IRQF_TRIGGER_NONE, DISP_DEVNAME, NULL);
  695. if (ret) {
  696. DDPERR("Unable to request IRQ, request_irq fail, i=%d, irq=%d\n",
  697. i, dispsys_dev->irq[i]);
  698. return ret;
  699. }
  700. }
  701. }
  702. /* mipi tx reg map here */
  703. dsi_reg_va = dispsys_reg[DISP_REG_DSI0];
  704. mipi_tx_reg = dispsys_reg[DISP_REG_MIPI];
  705. #ifndef DISP_NO_DPI
  706. DPI_REG = (struct DPI_REGS *)dispsys_reg[DISP_REG_DPI0];
  707. DPI_TVDPLL_CON0 = dispsys_reg[DISP_TVDPLL_CON0];
  708. DPI_TVDPLL_CON1 = dispsys_reg[DISP_TVDPLL_CON1];
  709. #endif
  710. /* //// power on MMSYS for early porting */
  711. #ifdef CONFIG_FPGA_EARLY_PORTING
  712. pr_debug("[DISP Probe] power MMSYS:0x%lx,0x%lx\n", DISP_REG_CONFIG_MMSYS_CG_CLR0,
  713. DISP_REG_CONFIG_MMSYS_CG_CLR1);
  714. DISP_REG_SET(0, DISP_REG_CONFIG_MMSYS_CG_CLR0, 0xFFFFFFFF);
  715. DISP_REG_SET(0, DISP_REG_CONFIG_MMSYS_CG_CLR1, 0xFFFFFFFF);
  716. DISP_REG_SET(0, DISPSYS_CONFIG_BASE + 0xC00, 0x0); /* fpga should set this register */
  717. #endif
  718. /* //// */
  719. #ifdef MTKFB_NO_M4U
  720. DISP_REG_SET(0, DISP_REG_SMI_LARB_MMU_EN, 0x0); /* m4u disable */
  721. #endif
  722. /* init arrays */
  723. ddp_path_init();
  724. /* init M4U callback */
  725. /* DDPMSG("register m4u callback\n");*/
  726. m4u_register_fault_callback(M4U_PORT_DISP_OVL0, disp_m4u_callback, 0);
  727. m4u_register_fault_callback(M4U_PORT_DISP_RDMA0, disp_m4u_callback, 0);
  728. m4u_register_fault_callback(M4U_PORT_DISP_WDMA0, disp_m4u_callback, 0);
  729. #if defined(MTK_FB_OVL1_SUPPORT)
  730. m4u_register_fault_callback(M4U_PORT_DISP_OVL1, disp_m4u_callback, 0);
  731. #endif
  732. #if defined(MTK_FB_RDMA1_SUPPORT)
  733. m4u_register_fault_callback(M4U_PORT_DISP_RDMA1, disp_m4u_callback, 0);
  734. #endif
  735. /*not necessary */
  736. /* DDPMSG("dispsys probe done.\n"); */
  737. /* NOT_REFERENCED(class_dev); */
  738. /* bus hang issue error intr enable */
  739. /* when MMSYS clock off but GPU/MJC/PWM clock on, avoid display hang and trigger error intr */
  740. {
  741. DISP_REG_SET_FIELD(0, MMSYS_TO_MFG_TX_ERROR, DISP_REG_CONFIG_MMSYS_INTEN, 1);
  742. DISP_REG_SET_FIELD(0, MMSYS_TO_MJC_TX_ERROR, DISP_REG_CONFIG_MMSYS_INTEN, 1);
  743. DISP_REG_SET_FIELD(0, PWM0_APB_TX_ERROR, DISP_REG_CONFIG_MMSYS_INTEN, 1);
  744. }
  745. /* sysfs */
  746. /*not necessary */
  747. /* DDPMSG("sysfs disp +");*/
  748. /* add kobject */
  749. if (kobject_init_and_add(&kdispobj, &disp_kobj_ktype, NULL, "disp") < 0) {
  750. DDPERR("fail to add disp\n");
  751. return -ENOMEM;
  752. }
  753. return 0;
  754. }
  755. static int disp_remove(struct platform_device *pdev)
  756. {
  757. /* sysfs */
  758. kobject_put(&kdispobj);
  759. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  760. misc_deregister(&disp_misc_dev);
  761. #endif
  762. return 0;
  763. }
  764. static void disp_shutdown(struct platform_device *pdev)
  765. {
  766. /* Nothing yet */
  767. }
  768. /* PM suspend */
  769. static int disp_suspend(struct platform_device *pdev, pm_message_t mesg)
  770. {
  771. pr_debug("\n\n==== DISP suspend is called ====\n");
  772. return 0;
  773. }
  774. /* PM resume */
  775. static int disp_resume(struct platform_device *pdev)
  776. {
  777. pr_debug("\n\n==== DISP resume is called ====\n");
  778. return 0;
  779. }
  780. static const struct of_device_id dispsys_of_ids[] = {
  781. { .compatible = "mediatek,mt6735-dispsys", },
  782. { .compatible = "mediatek,dispsys", },
  783. {}
  784. };
  785. static struct platform_driver dispsys_of_driver = {
  786. .driver = {
  787. .name = DISP_DEVNAME,
  788. .owner = THIS_MODULE,
  789. .of_match_table = dispsys_of_ids,
  790. },
  791. .probe = disp_probe,
  792. .remove = disp_remove,
  793. .shutdown = disp_shutdown,
  794. .suspend = disp_suspend,
  795. .resume = disp_resume,
  796. };
  797. static int __init disp_init(void)
  798. {
  799. int ret = 0;
  800. DDPPRINT("Register the disp driver\n");
  801. if (platform_driver_register(&dispsys_of_driver)) {
  802. DDPERR("failed to register disp driver\n");
  803. /* platform_device_unregister(&disp_device); */
  804. ret = -ENODEV;
  805. return ret;
  806. }
  807. return 0;
  808. }
  809. static void __exit disp_exit(void)
  810. {
  811. #ifndef CONFIG_MTK_CLKMGR
  812. int i = 0;
  813. for (i = 0; i < MAX_DISP_CLK_CNT; i++)
  814. ddp_clk_unprepare(i);
  815. #endif
  816. platform_driver_unregister(&dispsys_of_driver);
  817. }
  818. arch_initcall(disp_init);
  819. module_init(disp_probe_1);
  820. module_exit(disp_exit);
  821. MODULE_AUTHOR("Tzu-Meng, Chung <Tzu-Meng.Chung@mediatek.com>");
  822. MODULE_DESCRIPTION("Display subsystem Driver");
  823. MODULE_LICENSE("GPL");