vo_glamo: sub.h was moved to sub directory in c9026cb3210205b07e2e068467a18ee40f9259a3
[mplayer/glamo.git] / drivers / libglamo / blit.c
blobe0bb3849539ba037a15c20dafcf0347350214f39
1 /*
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,
20 * MA 02111-1307 USA
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "glamo.h"
27 #include "hw.h"
28 #include "dma.h"
29 #include "blit.h"
31 int mydiv(int n, int d)
33 int q;
35 for (q = 0; n >= d; n -= d)
36 q ++;
38 return q;
41 int myrem(int n, int d)
43 for (; n >= d; n -= d);
45 return n;
48 static void blit_set_onfly_regs(struct glamo_dma_manager *dma)
50 struct {
51 int src_block_x;
52 int src_block_y;
53 int src_block_w;
54 int src_block_h;
55 int jpeg_out_y;
56 int jpeg_out_x;
57 int fifo_full_cnt;
58 int in_length;
59 int fifo_data_cnt;
60 int in_height;
61 } onfly;
62 GLAMO_DMA_VARS;
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);
96 GLAMO_DMA_END(dma);
99 static void blit_set_weight_regs(struct glamo_dma_manager *dma)
101 int left = 1 << 14;
102 GLAMO_DMA_VARS;
104 /* nearest */
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);
113 GLAMO_DMA_END(dma);
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);
122 GLAMO_DMA_END(dma);
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;
129 int en3;
130 GLAMO_DMA_VARS;
132 blit = malloc(sizeof(*blit));
133 if (!blit)
134 return NULL;
136 blit->dma = dma;
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;
148 break;
149 case GLAMO_BLIT_FORMAT_YV16:
150 en3 = GLAMO_ISP_EN3_PLANE_MODE |
151 GLAMO_ISP_EN3_YUV_INPUT;
152 break;
153 case GLAMO_BLIT_FORMAT_YUY2:
154 en3 = GLAMO_ISP_EN3_YUV_INPUT;
155 break;
156 default:
157 return NULL;
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);
187 GLAMO_DMA_END(dma);
189 blit_set_onfly_regs(dma);
190 blit_set_weight_regs(dma);
192 return blit;
195 void glamo_blit_rotate(struct glamo_blit_manager *blit,
196 enum glamo_blit_rotation rot)
198 int en4;
199 GLAMO_DMA_VARS;
201 switch (rot)
203 case GLAMO_BLIT_ROTATION_0:
204 en4 = GLAMO_ISP_ROT_MODE_0;
205 break;
206 case GLAMO_BLIT_ROTATION_90:
207 en4 = GLAMO_ISP_ROT_MODE_90;
208 break;
209 case GLAMO_BLIT_ROTATION_270:
210 en4 = GLAMO_ISP_ROT_MODE_270;
211 break;
212 case GLAMO_BLIT_ROTATION_180:
213 en4 = GLAMO_ISP_ROT_MODE_180;
214 break;
215 case GLAMO_BLIT_ROTATION_MIRROR:
216 en4 = GLAMO_ISP_ROT_MODE_MIRROR;
217 break;
218 case GLAMO_BLIT_ROTATION_FLIP:
219 en4 = GLAMO_ISP_ROT_MODE_FLIP;
220 break;
221 default:
222 return;
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);
235 free(blit);
238 void glamo_blit_wait(struct glamo_blit_manager *blit)
240 while (1)
242 int val = GLAMO_IN_REG(GLAMO_REG_ISP_STATUS);
243 if (val & 0x1)
245 usleep(1 * 1000);
247 continue;
250 break;
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)
268 return NULL;
269 break;
270 case GLAMO_BLIT_FORMAT_YV16:
271 if (width & 1 || height & 1)
272 return NULL;
273 break;
274 case GLAMO_BLIT_FORMAT_YUY2:
275 break;
278 image = malloc(sizeof(*image));
279 if (!image)
280 return NULL;
282 image->format = blit->format;
283 image->data = data;
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);
300 break;
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;
312 break;
313 case GLAMO_BLIT_FORMAT_YUY2:
314 image->num_planes = 1;
315 image->pitches[0] = width * 2;
316 image->offsets[0] = 0;
317 break;
320 return image;
323 void glamo_blit_destroy_image(struct glamo_blit_manager *blit, struct glamo_blit_image *image)
325 free(image);
328 void glamo_blit_dump_image(struct glamo_blit_manager *blit, struct glamo_blit_image *image)
330 int i;
332 printf("dumping image\n"
333 "format 0x%x\n"
334 "data 0x%x\n"
335 "width %d\n"
336 "height %d\n"
337 "num_planes %d\n",
338 image->format,
339 (unsigned int) image->data,
340 image->width,
341 image->height,
342 image->num_planes);
344 for (i = 0; i < image->num_planes; i++)
346 printf("pitches[%d] %d\n"
347 "offsets[%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)
355 unsigned int offset;
356 GLAMO_DMA_VARS;
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);
382 GLAMO_DMA_END(dma);
383 break;
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);
396 GLAMO_DMA_END(dma);
397 break;
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;
405 GLAMO_DMA_VARS;
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);
429 GLAMO_DMA_END(dma);
430 break;
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);
448 GLAMO_DMA_END(dma);
449 break;
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);