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