ebi2_host.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  2. *
  3. * This software is licensed under the terms of the GNU General Public
  4. * License version 2, as published by the Free Software Foundation, and
  5. * may be copied, distributed, and modified under those terms.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/sched.h>
  15. #include <linux/time.h>
  16. #include <linux/init.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/spinlock.h>
  19. #include <linux/hrtimer.h>
  20. #include <linux/clk.h>
  21. #include <linux/io.h>
  22. #include <linux/debugfs.h>
  23. #include <linux/delay.h>
  24. #include <linux/mutex.h>
  25. #include <linux/pm_runtime.h>
  26. #include <linux/regulator/consumer.h>
  27. #include <linux/semaphore.h>
  28. #include <linux/uaccess.h>
  29. #include <asm/system.h>
  30. #include <asm/mach-types.h>
  31. #include <mach/clk.h>
  32. #include <mach/hardware.h>
  33. #include "msm_fb.h"
  34. struct mdp_ccs mdp_ccs_rgb2yuv;
  35. struct mdp_ccs mdp_ccs_yuv2rgb;
  36. static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
  37. static int pdev_list_cnt;
  38. static int ebi2_host_resource_initialized;
  39. static struct msm_panel_common_pdata *ebi2_host_pdata;
  40. static int ebi2_host_probe(struct platform_device *pdev);
  41. static int ebi2_host_remove(struct platform_device *pdev);
  42. static int ebi2_host_runtime_suspend(struct device *dev)
  43. {
  44. dev_dbg(dev, "pm_runtime: suspending...\n");
  45. return 0;
  46. }
  47. static int ebi2_host_runtime_resume(struct device *dev)
  48. {
  49. dev_dbg(dev, "pm_runtime: resuming...\n");
  50. return 0;
  51. }
  52. static const struct dev_pm_ops ebi2_host_dev_pm_ops = {
  53. .runtime_suspend = ebi2_host_runtime_suspend,
  54. .runtime_resume = ebi2_host_runtime_resume,
  55. };
  56. static struct platform_driver ebi2_host_driver = {
  57. .probe = ebi2_host_probe,
  58. .remove = ebi2_host_remove,
  59. .shutdown = NULL,
  60. .driver = {
  61. /*
  62. * Simulate mdp hw
  63. */
  64. .name = "mdp",
  65. .pm = &ebi2_host_dev_pm_ops,
  66. },
  67. };
  68. void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
  69. boolean isr)
  70. {
  71. return;
  72. }
  73. int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
  74. {
  75. return 0;
  76. }
  77. int mdp_start_histogram(struct fb_info *info)
  78. {
  79. return 0;
  80. }
  81. int mdp_stop_histogram(struct fb_info *info)
  82. {
  83. return 0;
  84. }
  85. void mdp_refresh_screen(unsigned long data)
  86. {
  87. return;
  88. }
  89. static int ebi2_host_off(struct platform_device *pdev)
  90. {
  91. int ret;
  92. ret = panel_next_off(pdev);
  93. return ret;
  94. }
  95. static int ebi2_host_on(struct platform_device *pdev)
  96. {
  97. int ret;
  98. ret = panel_next_on(pdev);
  99. return ret;
  100. }
  101. static int ebi2_host_probe(struct platform_device *pdev)
  102. {
  103. struct platform_device *msm_fb_dev = NULL;
  104. struct msm_fb_data_type *mfd;
  105. struct msm_fb_panel_data *pdata = NULL;
  106. int rc;
  107. if ((pdev->id == 0) && (pdev->num_resources > 0)) {
  108. ebi2_host_pdata = pdev->dev.platform_data;
  109. ebi2_host_resource_initialized = 1;
  110. return 0;
  111. }
  112. ebi2_host_resource_initialized = 1;
  113. if (!ebi2_host_resource_initialized)
  114. return -EPERM;
  115. mfd = platform_get_drvdata(pdev);
  116. if (!mfd)
  117. return -ENODEV;
  118. if (mfd->key != MFD_KEY)
  119. return -EINVAL;
  120. if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
  121. return -ENOMEM;
  122. msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
  123. if (!msm_fb_dev)
  124. return -ENOMEM;
  125. /* link to the latest pdev */
  126. mfd->pdev = msm_fb_dev;
  127. if (ebi2_host_pdata) {
  128. mfd->mdp_rev = ebi2_host_pdata->mdp_rev;
  129. mfd->mem_hid = ebi2_host_pdata->mem_hid;
  130. }
  131. /* add panel data */
  132. if (platform_device_add_data
  133. (msm_fb_dev, pdev->dev.platform_data,
  134. sizeof(struct msm_fb_panel_data))) {
  135. pr_err("ebi2_host_probe: platform_device_add_data failed!\n");
  136. rc = -ENOMEM;
  137. goto ebi2_host_probe_err;
  138. }
  139. /* data chain */
  140. pdata = msm_fb_dev->dev.platform_data;
  141. pdata->on = ebi2_host_on;
  142. pdata->off = ebi2_host_off;
  143. pdata->next = pdev;
  144. /* set driver data */
  145. platform_set_drvdata(msm_fb_dev, mfd);
  146. rc = platform_device_add(msm_fb_dev);
  147. if (rc)
  148. goto ebi2_host_probe_err;
  149. pm_runtime_set_active(&pdev->dev);
  150. pm_runtime_enable(&pdev->dev);
  151. pdev_list[pdev_list_cnt++] = pdev;
  152. return 0;
  153. ebi2_host_probe_err:
  154. platform_device_put(msm_fb_dev);
  155. return rc;
  156. }
  157. void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
  158. boolean sync)
  159. {
  160. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  161. struct fb_info *fbi = mfd->fbi;
  162. struct msm_panel_info *panel_info = &mfd->panel_info;
  163. MDPIBUF *iBuf;
  164. int bpp = info->var.bits_per_pixel / 8;
  165. int yres, remainder;
  166. if (panel_info->mode2_yres != 0) {
  167. yres = panel_info->mode2_yres;
  168. remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
  169. } else {
  170. yres = panel_info->yres;
  171. remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
  172. }
  173. if (!remainder)
  174. remainder = PAGE_SIZE;
  175. down(&mfd->sem);
  176. iBuf = &mfd->ibuf;
  177. /* use virtual address */
  178. iBuf->buf = (uint8 *) fbi->screen_base;
  179. if (fbi->var.yoffset < yres) {
  180. iBuf->buf += fbi->var.xoffset * bpp;
  181. } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
  182. iBuf->buf += fbi->var.xoffset * bpp + yres *
  183. fbi->fix.line_length + PAGE_SIZE - remainder;
  184. } else {
  185. iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
  186. fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
  187. }
  188. iBuf->ibuf_width = info->var.xres_virtual;
  189. iBuf->bpp = bpp;
  190. iBuf->vsync_enable = sync;
  191. if (dirty) {
  192. /*
  193. * ToDo: dirty region check inside var.xoffset+xres
  194. * <-> var.yoffset+yres
  195. */
  196. iBuf->dma_x = dirty->xoffset % info->var.xres;
  197. iBuf->dma_y = dirty->yoffset % info->var.yres;
  198. iBuf->dma_w = dirty->width;
  199. iBuf->dma_h = dirty->height;
  200. } else {
  201. iBuf->dma_x = 0;
  202. iBuf->dma_y = 0;
  203. iBuf->dma_w = info->var.xres;
  204. iBuf->dma_h = info->var.yres;
  205. }
  206. mfd->ibuf_flushed = FALSE;
  207. up(&mfd->sem);
  208. }
  209. void mdp_dma_pan_update(struct fb_info *info)
  210. {
  211. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  212. MDPIBUF *iBuf;
  213. int i, j;
  214. uint32 data;
  215. uint8 *src;
  216. struct msm_fb_panel_data *pdata =
  217. (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  218. struct fb_info *fbi = mfd->fbi;
  219. iBuf = &mfd->ibuf;
  220. invalidate_caches((unsigned long)fbi->screen_base,
  221. (unsigned long)info->fix.smem_len,
  222. (unsigned long)info->fix.smem_start);
  223. pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
  224. iBuf->dma_h);
  225. for (i = 0; i < iBuf->dma_h; i++) {
  226. src = iBuf->buf + (fbi->fix.line_length * (iBuf->dma_y + i))
  227. + (iBuf->dma_x * iBuf->bpp);
  228. for (j = 0; j < iBuf->dma_w; j++) {
  229. data = (uint32)(*src++ >> 2) << 12;
  230. data |= (uint32)(*src++ >> 2) << 6;
  231. data |= (uint32)(*src++ >> 2);
  232. data = ((data&0x1FF)<<16) | ((data&0x3FE00)>>9);
  233. outpdw(mfd->data_port, data);
  234. }
  235. }
  236. }
  237. static int ebi2_host_remove(struct platform_device *pdev)
  238. {
  239. pm_runtime_disable(&pdev->dev);
  240. return 0;
  241. }
  242. static int ebi2_host_register_driver(void)
  243. {
  244. return platform_driver_register(&ebi2_host_driver);
  245. }
  246. static int __init ebi2_host_driver_init(void)
  247. {
  248. int ret;
  249. ret = ebi2_host_register_driver();
  250. if (ret) {
  251. pr_err("ebi2_host_register_driver() failed!\n");
  252. return ret;
  253. }
  254. return 0;
  255. }
  256. module_init(ebi2_host_driver_init);