summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c71
1 files changed, 57 insertions, 14 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
index 783621c88b..25265395b2 100644
--- a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c
@@ -71,7 +71,14 @@ bool lcd_active(void)
71/* Update a fraction of the display. */ 71/* Update a fraction of the display. */
72void lcd_update_rect(int x, int y, int width, int height) 72void lcd_update_rect(int x, int y, int width, int height)
73{ 73{
74x=0;y=0;width=LCD_WIDTH;height=LCD_HEIGHT; /* HACK! */ 74 /* Currently only do full updates.
75 * DMA can't handle partial updates and CPU is too slow compared
76 * to full DMA updates */
77 x = 0;
78 y = 0;
79 width = LCD_WIDTH;
80 height = LCD_HEIGHT;
81
75 mutex_lock(&lcd_mtx); 82 mutex_lock(&lcd_mtx);
76 83
77 __cpm_start_lcd(); 84 __cpm_start_lcd();
@@ -82,12 +89,12 @@ x=0;y=0;width=LCD_WIDTH;height=LCD_HEIGHT; /* HACK! */
82 89
83 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = DMAC_DCCSR_NDES; 90 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = DMAC_DCCSR_NDES;
84 REG_DMAC_DSAR(DMA_LCD_CHANNEL) = PHYSADDR((unsigned long)&lcd_framebuffer[y][x]); 91 REG_DMAC_DSAR(DMA_LCD_CHANNEL) = PHYSADDR((unsigned long)&lcd_framebuffer[y][x]);
85 REG_DMAC_DRSR(DMA_LCD_CHANNEL) = DMAC_DRSR_RS_SLCD; /* source = SLCD */ 92 REG_DMAC_DRSR(DMA_LCD_CHANNEL) = DMAC_DRSR_RS_SLCD;
86 REG_DMAC_DTAR(DMA_LCD_CHANNEL) = PHYSADDR(SLCD_FIFO); 93 REG_DMAC_DTAR(DMA_LCD_CHANNEL) = PHYSADDR(SLCD_FIFO);
87 REG_DMAC_DTCR(DMA_LCD_CHANNEL) = width*height; 94 REG_DMAC_DTCR(DMA_LCD_CHANNEL) = (width * height) >> 3;
88 95
89 REG_DMAC_DCMD(DMA_LCD_CHANNEL) = ( DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 96 REG_DMAC_DCMD(DMA_LCD_CHANNEL) = ( DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32
90 | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BIT ); 97 | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE );
91 98
92 __dcache_writeback_all(); /* Size of framebuffer is way bigger than cache size. 99 __dcache_writeback_all(); /* Size of framebuffer is way bigger than cache size.
93 We need to find a way to make the framebuffer uncached, so this statement can get removed. */ 100 We need to find a way to make the framebuffer uncached, so this statement can get removed. */
@@ -101,7 +108,6 @@ x=0;y=0;width=LCD_WIDTH;height=LCD_HEIGHT; /* HACK! */
101 wakeup_wait(&lcd_wkup, TIMEOUT_BLOCK); /* Sleeping in lcd_update() should be safe */ 108 wakeup_wait(&lcd_wkup, TIMEOUT_BLOCK); /* Sleeping in lcd_update() should be safe */
102 109
103 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */ 110 REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */
104
105 dma_disable(); 111 dma_disable();
106 112
107 while(REG_SLCD_STATE & SLCD_STATE_BUSY); 113 while(REG_SLCD_STATE & SLCD_STATE_BUSY);
@@ -139,17 +145,54 @@ void lcd_update(void)
139 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); 145 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
140} 146}
141 147
142/* TODO: use IPU */ 148/* (Mis)use LCD framebuffer as a temporary buffer */
143void lcd_blit_yuv(unsigned char * const src[3], 149void lcd_blit_yuv(unsigned char * const src[3],
144 int src_x, int src_y, int stride, 150 int src_x, int src_y, int stride,
145 int x, int y, int width, int height) 151 int x, int y, int width, int height)
146{ 152{
147 (void)src; 153 __dcache_writeback_all();
148 (void)src_x; 154
149 (void)src_y; 155 __cpm_start_ipu();
150 (void)stride; 156
151 (void)x; 157 IPU_STOP_IPU();
152 (void)y; 158 IPU_RESET_IPU()
153 (void)width; 159 IPU_CLEAR_END_FLAG();
154 (void)height; 160
161 IPU_DISABLE_RSIZE();
162 IPU_DISABLE_IRQ();
163
164 IPU_SET_INFMT(INFMT_YUV420);
165 IPU_SET_OUTFMT(OUTFMT_RGB565);
166
167 IPU_SET_IN_FM(width, height);
168 IPU_SET_Y_STRIDE(stride);
169 IPU_SET_UV_STRIDE(stride, stride);
170
171 IPU_SET_Y_ADDR((unsigned long)src[0]);
172 IPU_SET_U_ADDR((unsigned long)src[2]);
173 IPU_SET_V_ADDR((unsigned long)src[3]);
174 IPU_SET_OUT_ADDR(PHYSADDR((unsigned long)&lcd_framebuffer[y][x]));
175
176 IPU_SET_OUT_FM(width, height);
177 IPU_SET_OUT_STRIDE(stride);
178
179 IPU_SET_CSC_C0_COEF(YUV_CSC_C0);
180 IPU_SET_CSC_C1_COEF(YUV_CSC_C1);
181 IPU_SET_CSC_C2_COEF(YUV_CSC_C2);
182 IPU_SET_CSC_C2_COEF(YUV_CSC_C3);
183 IPU_SET_CSC_C4_COEF(YUV_CSC_C4);
184
185 IPU_RUN_IPU();
186
187 while(!(IPU_POLLING_END_FLAG()) && IPU_IS_ENABLED());
188
189 IPU_CLEAR_END_FLAG();
190 IPU_STOP_IPU();
191
192 //__cpm_stop_ipu();
193
194 __dcache_invalidate_all();
195
196 /* YUV speed is limited by LCD speed */
197 lcd_update_rect(x, y, width, height);
155} 198}