Initial version of libomxil-e3250-v4l2
[platform/adaptation/ap_samsung/libomxil-e3250-v4l2.git] / exynos4 / libswconverter / swconvertor.c
1 /*
2  *
3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /*
19  * @file    swconvertor.c
20  *
21  * @brief   SEC_OMX specific define
22  *
23  * @author  ShinWon Lee (shinwon.lee@samsung.com)
24  *
25  * @version 1.0
26  *
27  * @history
28  *   2012.02.01 : Create
29  */
30
31 #include "stdio.h"
32 #include "stdlib.h"
33 #include "swconverter.h"
34
35 /*
36  * Get tiled address of position(x,y)
37  *
38  * @param x_size
39  *   width of tiled[in]
40  *
41  * @param y_size
42  *   height of tiled[in]
43  *
44  * @param x_pos
45  *   x position of tield[in]
46  *
47  * @param src_size
48  *   y position of tield[in]
49  *
50  * @return
51  *   address of tiled data
52  */
53 static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos)
54 {
55     int pixel_x_m1, pixel_y_m1;
56     int roundup_x, roundup_y;
57     int linear_addr0, linear_addr1, bank_addr ;
58     int x_addr;
59     int trans_addr;
60
61     pixel_x_m1 = x_size -1;
62     pixel_y_m1 = y_size -1;
63
64     roundup_x = ((pixel_x_m1 >> 7) + 1);
65     roundup_y = ((pixel_x_m1 >> 6) + 1);
66
67     x_addr = x_pos >> 2;
68
69     if ((y_size <= y_pos+32) && ( y_pos < y_size) &&
70         (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) {
71         linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf));
72         linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
73
74         if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
75             bank_addr = ((x_addr >> 4) & 0x1);
76         else
77             bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
78     } else {
79         linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
80         linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
81
82         if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
83             bank_addr = ((x_addr >> 4) & 0x1);
84         else
85             bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
86     }
87
88     linear_addr0 = linear_addr0 << 2;
89     trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0;
90
91     return trans_addr;
92 }
93
94 /*
95  * De-interleaves src to dest1, dest2
96  *
97  * @param dest1
98  *   Address of de-interleaved data[out]
99  *
100  * @param dest2
101  *   Address of de-interleaved data[out]
102  *
103  * @param src
104  *   Address of interleaved data[in]
105  *
106  * @param src_size
107  *   Size of interleaved data[in]
108  */
109 void csc_deinterleave_memcpy(
110     unsigned char *dest1,
111     unsigned char *dest2,
112     unsigned char *src,
113     unsigned int src_size)
114 {
115     unsigned int i = 0;
116     for(i=0; i<src_size/2; i++) {
117         dest1[i] = src[i*2];
118         dest2[i] = src[i*2+1];
119     }
120 }
121
122 /*
123  * Interleaves src1, src2 to dest
124  *
125  * @param dest
126  *   Address of interleaved data[out]
127  *
128  * @param src1
129  *   Address of de-interleaved data[in]
130  *
131  * @param src2
132  *   Address of de-interleaved data[in]
133  *
134  * @param src_size
135  *   Size of de-interleaved data[in]
136  */
137 void csc_interleave_memcpy(
138     unsigned char *dest,
139     unsigned char *src1,
140     unsigned char *src2,
141     unsigned int src_size)
142 {
143     unsigned int i = 0;
144     for(i=0; i<src_size; i++) {
145         dest[i * 2] = src1[i];
146         dest[i * 2 + 1] = src2[i];
147     }
148 }
149
150 /*
151  * Converts tiled data to linear
152  * Crops left, top, right, buttom
153  * 1. Y of NV12T to Y of YUV420P
154  * 2. Y of NV12T to Y of YUV420S
155  * 3. UV of NV12T to UV of YUV420S
156  *
157  * @param yuv420_dest
158  *   Y or UV plane address of YUV420[out]
159  *
160  * @param nv12t_src
161  *   Y or UV plane address of NV12T[in]
162  *
163  * @param yuv420_width
164  *   Width of YUV420[in]
165  *
166  * @param yuv420_height
167  *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
168  *
169  * @param left
170  *   Crop size of left
171  *
172  * @param top
173  *   Crop size of top
174  *
175  * @param right
176  *   Crop size of right
177  *
178  * @param buttom
179  *   Crop size of buttom
180  */
181 static void csc_tiled_to_linear_crop(
182     unsigned char *yuv420_dest,
183     unsigned char *nv12t_src,
184     unsigned int yuv420_width,
185     unsigned int yuv420_height,
186     unsigned int left,
187     unsigned int top,
188     unsigned int right,
189     unsigned int buttom)
190 {
191     unsigned int i, j;
192     unsigned int tiled_offset = 0, tiled_offset1 = 0;
193     unsigned int linear_offset = 0;
194     unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
195
196     temp3 = yuv420_width-right;
197     temp1 = temp3-left;
198     /* real width is greater than or equal 256 */
199     if (temp1 >= 256) {
200         for (i=top; i<yuv420_height-buttom; i=i+1) {
201             j = left;
202             temp3 = (j>>8)<<8;
203             temp3 = temp3>>6;
204             temp4 = i>>5;
205             if (temp4 & 0x1) {
206                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
207                 tiled_offset = temp4-1;
208                 temp1 = ((yuv420_width+127)>>7)<<7;
209                 tiled_offset = tiled_offset*(temp1>>6);
210                 tiled_offset = tiled_offset+temp3;
211                 tiled_offset = tiled_offset+2;
212                 temp1 = (temp3>>2)<<2;
213                 tiled_offset = tiled_offset+temp1;
214                 tiled_offset = tiled_offset<<11;
215                 tiled_offset1 = tiled_offset+2048*2;
216                 temp4 = 8;
217             } else {
218                 temp2 = ((yuv420_height+31)>>5)<<5;
219                 if ((i+32)<temp2) {
220                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
221                     temp1 = temp3+2;
222                     temp1 = (temp1>>2)<<2;
223                     tiled_offset = temp3+temp1;
224                     temp1 = ((yuv420_width+127)>>7)<<7;
225                     tiled_offset = tiled_offset+temp4*(temp1>>6);
226                     tiled_offset = tiled_offset<<11;
227                     tiled_offset1 = tiled_offset+2048*6;
228                     temp4 = 8;
229                 } else {
230                     /* even2 fomula: x+x_block_num*y */
231                     temp1 = ((yuv420_width+127)>>7)<<7;
232                     tiled_offset = temp4*(temp1>>6);
233                     tiled_offset = tiled_offset+temp3;
234                     tiled_offset = tiled_offset<<11;
235                     tiled_offset1 = tiled_offset+2048*2;
236                     temp4 = 4;
237                 }
238             }
239
240             temp1 = i&0x1F;
241             tiled_offset = tiled_offset+64*(temp1);
242             tiled_offset1 = tiled_offset1+64*(temp1);
243             temp2 = yuv420_width-left-right;
244             linear_offset = temp2*(i-top);
245             temp3 = ((j+256)>>8)<<8;
246             temp3 = temp3-j;
247             temp1 = left&0x3F;
248             if (temp3 > 192) {
249                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1);
250                 temp2 = ((left+63)>>6)<<6;
251                 temp3 = ((yuv420_width-right)>>6)<<6;
252                 if (temp2 == temp3) {
253                     temp2 = yuv420_width-right-(64-temp1);
254                 }
255                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64);
256                 memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64);
257                 memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64);
258                 linear_offset = linear_offset+256-temp1;
259             } else if (temp3 > 128) {
260                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1);
261                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64);
262                 memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64);
263                 linear_offset = linear_offset+192-temp1;
264             } else if (temp3 > 64) {
265                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1);
266                 memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64);
267                 linear_offset = linear_offset+128-temp1;
268             } else if (temp3 > 0) {
269                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1);
270                 linear_offset = linear_offset+64-temp1;
271             }
272
273             tiled_offset = tiled_offset+temp4*2048;
274             j = (left>>8)<<8;
275             j = j + 256;
276             temp2 = yuv420_width-right-256;
277             for (; j<=temp2; j=j+256) {
278                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
279                 tiled_offset1 = tiled_offset1+temp4*2048;
280                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
281                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
282                 tiled_offset = tiled_offset+temp4*2048;
283                 memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64);
284                 linear_offset = linear_offset+256;
285             }
286
287             tiled_offset1 = tiled_offset1+temp4*2048;
288             temp2 = yuv420_width-right-j;
289             if (temp2 > 192) {
290                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
291                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
292                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64);
293                 memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192);
294             } else if (temp2 > 128) {
295                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
296                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64);
297                 memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128);
298             } else if (temp2 > 64) {
299                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
300                 memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64);
301             } else {
302                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
303             }
304         }
305     } else if (temp1 >= 64) {
306         for (i=top; i<(yuv420_height-buttom); i=i+1) {
307             j = left;
308             tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
309             temp2 = ((j+64)>>6)<<6;
310             temp2 = temp2-j;
311             linear_offset = temp1*(i-top);
312             temp4 = j&0x3;
313             tiled_offset = tiled_offset+temp4;
314             memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
315             linear_offset = linear_offset+temp2;
316             j = j+temp2;
317             if ((j+64) <= temp3) {
318                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
319                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
320                 linear_offset = linear_offset+64;
321                 j = j+64;
322             }
323             if ((j+64) <= temp3) {
324                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
325                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64);
326                 linear_offset = linear_offset+64;
327                 j = j+64;
328             }
329             if (j < temp3) {
330                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
331                 temp2 = temp3-j;
332                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2);
333             }
334         }
335     } else {
336         for (i=top; i<(yuv420_height-buttom); i=i+1) {
337             linear_offset = temp1*(i-top);
338             for (j=left; j<(yuv420_width-right); j=j+2) {
339                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i);
340                 temp4 = j&0x3;
341                 tiled_offset = tiled_offset+temp4;
342                 memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2);
343                 linear_offset = linear_offset+2;
344             }
345         }
346     }
347 }
348
349 /*
350  * Converts and Deinterleaves tiled data to linear
351  * Crops left, top, right, buttom
352  * 1. UV of NV12T to UV of YUV420P
353  *
354  * @param yuv420_u_dest
355  *   U plane address of YUV420P[out]
356  *
357  * @param yuv420_v_dest
358  *   V plane address of YUV420P[out]
359  *
360  * @param nv12t_src
361  *   UV plane address of NV12T[in]
362  *
363  * @param yuv420_width
364  *   Width of YUV420[in]
365  *
366  * @param yuv420_uv_height
367  *   Height/2 of YUV420[in]
368  *
369  * @param left
370  *   Crop size of left
371  *
372  * @param top
373  *   Crop size of top
374  *
375  * @param right
376  *   Crop size of right
377  *
378  * @param buttom
379  *   Crop size of buttom
380  */
381 static void csc_tiled_to_linear_deinterleave_crop(
382     unsigned char *yuv420_u_dest,
383     unsigned char *yuv420_v_dest,
384     unsigned char *nv12t_uv_src,
385     unsigned int yuv420_width,
386     unsigned int yuv420_uv_height,
387     unsigned int left,
388     unsigned int top,
389     unsigned int right,
390     unsigned int buttom)
391 {
392     unsigned int i, j;
393     unsigned int tiled_offset = 0, tiled_offset1 = 0;
394     unsigned int linear_offset = 0;
395     unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
396
397     temp3 = yuv420_width-right;
398     temp1 = temp3-left;
399     /* real width is greater than or equal 256 */
400     if (temp1 >= 256) {
401         for (i=top; i<yuv420_uv_height-buttom; i=i+1) {
402             j = left;
403             temp3 = (j>>8)<<8;
404             temp3 = temp3>>6;
405             temp4 = i>>5;
406             if (temp4 & 0x1) {
407                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
408                 tiled_offset = temp4-1;
409                 temp1 = ((yuv420_width+127)>>7)<<7;
410                 tiled_offset = tiled_offset*(temp1>>6);
411                 tiled_offset = tiled_offset+temp3;
412                 tiled_offset = tiled_offset+2;
413                 temp1 = (temp3>>2)<<2;
414                 tiled_offset = tiled_offset+temp1;
415                 tiled_offset = tiled_offset<<11;
416                 tiled_offset1 = tiled_offset+2048*2;
417                 temp4 = 8;
418             } else {
419                 temp2 = ((yuv420_uv_height+31)>>5)<<5;
420                 if ((i+32)<temp2) {
421                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
422                     temp1 = temp3+2;
423                     temp1 = (temp1>>2)<<2;
424                     tiled_offset = temp3+temp1;
425                     temp1 = ((yuv420_width+127)>>7)<<7;
426                     tiled_offset = tiled_offset+temp4*(temp1>>6);
427                     tiled_offset = tiled_offset<<11;
428                     tiled_offset1 = tiled_offset+2048*6;
429                     temp4 = 8;
430                 } else {
431                     /* even2 fomula: x+x_block_num*y */
432                     temp1 = ((yuv420_width+127)>>7)<<7;
433                     tiled_offset = temp4*(temp1>>6);
434                     tiled_offset = tiled_offset+temp3;
435                     tiled_offset = tiled_offset<<11;
436                     tiled_offset1 = tiled_offset+2048*2;
437                     temp4 = 4;
438                 }
439             }
440
441             temp1 = i&0x1F;
442             tiled_offset = tiled_offset+64*(temp1);
443             tiled_offset1 = tiled_offset1+64*(temp1);
444             temp2 = yuv420_width-left-right;
445             linear_offset = temp2*(i-top)/2;
446             temp3 = ((j+256)>>8)<<8;
447             temp3 = temp3-j;
448             temp1 = left&0x3F;
449             if (temp3 > 192) {
450                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, yuv420_v_dest+linear_offset, nv12t_uv_src+tiled_offset+temp1, 64-temp1);
451                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2),
452                                         yuv420_v_dest+linear_offset+(32-temp1/2),
453                                         nv12t_uv_src+tiled_offset+2048, 64);
454                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2),
455                                         yuv420_v_dest+linear_offset+(64-temp1/2),
456                                         nv12t_uv_src+tiled_offset1, 64);
457                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(96-temp1/2),
458                                         yuv420_v_dest+linear_offset+(96-temp1/2),
459                                         nv12t_uv_src+tiled_offset1+2048, 64);
460                 linear_offset = linear_offset+128-temp1/2;
461             } else if (temp3 > 128) {
462                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
463                                         yuv420_v_dest+linear_offset,
464                                         nv12t_uv_src+tiled_offset+2048+temp1, 64-temp1);
465                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2),
466                                         yuv420_v_dest+linear_offset+(32-temp1/2),
467                                         nv12t_uv_src+tiled_offset1, 64);
468                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2),
469                                         yuv420_v_dest+linear_offset+(64-temp1/2),
470                                         nv12t_uv_src+tiled_offset1+2048, 64);
471                 linear_offset = linear_offset+96-temp1/2;
472             } else if (temp3 > 64) {
473                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
474                                         yuv420_v_dest+linear_offset,
475                                         nv12t_uv_src+tiled_offset1+temp1, 64-temp1);
476                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2),
477                                         yuv420_v_dest+linear_offset+(32-temp1/2),
478                                         nv12t_uv_src+tiled_offset1+2048, 64);
479                 linear_offset = linear_offset+64-temp1/2;
480             } else if (temp3 > 0) {
481                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
482                                         yuv420_v_dest+linear_offset,
483                                         nv12t_uv_src+tiled_offset1+2048+temp1, 64-temp1);
484                 linear_offset = linear_offset+32-temp1/2;
485             }
486
487             tiled_offset = tiled_offset+temp4*2048;
488             j = (left>>8)<<8;
489             j = j + 256;
490             temp2 = yuv420_width-right-256;
491             for (; j<=temp2; j=j+256) {
492                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
493                                         yuv420_v_dest+linear_offset,
494                                         nv12t_uv_src+tiled_offset, 64);
495                 tiled_offset1 = tiled_offset1+temp4*2048;
496                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
497                                         yuv420_v_dest+linear_offset+32,
498                                         nv12t_uv_src+tiled_offset+2048, 64);
499                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64,
500                                         yuv420_v_dest+linear_offset+64,
501                                         nv12t_uv_src+tiled_offset1, 64);
502                 tiled_offset = tiled_offset+temp4*2048;
503                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96,
504                                         yuv420_v_dest+linear_offset+96,
505                                         nv12t_uv_src+tiled_offset1+2048, 64);
506                 linear_offset = linear_offset+128;
507             }
508
509             tiled_offset1 = tiled_offset1+temp4*2048;
510             temp2 = yuv420_width-right-j;
511             if (temp2 > 192) {
512                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
513                                         yuv420_v_dest+linear_offset,
514                                         nv12t_uv_src+tiled_offset, 64);
515                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
516                                         yuv420_v_dest+linear_offset+32,
517                                         nv12t_uv_src+tiled_offset+2048, 64);
518                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64,
519                                         yuv420_v_dest+linear_offset+64,
520                                         nv12t_uv_src+tiled_offset1, 64);
521                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96,
522                                         yuv420_v_dest+linear_offset+96,
523                                         nv12t_uv_src+tiled_offset1+2048, temp2-192);
524             } else if (temp2 > 128) {
525                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
526                                         yuv420_v_dest+linear_offset,
527                                         nv12t_uv_src+tiled_offset, 64);
528                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
529                                         yuv420_v_dest+linear_offset+32,
530                                         nv12t_uv_src+tiled_offset+2048, 64);
531                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64,
532                                         yuv420_v_dest+linear_offset+64,
533                                         nv12t_uv_src+tiled_offset1, temp2-128);
534             } else if (temp2 > 64) {
535                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
536                                         yuv420_v_dest+linear_offset,
537                                         nv12t_uv_src+tiled_offset, 64);
538                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32,
539                                         yuv420_v_dest+linear_offset+32,
540                                         nv12t_uv_src+tiled_offset+2048, temp2-64);
541             } else {
542                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
543                                         yuv420_v_dest+linear_offset,
544                                         nv12t_uv_src+tiled_offset, temp2);
545             }
546         }
547     } else if (temp1 >= 64) {
548         for (i=top; i<(yuv420_uv_height-buttom); i=i+1) {
549             j = left;
550             tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
551             temp2 = ((j+64)>>6)<<6;
552             temp2 = temp2-j;
553             temp3 = yuv420_width-right;
554             temp4 = temp3-left;
555             linear_offset = temp4*(i-top)/2;
556             temp4 = j&0x3;
557             tiled_offset = tiled_offset+temp4;
558             csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
559                                     yuv420_v_dest+linear_offset,
560                                     nv12t_uv_src+tiled_offset, temp2);
561             linear_offset = linear_offset+temp2/2;
562             j = j+temp2;
563             if ((j+64) <= temp3) {
564                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
565                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
566                                         yuv420_v_dest+linear_offset,
567                                         nv12t_uv_src+tiled_offset, 64);
568                 linear_offset = linear_offset+32;
569                 j = j+64;
570             }
571             if ((j+64) <= temp3) {
572                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
573                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
574                                         yuv420_v_dest+linear_offset,
575                                         nv12t_uv_src+tiled_offset, 64);
576                 linear_offset = linear_offset+32;
577                 j = j+64;
578             }
579             if (j < temp3) {
580                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
581                 temp1 = temp3-j;
582                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
583                                         yuv420_v_dest+linear_offset,
584                                         nv12t_uv_src+tiled_offset, temp1);
585             }
586         }
587     } else {
588         for (i=top; i<(yuv420_uv_height-buttom); i=i+1) {
589             temp3 = yuv420_width-right;
590             temp4 = temp3-left;
591             linear_offset = temp4*(i-top)/2;
592             for (j=left; j<(yuv420_width-right); j=j+2) {
593                 tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i);
594                 temp3 = j&0x3;
595                 tiled_offset = tiled_offset+temp3;
596                 csc_deinterleave_memcpy(yuv420_u_dest+linear_offset,
597                                         yuv420_v_dest+linear_offset,
598                                         nv12t_uv_src+tiled_offset, 2);
599                 linear_offset = linear_offset+1;
600             }
601         }
602     }
603 }
604
605 /*
606  * Converts linear data to tiled
607  * Crops left, top, right, buttom
608  * 1. Y of YUV420P to Y of NV12T
609  * 2. Y of YUV420S to Y of NV12T
610  * 3. UV of YUV420S to UV of NV12T
611  *
612  * @param nv12t_dest
613  *   Y or UV plane address of NV12T[out]
614  *
615  * @param yuv420_src
616  *   Y or UV plane address of YUV420P(S)[in]
617  *
618  * @param yuv420_width
619  *   Width of YUV420[in]
620  *
621  * @param yuv420_height
622  *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
623  *
624  * @param left
625  *   Crop size of left
626  *
627  * @param top
628  *   Crop size of top
629  *
630  * @param right
631  *   Crop size of right
632  *
633  * @param buttom
634  *   Crop size of buttom
635  */
636 static void csc_linear_to_tiled_crop(
637     unsigned char *nv12t_dest,
638     unsigned char *yuv420_src,
639     unsigned int yuv420_width,
640     unsigned int yuv420_height,
641     unsigned int left,
642     unsigned int top,
643     unsigned int right,
644     unsigned int buttom)
645 {
646     unsigned int i, j;
647     unsigned int tiled_x_index = 0, tiled_y_index = 0;
648     unsigned int aligned_x_size = 0, aligned_y_size = 0;
649     unsigned int tiled_offset = 0;
650     unsigned int temp1 = 0, temp2 = 0;
651
652     aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5;
653     aligned_x_size = ((yuv420_width-left-right)>>6)<<6;
654
655     for (i=0; i<aligned_y_size; i=i+32) {
656         for (j=0; j<aligned_x_size; j=j+64) {
657             tiled_offset = 0;
658             tiled_x_index = j>>6;
659             tiled_y_index = i>>5;
660             if (tiled_y_index & 0x1) {
661                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
662                 tiled_offset = tiled_y_index-1;
663                 temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
664                 tiled_offset = tiled_offset*(temp1>>6);
665                 tiled_offset = tiled_offset+tiled_x_index;
666                 tiled_offset = tiled_offset+2;
667                 temp1 = (tiled_x_index>>2)<<2;
668                 tiled_offset = tiled_offset+temp1;
669                 tiled_offset = tiled_offset<<11;
670             } else {
671                 temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
672                 if ((i+32)<temp2) {
673                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
674                     temp1 = tiled_x_index+2;
675                     temp1 = (temp1>>2)<<2;
676                     tiled_offset = tiled_x_index+temp1;
677                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
678                     tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
679                     tiled_offset = tiled_offset<<11;
680                 } else {
681                     /* even2 fomula: x+x_block_num*y */
682                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
683                     tiled_offset = tiled_y_index*(temp1>>6);
684                     tiled_offset = tiled_offset+tiled_x_index;
685                     tiled_offset = tiled_offset<<11;
686                 }
687             }
688
689             memcpy(nv12t_dest+tiled_offset, yuv420_src+left+j+yuv420_width*(i+top), 64);
690             memcpy(nv12t_dest+tiled_offset+64*1, yuv420_src+left+j+yuv420_width*(i+top+1), 64);
691             memcpy(nv12t_dest+tiled_offset+64*2, yuv420_src+left+j+yuv420_width*(i+top+2), 64);
692             memcpy(nv12t_dest+tiled_offset+64*3, yuv420_src+left+j+yuv420_width*(i+top+3), 64);
693             memcpy(nv12t_dest+tiled_offset+64*4, yuv420_src+left+j+yuv420_width*(i+top+4), 64);
694             memcpy(nv12t_dest+tiled_offset+64*5, yuv420_src+left+j+yuv420_width*(i+top+5), 64);
695             memcpy(nv12t_dest+tiled_offset+64*6, yuv420_src+left+j+yuv420_width*(i+top+6), 64);
696             memcpy(nv12t_dest+tiled_offset+64*7, yuv420_src+left+j+yuv420_width*(i+top+7), 64);
697             memcpy(nv12t_dest+tiled_offset+64*8, yuv420_src+left+j+yuv420_width*(i+top+8), 64);
698             memcpy(nv12t_dest+tiled_offset+64*9, yuv420_src+left+j+yuv420_width*(i+top+9), 64);
699             memcpy(nv12t_dest+tiled_offset+64*10, yuv420_src+left+j+yuv420_width*(i+top+10), 64);
700             memcpy(nv12t_dest+tiled_offset+64*11, yuv420_src+left+j+yuv420_width*(i+top+11), 64);
701             memcpy(nv12t_dest+tiled_offset+64*12, yuv420_src+left+j+yuv420_width*(i+top+12), 64);
702             memcpy(nv12t_dest+tiled_offset+64*13, yuv420_src+left+j+yuv420_width*(i+top+13), 64);
703             memcpy(nv12t_dest+tiled_offset+64*14, yuv420_src+left+j+yuv420_width*(i+top+14), 64);
704             memcpy(nv12t_dest+tiled_offset+64*15, yuv420_src+left+j+yuv420_width*(i+top+15), 64);
705             memcpy(nv12t_dest+tiled_offset+64*16, yuv420_src+left+j+yuv420_width*(i+top+16), 64);
706             memcpy(nv12t_dest+tiled_offset+64*17, yuv420_src+left+j+yuv420_width*(i+top+17), 64);
707             memcpy(nv12t_dest+tiled_offset+64*18, yuv420_src+left+j+yuv420_width*(i+top+18), 64);
708             memcpy(nv12t_dest+tiled_offset+64*19, yuv420_src+left+j+yuv420_width*(i+top+19), 64);
709             memcpy(nv12t_dest+tiled_offset+64*20, yuv420_src+left+j+yuv420_width*(i+top+20), 64);
710             memcpy(nv12t_dest+tiled_offset+64*21, yuv420_src+left+j+yuv420_width*(i+top+21), 64);
711             memcpy(nv12t_dest+tiled_offset+64*22, yuv420_src+left+j+yuv420_width*(i+top+22), 64);
712             memcpy(nv12t_dest+tiled_offset+64*23, yuv420_src+left+j+yuv420_width*(i+top+23), 64);
713             memcpy(nv12t_dest+tiled_offset+64*24, yuv420_src+left+j+yuv420_width*(i+top+24), 64);
714             memcpy(nv12t_dest+tiled_offset+64*25, yuv420_src+left+j+yuv420_width*(i+top+25), 64);
715             memcpy(nv12t_dest+tiled_offset+64*26, yuv420_src+left+j+yuv420_width*(i+top+26), 64);
716             memcpy(nv12t_dest+tiled_offset+64*27, yuv420_src+left+j+yuv420_width*(i+top+27), 64);
717             memcpy(nv12t_dest+tiled_offset+64*28, yuv420_src+left+j+yuv420_width*(i+top+28), 64);
718             memcpy(nv12t_dest+tiled_offset+64*29, yuv420_src+left+j+yuv420_width*(i+top+29), 64);
719             memcpy(nv12t_dest+tiled_offset+64*30, yuv420_src+left+j+yuv420_width*(i+top+30), 64);
720             memcpy(nv12t_dest+tiled_offset+64*31, yuv420_src+left+j+yuv420_width*(i+top+31), 64);
721         }
722     }
723
724     for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+2) {
725         for (j=0; j<aligned_x_size; j=j+64) {
726             tiled_offset = 0;
727             tiled_x_index = j>>6;
728             tiled_y_index = i>>5;
729             if (tiled_y_index & 0x1) {
730                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
731                 tiled_offset = tiled_y_index-1;
732                 temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
733                 tiled_offset = tiled_offset*(temp1>>6);
734                 tiled_offset = tiled_offset+tiled_x_index;
735                 tiled_offset = tiled_offset+2;
736                 temp1 = (tiled_x_index>>2)<<2;
737                 tiled_offset = tiled_offset+temp1;
738                 tiled_offset = tiled_offset<<11;
739             } else {
740                 temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
741                 if ((i+32)<temp2) {
742                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
743                     temp1 = tiled_x_index+2;
744                     temp1 = (temp1>>2)<<2;
745                     tiled_offset = tiled_x_index+temp1;
746                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
747                     tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
748                     tiled_offset = tiled_offset<<11;
749                 } else {
750                     /* even2 fomula: x+x_block_num*y */
751                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
752                     tiled_offset = tiled_y_index*(temp1>>6);
753                     tiled_offset = tiled_offset+tiled_x_index;
754                     tiled_offset = tiled_offset<<11;
755                 }
756             }
757
758             temp1 = i&0x1F;
759             memcpy(nv12t_dest+tiled_offset+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 64);
760             memcpy(nv12t_dest+tiled_offset+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 64);
761         }
762     }
763
764     for (i=0; i<(yuv420_height-top-buttom); i=i+2) {
765         for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) {
766             tiled_offset = 0;
767             tiled_x_index = j>>6;
768             tiled_y_index = i>>5;
769             if (tiled_y_index & 0x1) {
770                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
771                 tiled_offset = tiled_y_index-1;
772                 temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
773                 tiled_offset = tiled_offset*(temp1>>6);
774                 tiled_offset = tiled_offset+tiled_x_index;
775                 tiled_offset = tiled_offset+2;
776                 temp1 = (tiled_x_index>>2)<<2;
777                 tiled_offset = tiled_offset+temp1;
778                 tiled_offset = tiled_offset<<11;
779             } else {
780                 temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
781                 if ((i+32)<temp2) {
782                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
783                     temp1 = tiled_x_index+2;
784                     temp1 = (temp1>>2)<<2;
785                     tiled_offset = tiled_x_index+temp1;
786                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
787                     tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
788                     tiled_offset = tiled_offset<<11;
789                 } else {
790                     /* even2 fomula: x+x_block_num*y */
791                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
792                     tiled_offset = tiled_y_index*(temp1>>6);
793                     tiled_offset = tiled_offset+tiled_x_index;
794                     tiled_offset = tiled_offset<<11;
795                 }
796             }
797
798             temp1 = i&0x1F;
799             temp2 = j&0x3F;
800             memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 2);
801             memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 2);
802         }
803     }
804
805 }
806
807 /*
808  * Converts and Interleaves linear to tiled
809  * Crops left, top, right, buttom
810  * 1. UV of YUV420P to UV of NV12T
811  *
812  * @param nv12t_uv_dest
813  *   UV plane address of NV12T[out]
814  *
815  * @param yuv420p_u_src
816  *   U plane address of YUV420P[in]
817  *
818  * @param yuv420p_v_src
819  *   V plane address of YUV420P[in]
820  *
821  * @param yuv420_width
822  *   Width of YUV420[in]
823  *
824  * @param yuv420_uv_height
825  *   Height/2 of YUV420[in]
826  *
827  * @param left
828  *   Crop size of left
829  *
830  * @param top
831  *   Crop size of top
832  *
833  * @param right
834  *   Crop size of right
835  *
836  * @param buttom
837  *   Crop size of buttom
838  */
839 static void csc_linear_to_tiled_interleave_crop(
840     unsigned char *nv12t_uv_dest,
841     unsigned char *yuv420_u_src,
842     unsigned char *yuv420_v_src,
843     unsigned int yuv420_width,
844     unsigned int yuv420_height,
845     unsigned int left,
846     unsigned int top,
847     unsigned int right,
848     unsigned int buttom)
849 {
850     unsigned int i, j;
851     unsigned int tiled_x_index = 0, tiled_y_index = 0;
852     unsigned int aligned_x_size = 0, aligned_y_size = 0;
853     unsigned int tiled_offset = 0;
854     unsigned int temp1 = 0, temp2 = 0;
855
856     aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5;
857     aligned_x_size = ((yuv420_width-left-right)>>6)<<6;
858
859     for (i=0; i<aligned_y_size; i=i+32) {
860         for (j=0; j<aligned_x_size; j=j+64) {
861             tiled_offset = 0;
862             tiled_x_index = j>>6;
863             tiled_y_index = i>>5;
864             if (tiled_y_index & 0x1) {
865                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
866                 tiled_offset = tiled_y_index-1;
867                 temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
868                 tiled_offset = tiled_offset*(temp1>>6);
869                 tiled_offset = tiled_offset+tiled_x_index;
870                 tiled_offset = tiled_offset+2;
871                 temp1 = (tiled_x_index>>2)<<2;
872                 tiled_offset = tiled_offset+temp1;
873                 tiled_offset = tiled_offset<<11;
874             } else {
875                 temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
876                 if ((i+32)<temp2) {
877                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
878                     temp1 = tiled_x_index+2;
879                     temp1 = (temp1>>2)<<2;
880                     tiled_offset = tiled_x_index+temp1;
881                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
882                     tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
883                     tiled_offset = tiled_offset<<11;
884                 } else {
885                     /* even2 fomula: x+x_block_num*y */
886                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
887                     tiled_offset = tiled_y_index*(temp1>>6);
888                     tiled_offset = tiled_offset+tiled_x_index;
889                     tiled_offset = tiled_offset<<11;
890                 }
891             }
892
893             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset,
894                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top),
895                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32);
896             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*1,
897                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+1),
898                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+1), 32);
899             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*2,
900                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+2),
901                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+2), 32);
902             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*3,
903                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+3),
904                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+3), 32);
905             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*4,
906                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+4),
907                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+4), 32);
908             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*5,
909                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+5),
910                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+5), 32);
911             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*6,
912                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+6),
913                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+6), 32);
914             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*7,
915                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+7),
916                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+7), 32);
917             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*8,
918                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+8),
919                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+8), 32);
920             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*9,
921                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+9),
922                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+9), 32);
923             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*10,
924                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+10),
925                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+10), 32);
926             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*11,
927                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+11),
928                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+11), 32);
929             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*12,
930                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+12),
931                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+12), 32);
932             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*13,
933                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+13),
934                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+13), 32);
935             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*14,
936                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+14),
937                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+14), 32);
938             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*15,
939                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+15),
940                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+15), 32);
941             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*16,
942                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+16),
943                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+16), 32);
944             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*17,
945                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+17),
946                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+17), 32);
947             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*18,
948                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+18),
949                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+18), 32);
950             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*19,
951                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+19),
952                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+19), 32);
953             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*20,
954                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+20),
955                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+20), 32);
956             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*21,
957                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+21),
958                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+21), 32);
959             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*22,
960                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+22),
961                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+22), 32);
962             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*23,
963                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+23),
964                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+23), 32);
965             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*24,
966                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+24),
967                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+24), 32);
968             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*25,
969                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+25),
970                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+25), 32);
971             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*26,
972                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+26),
973                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+26), 32);
974             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*27,
975                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+27),
976                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+27), 32);
977             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*28,
978                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+28),
979                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+28), 32);
980             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*29,
981                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+29),
982                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+29), 32);
983             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*30,
984                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+30),
985                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+30), 32);
986             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*31,
987                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+31),
988                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+31), 32);
989
990         }
991     }
992
993     for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+1) {
994         for (j=0; j<aligned_x_size; j=j+64) {
995             tiled_offset = 0;
996             tiled_x_index = j>>6;
997             tiled_y_index = i>>5;
998             if (tiled_y_index & 0x1) {
999                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
1000                 tiled_offset = tiled_y_index-1;
1001                 temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
1002                 tiled_offset = tiled_offset*(temp1>>6);
1003                 tiled_offset = tiled_offset+tiled_x_index;
1004                 tiled_offset = tiled_offset+2;
1005                 temp1 = (tiled_x_index>>2)<<2;
1006                 tiled_offset = tiled_offset+temp1;
1007                 tiled_offset = tiled_offset<<11;
1008             } else {
1009                 temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
1010                 if ((i+32)<temp2) {
1011                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
1012                     temp1 = tiled_x_index+2;
1013                     temp1 = (temp1>>2)<<2;
1014                     tiled_offset = tiled_x_index+temp1;
1015                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
1016                     tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
1017                     tiled_offset = tiled_offset<<11;
1018                 } else {
1019                     /* even2 fomula: x+x_block_num*y */
1020                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
1021                     tiled_offset = tiled_y_index*(temp1>>6);
1022                     tiled_offset = tiled_offset+tiled_x_index;
1023                     tiled_offset = tiled_offset<<11;
1024                 }
1025             }
1026             temp1 = i&0x1F;
1027             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1),
1028                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top),
1029                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32);
1030        }
1031     }
1032
1033     for (i=0; i<(yuv420_height-top-buttom); i=i+1) {
1034         for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) {
1035             tiled_offset = 0;
1036             tiled_x_index = j>>6;
1037             tiled_y_index = i>>5;
1038             if (tiled_y_index & 0x1) {
1039                 /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */
1040                 tiled_offset = tiled_y_index-1;
1041                 temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
1042                 tiled_offset = tiled_offset*(temp1>>6);
1043                 tiled_offset = tiled_offset+tiled_x_index;
1044                 tiled_offset = tiled_offset+2;
1045                 temp1 = (tiled_x_index>>2)<<2;
1046                 tiled_offset = tiled_offset+temp1;
1047                 tiled_offset = tiled_offset<<11;
1048             } else {
1049                 temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5;
1050                 if ((i+32)<temp2) {
1051                     /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */
1052                     temp1 = tiled_x_index+2;
1053                     temp1 = (temp1>>2)<<2;
1054                     tiled_offset = tiled_x_index+temp1;
1055                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
1056                     tiled_offset = tiled_offset+tiled_y_index*(temp1>>6);
1057                     tiled_offset = tiled_offset<<11;
1058                 } else {
1059                     /* even2 fomula: x+x_block_num*y */
1060                     temp1 = (((yuv420_width-left-right)+127)>>7)<<7;
1061                     tiled_offset = tiled_y_index*(temp1>>6);
1062                     tiled_offset = tiled_offset+tiled_x_index;
1063                     tiled_offset = tiled_offset<<11;
1064                 }
1065             }
1066             temp1 = i&0x1F;
1067             temp2 = j&0x3F;
1068             csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1),
1069                                     yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top),
1070                                     yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 1);
1071        }
1072     }
1073
1074 }
1075
1076
1077 /*
1078  * Converts tiled data to linear
1079  * Crops left, top, right, buttom
1080  * 1. Y of NV12T to Y of YUV420P
1081  * 2. Y of NV12T to Y of YUV420S
1082  * 3. UV of NV12T to UV of YUV420S
1083  *
1084  * @param yuv420_dest
1085  *   Y or UV plane address of YUV420[out]
1086  *
1087  * @param nv12t_src
1088  *   Y or UV plane address of NV12T[in]
1089  *
1090  * @param yuv420_width
1091  *   Width of YUV420[in]
1092  *
1093  * @param yuv420_height
1094  *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
1095  *
1096  * @param left
1097  *   Crop size of left
1098  *
1099  * @param top
1100  *   Crop size of top
1101  *
1102  * @param right
1103  *   Crop size of right
1104  *
1105  * @param buttom
1106  *   Crop size of buttom
1107  */
1108 void csc_tiled_to_linear_crop_neon(
1109     unsigned char *yuv420_dest,
1110     unsigned char *nv12t_src,
1111     unsigned int yuv420_width,
1112     unsigned int yuv420_height,
1113     unsigned int left,
1114     unsigned int top,
1115     unsigned int right,
1116     unsigned int buttom);
1117
1118 /*
1119  * Converts and Deinterleaves tiled data to linear
1120  * Crops left, top, right, buttom
1121  * 1. UV of NV12T to UV of YUV420P
1122  *
1123  * @param yuv420_u_dest
1124  *   U plane address of YUV420P[out]
1125  *
1126  * @param yuv420_v_dest
1127  *   V plane address of YUV420P[out]
1128  *
1129  * @param nv12t_src
1130  *   UV plane address of NV12T[in]
1131  *
1132  * @param yuv420_width
1133  *   Width of YUV420[in]
1134  *
1135  * @param yuv420_uv_height
1136  *   Height/2 of YUV420[in]
1137  *
1138  * @param left
1139  *   Crop size of left
1140  *
1141  * @param top
1142  *   Crop size of top
1143  *
1144  * @param right
1145  *   Crop size of right
1146  *
1147  * @param buttom
1148  *   Crop size of buttom
1149  */
1150 void csc_tiled_to_linear_deinterleave_crop_neon(
1151     unsigned char *yuv420_u_dest,
1152     unsigned char *yuv420_v_dest,
1153     unsigned char *nv12t_uv_src,
1154     unsigned int yuv420_width,
1155     unsigned int yuv420_uv_height,
1156     unsigned int left,
1157     unsigned int top,
1158     unsigned int right,
1159     unsigned int buttom);
1160
1161 /*
1162  * Converts linear data to tiled
1163  * Crops left, top, right, buttom
1164  * 1. Y of YUV420P to Y of NV12T
1165  * 2. Y of YUV420S to Y of NV12T
1166  * 3. UV of YUV420S to UV of NV12T
1167  *
1168  * @param nv12t_dest
1169  *   Y or UV plane address of NV12T[out]
1170  *
1171  * @param yuv420_src
1172  *   Y or UV plane address of YUV420P(S)[in]
1173  *
1174  * @param yuv420_width
1175  *   Width of YUV420[in]
1176  *
1177  * @param yuv420_height
1178  *   Y: Height of YUV420, UV: Height/2 of YUV420[in]
1179  *
1180  * @param left
1181  *   Crop size of left
1182  *
1183  * @param top
1184  *   Crop size of top
1185  *
1186  * @param right
1187  *   Crop size of right
1188  *
1189  * @param buttom
1190  *   Crop size of buttom
1191  */
1192 void csc_linear_to_tiled_crop_neon(
1193     unsigned char *nv12t_dest,
1194     unsigned char *yuv420_src,
1195     unsigned int yuv420_width,
1196     unsigned int yuv420_height,
1197     unsigned int left,
1198     unsigned int top,
1199     unsigned int right,
1200     unsigned int buttom);
1201
1202 /*
1203  * Converts and Interleaves linear to tiled
1204  * Crops left, top, right, buttom
1205  * 1. UV of YUV420P to UV of NV12T
1206  *
1207  * @param nv12t_uv_dest
1208  *   UV plane address of NV12T[out]
1209  *
1210  * @param yuv420p_u_src
1211  *   U plane address of YUV420P[in]
1212  *
1213  * @param yuv420p_v_src
1214  *   V plane address of YUV420P[in]
1215  *
1216  * @param yuv420_width
1217  *   Width of YUV420[in]
1218  *
1219  * @param yuv420_uv_height
1220  *   Height/2 of YUV420[in]
1221  *
1222  * @param left
1223  *   Crop size of left
1224  *
1225  * @param top
1226  *   Crop size of top
1227  *
1228  * @param right
1229  *   Crop size of right
1230  *
1231  * @param buttom
1232  *   Crop size of buttom
1233  */
1234 void csc_linear_to_tiled_interleave_crop_neon(
1235     unsigned char *nv12t_uv_dest,
1236     unsigned char *yuv420_u_src,
1237     unsigned char *yuv420_v_src,
1238     unsigned int yuv420_width,
1239     unsigned int yuv420_height,
1240     unsigned int left,
1241     unsigned int top,
1242     unsigned int right,
1243     unsigned int buttom);
1244
1245 /*
1246  * Converts tiled data to linear.
1247  * 1. y of nv12t to y of yuv420p
1248  * 2. y of nv12t to y of yuv420s
1249  *
1250  * @param dst
1251  *   y address of yuv420[out]
1252  *
1253  * @param src
1254  *   y address of nv12t[in]
1255  *
1256  * @param yuv420_width
1257  *   real width of yuv420[in]
1258  *   it should be even
1259  *
1260  * @param yuv420_height
1261  *   real height of yuv420[in]
1262  *   it should be even.
1263  *
1264  */
1265 void csc_tiled_to_linear_y(
1266     unsigned char *y_dst,
1267     unsigned char *y_src,
1268     unsigned int width,
1269     unsigned int height)
1270 {
1271     csc_tiled_to_linear_crop(y_dst, y_src, width, height, 0, 0, 0, 0);
1272 }
1273
1274 /*
1275  * Converts tiled data to linear
1276  * 1. uv of nv12t to y of yuv420s
1277  *
1278  * @param dst
1279  *   uv address of yuv420s[out]
1280  *
1281  * @param src
1282  *   uv address of nv12t[in]
1283  *
1284  * @param yuv420_width
1285  *   real width of yuv420s[in]
1286  *
1287  * @param yuv420_height
1288  *   real height of yuv420s[in]
1289  *
1290  */
1291 void csc_tiled_to_linear_uv(
1292     unsigned char *uv_dst,
1293     unsigned char *uv_src,
1294     unsigned int width,
1295     unsigned int height)
1296 {
1297     csc_tiled_to_linear_crop(uv_dst, uv_src, width, height, 0, 0, 0, 0);
1298 }
1299
1300 /*
1301  * Converts tiled data to linear
1302  * 1. uv of nt12t to uv of yuv420p
1303  *
1304  * @param u_dst
1305  *   u address of yuv420p[out]
1306  *
1307  * @param v_dst
1308  *   v address of yuv420p[out]
1309  *
1310  * @param uv_src
1311  *   uv address of nt12t[in]
1312  *
1313  * @param yuv420_width
1314  *   real width of yuv420p[in]
1315  *
1316  * @param yuv420_height
1317  *   real height of yuv420p[in]
1318  */
1319 void csc_tiled_to_linear_uv_deinterleave(
1320     unsigned char *u_dst,
1321     unsigned char *v_dst,
1322     unsigned char *uv_src,
1323     unsigned int width,
1324     unsigned int height)
1325 {
1326     csc_tiled_to_linear_deinterleave_crop(u_dst, v_dst, uv_src, width, height,
1327                                           0, 0, 0, 0);
1328 }
1329
1330 /*
1331  * Converts linear data to tiled
1332  * 1. y of yuv420 to y of nv12t
1333  *
1334  * @param dst
1335  *   y address of nv12t[out]
1336  *
1337  * @param src
1338  *   y address of yuv420[in]
1339  *
1340  * @param yuv420_width
1341  *   real width of yuv420[in]
1342  *   it should be even
1343  *
1344  * @param yuv420_height
1345  *   real height of yuv420[in]
1346  *   it should be even.
1347  *
1348  */
1349 void csc_linear_to_tiled_y(
1350     unsigned char *y_dst,
1351     unsigned char *y_src,
1352     unsigned int width,
1353     unsigned int height)
1354 {
1355     csc_linear_to_tiled_crop(y_dst, y_src, width, height, 0, 0, 0, 0);
1356 }
1357
1358 /*
1359  * Converts and interleaves linear data to tiled
1360  * 1. uv of nv12t to uv of yuv420
1361  *
1362  * @param dst
1363  *   uv address of nv12t[out]
1364  *
1365  * @param src
1366  *   u address of yuv420[in]
1367  *
1368  * @param src
1369  *   v address of yuv420[in]
1370  *
1371  * @param yuv420_width
1372  *   real width of yuv420[in]
1373  *
1374  * @param yuv420_height
1375  *   real height of yuv420[in]
1376  *
1377  */
1378 void csc_linear_to_tiled_uv(
1379     unsigned char *uv_dst,
1380     unsigned char *u_src,
1381     unsigned char *v_src,
1382     unsigned int width,
1383     unsigned int height)
1384 {
1385     csc_linear_to_tiled_interleave_crop(uv_dst, u_src, v_src, width, height,
1386                                         0, 0, 0, 0);
1387 }
1388
1389 /*
1390  * Converts tiled data to linear for mfc 6.x
1391  * 1. Y of NV12T to Y of YUV420P
1392  * 2. Y of NV12T to Y of YUV420S
1393  *
1394  * @param dst
1395  *   Y address of YUV420[out]
1396  *
1397  * @param src
1398  *   Y address of NV12T[in]
1399  *
1400  * @param yuv420_width
1401  *   real width of YUV420[in]
1402  *
1403  * @param yuv420_height
1404  *   Y: real height of YUV420[in]
1405  *
1406  */
1407 void csc_tiled_to_linear_y_neon(
1408     unsigned char *y_dst,
1409     unsigned char *y_src,
1410     unsigned int width,
1411     unsigned int height)
1412 {
1413     csc_tiled_to_linear_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0);
1414 }
1415
1416 /*
1417  * Converts tiled data to linear for mfc 6.x
1418  * 1. UV of NV12T to Y of YUV420S
1419  *
1420  * @param u_dst
1421  *   UV plane address of YUV420P[out]
1422  *
1423  * @param nv12t_src
1424  *   Y or UV plane address of NV12T[in]
1425  *
1426  * @param yuv420_width
1427  *   real width of YUV420[in]
1428  *
1429  * @param yuv420_height
1430  *   (real height)/2 of YUV420[in]
1431  */
1432 void csc_tiled_to_linear_uv_neon(
1433     unsigned char *uv_dst,
1434     unsigned char *uv_src,
1435     unsigned int width,
1436     unsigned int height)
1437 {
1438     csc_tiled_to_linear_crop_neon(uv_dst, uv_src, width, height, 0, 0, 0, 0);
1439 }
1440
1441 /*
1442  * Converts tiled data to linear for mfc 6.x
1443  * Deinterleave src to u_dst, v_dst
1444  * 1. UV of NV12T to Y of YUV420P
1445  *
1446  * @param u_dst
1447  *   U plane address of YUV420P[out]
1448  *
1449  * @param v_dst
1450  *   V plane address of YUV420P[out]
1451  *
1452  * @param nv12t_src
1453  *   Y or UV plane address of NV12T[in]
1454  *
1455  * @param yuv420_width
1456  *   real width of YUV420[in]
1457  *
1458  * @param yuv420_height
1459  *   (real height)/2 of YUV420[in]
1460  */
1461 void csc_tiled_to_linear_uv_deinterleave_neon(
1462     unsigned char *u_dst,
1463     unsigned char *v_dst,
1464     unsigned char *uv_src,
1465     unsigned int width,
1466     unsigned int height)
1467 {
1468     csc_tiled_to_linear_deinterleave_crop_neon(u_dst, v_dst, uv_src, width, height,
1469                                           0, 0, 0, 0);
1470 }
1471
1472 /*
1473  * Converts linear data to tiled
1474  * 1. y of yuv420 to y of nv12t
1475  *
1476  * @param dst
1477  *   y address of nv12t[out]
1478  *
1479  * @param src
1480  *   y address of yuv420[in]
1481  *
1482  * @param yuv420_width
1483  *   real width of yuv420[in]
1484  *   it should be even
1485  *
1486  * @param yuv420_height
1487  *   real height of yuv420[in]
1488  *   it should be even.
1489  *
1490  */
1491 void csc_linear_to_tiled_y_neon(
1492     unsigned char *y_dst,
1493     unsigned char *y_src,
1494     unsigned int width,
1495     unsigned int height)
1496 {
1497     csc_linear_to_tiled_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0);
1498 }
1499
1500 /*
1501  * Converts and interleaves linear data to tiled
1502  * 1. uv of nv12t to uv of yuv420
1503  *
1504  * @param dst
1505  *   uv address of nv12t[out]
1506  *
1507  * @param src
1508  *   u address of yuv420[in]
1509  *
1510  * @param src
1511  *   v address of yuv420[in]
1512  *
1513  * @param yuv420_width
1514  *   real width of yuv420[in]
1515  *
1516  * @param yuv420_height
1517  *   real height of yuv420[in]
1518  *
1519  */
1520 void csc_linear_to_tiled_uv_neon(
1521     unsigned char *uv_dst,
1522     unsigned char *u_src,
1523     unsigned char *v_src,
1524     unsigned int width,
1525     unsigned int height)
1526 {
1527     csc_linear_to_tiled_interleave_crop_neon(uv_dst, u_src, v_src,
1528                                              width, height, 0, 0, 0, 0);
1529 }
1530
1531 /*
1532  * Converts RGB565 to YUV420P
1533  *
1534  * @param y_dst
1535  *   Y plane address of YUV420P[out]
1536  *
1537  * @param u_dst
1538  *   U plane address of YUV420P[out]
1539  *
1540  * @param v_dst
1541  *   V plane address of YUV420P[out]
1542  *
1543  * @param rgb_src
1544  *   Address of RGB565[in]
1545  *
1546  * @param width
1547  *   Width of RGB565[in]
1548  *
1549  * @param height
1550  *   Height of RGB565[in]
1551  */
1552 void csc_RGB565_to_YUV420P(
1553     unsigned char *y_dst,
1554     unsigned char *u_dst,
1555     unsigned char *v_dst,
1556     unsigned char *rgb_src,
1557     unsigned int width,
1558     unsigned int height)
1559 {
1560     unsigned int i, j;
1561     unsigned int tmp;
1562
1563     unsigned int R, G, B;
1564     unsigned int Y, U, V;
1565
1566     unsigned int offset1 = width * height;
1567     unsigned int offset2 = width/2 * height/2;
1568
1569     unsigned short int *pSrc = (unsigned short int *)rgb_src;
1570
1571     unsigned char *pDstY = (unsigned char *)y_dst;
1572     unsigned char *pDstU = (unsigned char *)u_dst;
1573     unsigned char *pDstV = (unsigned char *)v_dst;
1574
1575     unsigned int yIndex = 0;
1576     unsigned int uIndex = 0;
1577     unsigned int vIndex = 0;
1578
1579     for (j = 0; j < height; j++) {
1580         for (i = 0; i < width; i++) {
1581             tmp = pSrc[j * width + i];
1582
1583             R = (tmp & 0x0000F800) >> 8;
1584             G = (tmp & 0x000007E0) >> 3;
1585             B = (tmp & 0x0000001F);
1586             B = B << 3;
1587
1588             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
1589             Y = Y >> 8;
1590             Y += 16;
1591
1592             pDstY[yIndex++] = (unsigned char)Y;
1593
1594             if ((j % 2) == 0 && (i % 2) == 0) {
1595                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
1596                 U = U >> 8;
1597                 U += 128;
1598                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
1599                 V = V >> 8;
1600                 V += 128;
1601
1602                 pDstU[uIndex++] = (unsigned char)U;
1603                 pDstV[vIndex++] = (unsigned char)V;
1604             }
1605         }
1606     }
1607 }
1608
1609 /*
1610  * Converts RGB565 to YUV420SP
1611  *
1612  * @param y_dst
1613  *   Y plane address of YUV420SP[out]
1614  *
1615  * @param uv_dst
1616  *   UV plane address of YUV420SP[out]
1617  *
1618  * @param rgb_src
1619  *   Address of RGB565[in]
1620  *
1621  * @param width
1622  *   Width of RGB565[in]
1623  *
1624  * @param height
1625  *   Height of RGB565[in]
1626  */
1627 void csc_RGB565_to_YUV420SP(
1628     unsigned char *y_dst,
1629     unsigned char *uv_dst,
1630     unsigned char *rgb_src,
1631     unsigned int width,
1632     unsigned int height)
1633 {
1634     unsigned int i, j;
1635     unsigned int tmp;
1636
1637     unsigned int R, G, B;
1638     unsigned int Y, U, V;
1639
1640     unsigned int offset = width * height;
1641
1642     unsigned short int *pSrc = (unsigned short int *)rgb_src;
1643
1644     unsigned char *pDstY = (unsigned char *)y_dst;
1645     unsigned char *pDstUV = (unsigned char *)uv_dst;
1646
1647     unsigned int yIndex = 0;
1648     unsigned int uvIndex = 0;
1649
1650     for (j = 0; j < height; j++) {
1651         for (i = 0; i < width; i++) {
1652             tmp = pSrc[j * width + i];
1653
1654             R = (tmp & 0x0000F800) >> 11;
1655             R = R * 8;
1656             G = (tmp & 0x000007E0) >> 5;
1657             G = G * 4;
1658             B = (tmp & 0x0000001F);
1659             B = B * 8;
1660
1661             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
1662             Y = Y >> 8;
1663             Y += 16;
1664
1665             pDstY[yIndex++] = (unsigned char)Y;
1666
1667             if ((j % 2) == 0 && (i % 2) == 0) {
1668                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
1669                 U = U >> 8;
1670                 U += 128;
1671                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
1672                 V = V >> 8;
1673                 V += 128;
1674
1675                 pDstUV[uvIndex++] = (unsigned char)U;
1676                 pDstUV[uvIndex++] = (unsigned char)V;
1677             }
1678         }
1679     }
1680 }
1681
1682 /*
1683  * Converts ARGB8888 to YUV420P
1684  *
1685  * @param y_dst
1686  *   Y plane address of YUV420P[out]
1687  *
1688  * @param u_dst
1689  *   U plane address of YUV420P[out]
1690  *
1691  * @param v_dst
1692  *   V plane address of YUV420P[out]
1693  *
1694  * @param rgb_src
1695  *   Address of ARGB8888[in]
1696  *
1697  * @param width
1698  *   Width of ARGB8888[in]
1699  *
1700  * @param height
1701  *   Height of ARGB8888[in]
1702  */
1703 void csc_ARGB8888_to_YUV420P(
1704     unsigned char *y_dst,
1705     unsigned char *u_dst,
1706     unsigned char *v_dst,
1707     unsigned char *rgb_src,
1708     unsigned int width,
1709     unsigned int height)
1710 {
1711     unsigned int i, j;
1712     unsigned int tmp;
1713
1714     unsigned int R, G, B;
1715     unsigned int Y, U, V;
1716
1717     unsigned int offset1 = width * height;
1718     unsigned int offset2 = width/2 * height/2;
1719
1720     unsigned int *pSrc = (unsigned int *)rgb_src;
1721
1722     unsigned char *pDstY = (unsigned char *)y_dst;
1723     unsigned char *pDstU = (unsigned char *)u_dst;
1724     unsigned char *pDstV = (unsigned char *)v_dst;
1725
1726     unsigned int yIndex = 0;
1727     unsigned int uIndex = 0;
1728     unsigned int vIndex = 0;
1729
1730     for (j = 0; j < height; j++) {
1731         for (i = 0; i < width; i++) {
1732             tmp = pSrc[j * width + i];
1733
1734             R = (tmp & 0x00FF0000) >> 16;
1735             G = (tmp & 0x0000FF00) >> 8;
1736             B = (tmp & 0x000000FF);
1737
1738             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
1739             Y = Y >> 8;
1740             Y += 16;
1741
1742             pDstY[yIndex++] = (unsigned char)Y;
1743
1744             if ((j % 2) == 0 && (i % 2) == 0) {
1745                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
1746                 U = U >> 8;
1747                 U += 128;
1748                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
1749                 V = V >> 8;
1750                 V += 128;
1751
1752                 pDstU[uIndex++] = (unsigned char)U;
1753                 pDstV[vIndex++] = (unsigned char)V;
1754             }
1755         }
1756     }
1757 }
1758
1759
1760 /*
1761  * Converts ARGB8888 to YUV420SP
1762  *
1763  * @param y_dst
1764  *   Y plane address of YUV420SP[out]
1765  *
1766  * @param uv_dst
1767  *   UV plane address of YUV420SP[out]
1768  *
1769  * @param rgb_src
1770  *   Address of ARGB8888[in]
1771  *
1772  * @param width
1773  *   Width of ARGB8888[in]
1774  *
1775  * @param height
1776  *   Height of ARGB8888[in]
1777  */
1778 void csc_ARGB8888_to_YUV420SP(
1779     unsigned char *y_dst,
1780     unsigned char *uv_dst,
1781     unsigned char *rgb_src,
1782     unsigned int width,
1783     unsigned int height)
1784 {
1785     unsigned int i, j;
1786     unsigned int tmp;
1787
1788     unsigned int R, G, B;
1789     unsigned int Y, U, V;
1790
1791     unsigned int offset = width * height;
1792
1793     unsigned int *pSrc = (unsigned int *)rgb_src;
1794
1795     unsigned char *pDstY = (unsigned char *)y_dst;
1796     unsigned char *pDstUV = (unsigned char *)uv_dst;
1797
1798     unsigned int yIndex = 0;
1799     unsigned int uvIndex = 0;
1800
1801     for (j = 0; j < height; j++) {
1802         for (i = 0; i < width; i++) {
1803             tmp = pSrc[j * width + i];
1804
1805             R = (tmp & 0x00FF0000) >> 16;
1806             G = (tmp & 0x0000FF00) >> 8;
1807             B = (tmp & 0x000000FF);
1808
1809             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
1810             Y = Y >> 8;
1811             Y += 16;
1812
1813             pDstY[yIndex++] = (unsigned char)Y;
1814
1815             if ((j % 2) == 0 && (i % 2) == 0) {
1816                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
1817                 U = U >> 8;
1818                 U += 128;
1819                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
1820                 V = V >> 8;
1821                 V += 128;
1822
1823                 pDstUV[uvIndex++] = (unsigned char)U;
1824                 pDstUV[uvIndex++] = (unsigned char)V;
1825             }
1826         }
1827     }
1828 }