mdp_dma_s.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* Copyright (c) 2008-2009, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  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. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/time.h>
  17. #include <linux/init.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/hrtimer.h>
  20. #include <mach/hardware.h>
  21. #include <linux/io.h>
  22. #include <asm/system.h>
  23. #include <asm/mach-types.h>
  24. #include <linux/semaphore.h>
  25. #include <linux/spinlock.h>
  26. #include <linux/fb.h>
  27. #include "mdp.h"
  28. #include "msm_fb.h"
  29. static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
  30. {
  31. MDPIBUF *iBuf = &mfd->ibuf;
  32. int mddi_dest = FALSE;
  33. uint32 outBpp = iBuf->bpp;
  34. uint32 dma_s_cfg_reg;
  35. uint8 *src;
  36. struct msm_fb_panel_data *pdata =
  37. (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  38. dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
  39. DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
  40. if (mfd->fb_imgType == MDP_BGR_565)
  41. dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
  42. else
  43. dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
  44. if (outBpp == 4)
  45. dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
  46. if (outBpp == 2)
  47. dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
  48. if (mfd->panel_info.pdest != DISPLAY_2) {
  49. printk(KERN_ERR "error: non-secondary type through dma_s!\n");
  50. return;
  51. }
  52. if (mfd->panel_info.type == MDDI_PANEL ||
  53. mfd->panel_info.type == EXT_MDDI_PANEL) {
  54. dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
  55. mddi_dest = TRUE;
  56. } else {
  57. dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
  58. outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
  59. }
  60. src = (uint8 *) iBuf->buf;
  61. /* starting input address */
  62. src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
  63. /* MDP cmd block enable */
  64. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  65. /* PIXELSIZE */
  66. if (mfd->panel_info.type == MDDI_PANEL) {
  67. MDP_OUTP(MDP_BASE + 0xa0004,
  68. (iBuf->dma_h << 16 | iBuf->dma_w));
  69. MDP_OUTP(MDP_BASE + 0xa0008, src); /* ibuf address */
  70. MDP_OUTP(MDP_BASE + 0xa000c,
  71. iBuf->ibuf_width * outBpp);/* ystride */
  72. } else {
  73. MDP_OUTP(MDP_BASE + 0xb0004,
  74. (iBuf->dma_h << 16 | iBuf->dma_w));
  75. MDP_OUTP(MDP_BASE + 0xb0008, src); /* ibuf address */
  76. MDP_OUTP(MDP_BASE + 0xb000c,
  77. iBuf->ibuf_width * outBpp);/* ystride */
  78. }
  79. if (mfd->panel_info.bpp == 18) {
  80. dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
  81. DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
  82. } else {
  83. dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
  84. DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
  85. }
  86. if (mddi_dest) {
  87. if (mfd->panel_info.type == MDDI_PANEL) {
  88. MDP_OUTP(MDP_BASE + 0xa0010,
  89. (iBuf->dma_y << 16) | iBuf->dma_x);
  90. MDP_OUTP(MDP_BASE + 0x00090, 1);
  91. } else {
  92. MDP_OUTP(MDP_BASE + 0xb0010,
  93. (iBuf->dma_y << 16) | iBuf->dma_x);
  94. MDP_OUTP(MDP_BASE + 0x00090, 2);
  95. }
  96. MDP_OUTP(MDP_BASE + 0x00094,
  97. (MDDI_VDO_PACKET_DESC << 16) |
  98. mfd->panel_info.mddi.vdopkt);
  99. } else {
  100. /* setting LCDC write window */
  101. pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
  102. iBuf->dma_h);
  103. }
  104. if (mfd->panel_info.type == MDDI_PANEL)
  105. MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
  106. else
  107. MDP_OUTP(MDP_BASE + 0xb0000, dma_s_cfg_reg);
  108. /* MDP cmd block disable */
  109. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  110. if (mfd->panel_info.type == MDDI_PANEL)
  111. mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
  112. else
  113. mdp_pipe_kickoff(MDP_DMA_E_TERM, mfd);
  114. }
  115. void mdp_dma_s_update(struct msm_fb_data_type *mfd)
  116. {
  117. down(&mfd->dma->mutex);
  118. if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
  119. down(&mfd->sem);
  120. mdp_enable_irq(MDP_DMA_S_TERM);
  121. if (mfd->panel_info.type == MDDI_PANEL)
  122. mdp_enable_irq(MDP_DMA_S_TERM);
  123. else
  124. mdp_enable_irq(MDP_DMA_E_TERM);
  125. mfd->dma->busy = TRUE;
  126. INIT_COMPLETION(mfd->dma->comp);
  127. mfd->ibuf_flushed = TRUE;
  128. mdp_dma_s_update_lcd(mfd);
  129. up(&mfd->sem);
  130. /* wait until DMA finishes the current job */
  131. wait_for_completion_killable(&mfd->dma->comp);
  132. if (mfd->panel_info.type == MDDI_PANEL)
  133. mdp_disable_irq(MDP_DMA_S_TERM);
  134. else
  135. mdp_disable_irq(MDP_DMA_E_TERM);
  136. /* signal if pan function is waiting for the update completion */
  137. if (mfd->pan_waiting) {
  138. mfd->pan_waiting = FALSE;
  139. complete(&mfd->pan_comp);
  140. }
  141. }
  142. up(&mfd->dma->mutex);
  143. }