summaryrefslogtreecommitdiff
path: root/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/iriver/h10/lcd-h10_5gb.c')
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10_5gb.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
index 4386e1670c..5e1ad9ce23 100644
--- a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
+++ b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c
@@ -118,6 +118,168 @@ void lcd_init_device(void)
118 118
119/*** update functions ***/ 119/*** update functions ***/
120 120
121#define CSUB_X 2
122#define CSUB_Y 2
123
124#define RYFAC (31*257)
125#define GYFAC (31*257)
126#define BYFAC (31*257)
127#define RVFAC 11170 /* 31 * 257 * 1.402 */
128#define GVFAC (-5690) /* 31 * 257 * -0.714136 */
129#define GUFAC (-2742) /* 31 * 257 * -0.344136 */
130#define BUFAC 14118 /* 31 * 257 * 1.772 */
131
132#define ROUNDOFFS (127*257)
133#define ROUNDOFFSG (63*257)
134
135/* Performance function to blit a YUV bitmap directly to the LCD */
136void lcd_blit_yuv(unsigned char * const src[3],
137 int src_x, int src_y, int stride,
138 int x, int y, int width, int height)
139{
140 int y0, x0, y1, x1;
141 int ymax;
142
143 width = (width + 1) & ~1;
144
145 /* calculate the drawing region */
146 x0 = x;
147 x1 = x + width - 1;
148 y0 = y;
149 y1 = y + height - 1;
150
151 /* max horiz << 8 | start horiz */
152 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (x1 << 8) | x0);
153
154 /* max vert << 8 | start vert */
155 lcd_write_reg(R_VERT_RAM_ADDR_POS, (y1 << 8) | y0);
156
157 /* start vert << 8 | start horiz */
158 lcd_write_reg(R_RAM_ADDR_SET, (y0 << 8) | x0);
159
160 /* start drawing */
161 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
162
163 ymax = y + height - 1 ;
164
165 const int stride_div_csub_x = stride/CSUB_X;
166
167 for (; y <= ymax ; y++)
168 {
169 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
170 const unsigned char *ysrc = src[0] + stride * src_y + src_x;
171
172 const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) +
173 (src_x/CSUB_X);
174
175 const unsigned char *usrc = src[1] + uvoffset;
176 const unsigned char *vsrc = src[2] + uvoffset;
177 const unsigned char *row_end = ysrc + width;
178
179 int y, u, v;
180 int red1, green1, blue1;
181 int red2, green2, blue2;
182 unsigned rbits, gbits, bbits;
183
184 int rc, gc, bc;
185
186 do
187 {
188 u = *usrc++ - 128;
189 v = *vsrc++ - 128;
190 rc = RVFAC * v + ROUNDOFFS;
191 gc = GVFAC * v + GUFAC * u + ROUNDOFFSG;
192 bc = BUFAC * u + ROUNDOFFS;
193
194 /* Pixel 1 */
195 y = *ysrc++;
196
197 red1 = RYFAC * y + rc;
198 green1 = GYFAC * y + gc;
199 blue1 = BYFAC * y + bc;
200
201 /* Pixel 2 */
202 y = *ysrc++;
203 red2 = RYFAC * y + rc;
204 green2 = GYFAC * y + gc;
205 blue2 = BYFAC * y + bc;
206
207 /* Since out of bounds errors are relatively rare, we check two
208 pixels at once to see if any components are out of bounds, and
209 then fix whichever is broken. This works due to high values and
210 negative values both becoming larger than the cutoff when
211 casted to unsigned. And ORing them together checks all of them
212 simultaneously. */
213 if (((unsigned)(red1 | green1 | blue1 |
214 red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) {
215 if (((unsigned)(red1 | green1 | blue1)) >
216 (RYFAC*255+ROUNDOFFS)) {
217 if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS))
218 {
219 if (red1 < 0)
220 red1 = 0;
221 else
222 red1 = (RYFAC*255+ROUNDOFFS);
223 }
224 if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG))
225 {
226 if (green1 < 0)
227 green1 = 0;
228 else
229 green1 = (GYFAC*255+ROUNDOFFSG);
230 }
231 if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS))
232 {
233 if (blue1 < 0)
234 blue1 = 0;
235 else
236 blue1 = (BYFAC*255+ROUNDOFFS);
237 }
238 }
239
240 if (((unsigned)(red2 | green2 | blue2)) >
241 (RYFAC*255+ROUNDOFFS)) {
242 if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS))
243 {
244 if (red2 < 0)
245 red2 = 0;
246 else
247 red2 = (RYFAC*255+ROUNDOFFS);
248 }
249 if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG))
250 {
251 if (green2 < 0)
252 green2 = 0;
253 else
254 green2 = (GYFAC*255+ROUNDOFFSG);
255 }
256 if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS))
257 {
258 if (blue2 < 0)
259 blue2 = 0;
260 else
261 blue2 = (BYFAC*255+ROUNDOFFS);
262 }
263 }
264 }
265
266 rbits = red1 >> 16 ;
267 gbits = green1 >> 15 ;
268 bbits = blue1 >> 16 ;
269 lcd_send_data((rbits << 11) | (gbits << 5) | bbits);
270
271 rbits = red2 >> 16 ;
272 gbits = green2 >> 15 ;
273 bbits = blue2 >> 16 ;
274 lcd_send_data((rbits << 11) | (gbits << 5) | bbits);
275 }
276 while (ysrc < row_end);
277
278 src_y++;
279 }
280}
281
282
121/* Update a fraction of the display. */ 283/* Update a fraction of the display. */
122void lcd_update_rect(int x0, int y0, int width, int height) 284void lcd_update_rect(int x0, int y0, int width, int height)
123{ 285{