2 * Image blitting support using the 2D engine.
4 * Copyright (C) 2007 OpenMoko, Inc.
5 * Author: Chia-I Wu <olv@openmoko.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
31 int mydiv(int n
, int d
)
35 for (q
= 0; n
>= d
; n
-= d
)
41 int myrem(int n
, int d
)
43 for (; n
>= d
; n
-= d
);
48 static void blit_set_onfly_regs(struct glamo_dma_manager
*dma
)
64 onfly
.src_block_y
= 32;
65 onfly
.src_block_x
= 32;
66 onfly
.src_block_w
= 36;
67 onfly
.src_block_h
= 35;
68 onfly
.jpeg_out_y
= 32;
69 onfly
.jpeg_out_x
= 32;
70 onfly
.fifo_full_cnt
= onfly
.src_block_w
* 2 + 2;
71 onfly
.in_length
= onfly
.jpeg_out_x
+ 3;
72 onfly
.fifo_data_cnt
= (onfly
.src_block_w
* onfly
.src_block_h
) >> 1;
73 onfly
.in_height
= onfly
.jpeg_out_y
+ 2;
75 GLAMO_DMA_BEGIN(dma
, 10);
76 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_ONFLY_MODE1
, onfly
.src_block_y
<< 10 | onfly
.src_block_x
<< 2);
77 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_ONFLY_MODE2
, onfly
.src_block_h
<< 8 | onfly
.src_block_w
);
78 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_ONFLY_MODE3
, onfly
.jpeg_out_y
<< 8 | onfly
.jpeg_out_x
);
79 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_ONFLY_MODE4
, onfly
.fifo_full_cnt
<< 8 | onfly
.in_length
);
80 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_ONFLY_MODE5
, onfly
.fifo_data_cnt
<< 6 | onfly
.in_height
);
82 /* Smedia suggests these values */
83 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE1, 0x8080);
84 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE2, 0x2526);
85 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE3, 0x2020);
86 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE4, 0x5023);
87 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE5, 0xafe2);
89 /* another set of values they suggest */
90 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE1, 0x8080);
91 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE2, 0x2324);
92 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE3, 0x2020);
93 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE4, 0x4a23);
94 //GLAMO_DMA_OUT(dma, GLAMO_REG_ISP_ONFLY_MODE5, 0x9da2);
99 static void blit_set_weight_regs(struct glamo_dma_manager
*dma
)
106 GLAMO_DMA_BEGIN(dma
, 12);
107 GLAMO_DMA_BURST(dma
, GLAMO_REG_ISP_DEC_SCALEH_MATRIX
, 10);
108 GLAMO_DMA_OUT(dma
, left
, 0);
109 GLAMO_DMA_OUT(dma
, left
, 0);
110 GLAMO_DMA_OUT(dma
, left
, 0);
111 GLAMO_DMA_OUT(dma
, left
, 0);
112 GLAMO_DMA_OUT(dma
, left
, 0);
115 GLAMO_DMA_BEGIN(dma
, 12);
116 GLAMO_DMA_BURST(dma
, GLAMO_REG_ISP_DEC_SCALEV_MATRIX
, 10);
117 GLAMO_DMA_OUT(dma
, left
, 0);
118 GLAMO_DMA_OUT(dma
, left
, 0);
119 GLAMO_DMA_OUT(dma
, left
, 0);
120 GLAMO_DMA_OUT(dma
, left
, 0);
121 GLAMO_DMA_OUT(dma
, left
, 0);
125 struct glamo_blit_manager
*glamo_blit_new(struct glamo_dma_manager
*dma
,
126 enum glamo_blit_format format
)
128 struct glamo_blit_manager
*blit
;
132 blit
= malloc(sizeof(*blit
));
137 blit
->format
= format
;
139 glamo_hw_engine_enable(GLAMO_ENGINE_ISP
);
140 glamo_hw_engine_reset(GLAMO_ENGINE_ISP
);
142 switch (blit
->format
)
144 case GLAMO_BLIT_FORMAT_I420
:
145 en3
= GLAMO_ISP_EN3_PLANE_MODE
|
146 GLAMO_ISP_EN3_YUV_INPUT
|
147 GLAMO_ISP_EN3_YUV420
;
149 case GLAMO_BLIT_FORMAT_YV16
:
150 en3
= GLAMO_ISP_EN3_PLANE_MODE
|
151 GLAMO_ISP_EN3_YUV_INPUT
;
153 case GLAMO_BLIT_FORMAT_YUY2
:
154 en3
= GLAMO_ISP_EN3_YUV_INPUT
;
159 en3
|= GLAMO_ISP_EN3_SCALE_IMPROVE
;
161 GLAMO_DMA_BEGIN(dma
, 18);
164 * In 8.8 fixed point,
166 * R = Y + 1.402 (Cr-128)
167 * = Y + 0x0167 Cr - 0xb3
169 * G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
170 * = Y - 0x0058 Cb - 0x00b6 Cr + 0x89
172 * B = Y + 1.772 (Cb-128)
173 * = Y + 0x01c5 Cb - 0xe2
175 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_YUV2RGB_11
, 0x0167);
176 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_YUV2RGB_21
, 0x01c5);
177 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_YUV2RGB_32
, 0x00b6);
178 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_YUV2RGB_33
, 0x0058);
179 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_YUV2RGB_RG
, 0xb3 << 8 | 0x89);
180 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_YUV2RGB_B
, 0xe2);
182 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_EN3
, en3
);
184 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_DEC_EN
, GLAMO_ISP_PORT1_EN_OUTPUT
);
185 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT2_EN
, GLAMO_ISP_PORT2_EN_DECODE
);
189 blit_set_onfly_regs(dma
);
190 blit_set_weight_regs(dma
);
195 void glamo_blit_rotate(struct glamo_blit_manager
*blit
,
196 enum glamo_blit_rotation rot
)
203 case GLAMO_BLIT_ROTATION_0
:
204 en4
= GLAMO_ISP_ROT_MODE_0
;
206 case GLAMO_BLIT_ROTATION_90
:
207 en4
= GLAMO_ISP_ROT_MODE_90
;
209 case GLAMO_BLIT_ROTATION_270
:
210 en4
= GLAMO_ISP_ROT_MODE_270
;
212 case GLAMO_BLIT_ROTATION_180
:
213 en4
= GLAMO_ISP_ROT_MODE_180
;
215 case GLAMO_BLIT_ROTATION_MIRROR
:
216 en4
= GLAMO_ISP_ROT_MODE_MIRROR
;
218 case GLAMO_BLIT_ROTATION_FLIP
:
219 en4
= GLAMO_ISP_ROT_MODE_FLIP
;
225 GLAMO_DMA_BEGIN(blit
->dma
, 2);
226 GLAMO_DMA_OUT(blit
->dma
, GLAMO_REG_ISP_EN4
, en4
);
227 GLAMO_DMA_END(blit
->dma
);
230 void glamo_blit_destroy(struct glamo_blit_manager
*blit
)
232 glamo_hw_engine_reset(GLAMO_ENGINE_ISP
);
233 glamo_hw_engine_disable(GLAMO_ENGINE_ISP
);
238 void glamo_blit_wait(struct glamo_blit_manager
*blit
)
242 int val
= GLAMO_IN_REG(GLAMO_REG_ISP_STATUS
);
254 void glamo_blit_dump(struct glamo_blit_manager
*blit
)
256 glamo_hw_dump(GLAMO_REG_ISP_EN1
, ((GLAMO_REG_ISP_STATUS
- GLAMO_REG_ISP_EN1
) >> 1) + 1);
259 struct glamo_blit_image
*glamo_blit_new_image(struct glamo_blit_manager
*blit
,
260 const unsigned char *data
, int width
, int height
)
262 struct glamo_blit_image
*image
;
264 switch (blit
->format
)
266 case GLAMO_BLIT_FORMAT_I420
:
267 if (width
& 1 || height
& 1)
270 case GLAMO_BLIT_FORMAT_YV16
:
271 if (width
& 1 || height
& 1)
274 case GLAMO_BLIT_FORMAT_YUY2
:
278 image
= malloc(sizeof(*image
));
282 image
->format
= blit
->format
;
284 image
->width
= width
;
285 image
->height
= height
;
287 switch (image
->format
)
289 case GLAMO_BLIT_FORMAT_I420
:
290 image
->num_planes
= 3;
292 image
->pitches
[0] = width
;
293 image
->offsets
[0] = 0;
295 image
->pitches
[1] = width
>> 1;
296 image
->offsets
[1] = image
->offsets
[0] + image
->pitches
[0] * image
->height
;
298 image
->pitches
[2] = width
>> 1;
299 image
->offsets
[2] = image
->offsets
[1] + ((image
->pitches
[1] * image
->height
) >> 1);
301 case GLAMO_BLIT_FORMAT_YV16
:
302 image
->num_planes
= 3;
304 image
->pitches
[0] = width
;
305 image
->offsets
[0] = 0;
307 image
->pitches
[1] = width
>> 1;
308 image
->offsets
[1] = image
->offsets
[0] + image
->pitches
[0] * image
->height
;
310 image
->pitches
[2] = width
>> 1;
311 image
->offsets
[2] = image
->offsets
[1] + image
->pitches
[1] * image
->height
;
313 case GLAMO_BLIT_FORMAT_YUY2
:
314 image
->num_planes
= 1;
315 image
->pitches
[0] = width
* 2;
316 image
->offsets
[0] = 0;
323 void glamo_blit_destroy_image(struct glamo_blit_manager
*blit
, struct glamo_blit_image
*image
)
328 void glamo_blit_dump_image(struct glamo_blit_manager
*blit
, struct glamo_blit_image
*image
)
332 printf("dumping image\n"
339 (unsigned int) image
->data
,
344 for (i
= 0; i
< image
->num_planes
; i
++)
346 printf("pitches[%d] %d\n"
348 i
, image
->pitches
[i
],
349 i
, image
->offsets
[i
]);
353 static void blit_image_regs(struct glamo_dma_manager
*dma
, struct glamo_blit_image
*image
)
358 switch (image
->format
)
360 case GLAMO_BLIT_FORMAT_I420
:
361 case GLAMO_BLIT_FORMAT_YV16
:
362 GLAMO_DMA_BEGIN(dma
, 20);
364 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_PITCH_Y
, image
->pitches
[0]);
365 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_PITCH_UV
, image
->pitches
[1]);
367 offset
= (unsigned int) image
->data
+ image
->offsets
[0];
368 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_Y_ADDRL
, offset
& 0xffff);
369 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_Y_ADDRH
, (offset
>> 16) & 0x7f);
371 offset
= (unsigned int) image
->data
+ image
->offsets
[1];
372 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_U_ADDRL
, offset
& 0xffff);
373 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_U_ADDRH
, (offset
>> 16) & 0x7f);
375 offset
= (unsigned int) image
->data
+ image
->offsets
[2];
376 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_V_ADDRL
, offset
& 0xffff);
377 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_V_ADDRH
, (offset
>> 16) & 0x7f);
379 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_HEIGHT
, image
->height
);
380 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_WIDTH
, image
->width
);
384 case GLAMO_BLIT_FORMAT_YUY2
:
385 GLAMO_DMA_BEGIN(dma
, 10);
387 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_CAP_PITCH
, image
->pitches
[0]);
389 offset
= (unsigned int) image
->data
+ image
->offsets
[0];
390 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_CAP_0_ADDRL
, offset
& 0xffff);
391 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_CAP_0_ADDRH
, (offset
>> 16) & 0x7f);
393 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_CAP_HEIGHT
, image
->height
);
394 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_CAP_WIDTH
, image
->width
);
401 static void blit_port_regs(struct glamo_dma_manager
*dma
, struct glamo_blit_image
*image
,
402 int x
, int y
, int width
, int height
)
404 unsigned int offset
, scale
;
407 offset
= y
* glamo_pitch
+ x
* 2;
409 switch (image
->format
)
411 case GLAMO_BLIT_FORMAT_I420
:
412 case GLAMO_BLIT_FORMAT_YV16
:
413 GLAMO_DMA_BEGIN(dma
, 14);
415 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_DEC_PITCH
, glamo_pitch
);
417 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_DEC_0_ADDRL
, offset
& 0xffff);
418 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_DEC_0_ADDRH
, (offset
>> 16) & 0x7f);
420 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_DEC_WIDTH
, width
);
421 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_DEC_HEIGHT
, height
);
423 scale
= mydiv((image
->width
<< 11), width
);
424 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_SCALEH
, scale
);
426 scale
= mydiv((image
->height
<< 11), height
);
427 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_SCALEV
, scale
);
431 case GLAMO_BLIT_FORMAT_YUY2
:
432 GLAMO_DMA_BEGIN(dma
, 14);
434 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_CAP_PITCH
, glamo_pitch
);
436 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_CAP_0_ADDRL
, offset
& 0xffff);
437 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_CAP_0_ADDRH
, (offset
>> 16) & 0x7f);
439 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_CAP_WIDTH
, width
);
440 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_PORT1_CAP_HEIGHT
, height
);
442 scale
= mydiv((image
->width
<< 11), width
);
443 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_SCALEH
, scale
);
445 scale
= mydiv((image
->height
<< 11), height
);
446 GLAMO_DMA_OUT(dma
, GLAMO_REG_ISP_DEC_SCALEV
, scale
);
453 void glamo_blit_show_image(struct glamo_blit_manager
*blit
, struct glamo_blit_image
*image
,
454 int x
, int y
, int width
, int height
)
456 blit_image_regs(blit
->dma
, image
);
457 blit_port_regs(blit
->dma
, image
, x
, y
, width
, height
);
459 glamo_dma_flush(blit
->dma
);
460 glamo_dma_wait(blit
->dma
, GLAMO_DMA_WAIT_CMDQ
);
462 glamo_set_bit_mask(GLAMO_REG_ISP_EN1
, GLAMO_ISP_EN1_FIRE_ISP
, 0xffff);
463 glamo_set_bit_mask(GLAMO_REG_ISP_EN1
, GLAMO_ISP_EN1_FIRE_ISP
, 0);