diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-03-24 17:38:29 +0100 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-03-24 17:38:29 +0100 |
commit | f1be2fe3cd7c04704e166f5303c5c41a7be146c1 (patch) | |
tree | 30f067137f5bc498e126a3885679a9738af0c188 /exynos4/hal/libswconverter | |
download | android_hardware_samsung-f1be2fe3cd7c04704e166f5303c5c41a7be146c1.tar.gz android_hardware_samsung-f1be2fe3cd7c04704e166f5303c5c41a7be146c1.tar.bz2 android_hardware_samsung-f1be2fe3cd7c04704e166f5303c5c41a7be146c1.zip |
initial commit, taken and modified from linaro/insignal
Diffstat (limited to 'exynos4/hal/libswconverter')
-rw-r--r-- | exynos4/hal/libswconverter/Android.mk | 44 | ||||
-rw-r--r-- | exynos4/hal/libswconverter/csc_interleave_memcpy_neon.s | 120 | ||||
-rw-r--r-- | exynos4/hal/libswconverter/csc_linear_to_tiled_crop_neon.s | 492 | ||||
-rw-r--r-- | exynos4/hal/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s | 563 | ||||
-rw-r--r-- | exynos4/hal/libswconverter/csc_tiled_to_linear_crop_neon.s | 701 | ||||
-rw-r--r-- | exynos4/hal/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s | 786 | ||||
-rw-r--r-- | exynos4/hal/libswconverter/swconvertor.c | 1828 |
7 files changed, 4534 insertions, 0 deletions
diff --git a/exynos4/hal/libswconverter/Android.mk b/exynos4/hal/libswconverter/Android.mk new file mode 100644 index 0000000..ce6daf4 --- /dev/null +++ b/exynos4/hal/libswconverter/Android.mk @@ -0,0 +1,44 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + swconvertor.c \ + csc_linear_to_tiled_crop_neon.s \ + csc_linear_to_tiled_interleave_crop_neon.s \ + csc_tiled_to_linear_crop_neon.s \ + csc_tiled_to_linear_deinterleave_crop_neon.s \ + csc_interleave_memcpy_neon.s + +LOCAL_C_INCLUDES := \ + $(TOP)/$(BOARD_HMM_PATH)/openmax/include/khronos \ + $(TOP)/$(BOARD_HMM_PATH)/openmax/include/sec \ + $(TOP)/$(BOARD_HAL_PATH)/include \ + $(TOP)/$(BOARD_HAL_PATH)/libhwconverter + +ifeq ($(BOARD_USE_SAMSUNG_COLORFORMAT), true) +LOCAL_CFLAGS += -DUSE_SAMSUNG_COLORFORMAT +endif + +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE := libswconverter + +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm + +LOCAL_SHARED_LIBRARIES := liblog libfimc libhwconverter + +include $(BUILD_STATIC_LIBRARY) diff --git a/exynos4/hal/libswconverter/csc_interleave_memcpy_neon.s b/exynos4/hal/libswconverter/csc_interleave_memcpy_neon.s new file mode 100644 index 0000000..1ab25b6 --- /dev/null +++ b/exynos4/hal/libswconverter/csc_interleave_memcpy_neon.s @@ -0,0 +1,120 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.02.01 : Create + */ + +/* + * Interleave src1, src2 to dst + * + * @param dest + * dst address[out] + * + * @param src1 + * src1 address[in] + * + * @param src2 + * src2 address[in] + * + * @param src_size + * src_size or src1 + */ + + .arch armv7-a + .text + .global csc_interleave_memcpy_neon + .type csc_interleave_memcpy_neon, %function +csc_interleave_memcpy_neon: + .fnstart + + @r0 dest + @r1 src1 + @r2 src2 + @r3 src_size + @r4 + @r5 + @r6 + @r7 + @r8 temp1 + @r9 temp2 + @r10 dest_addr + @r11 src1_addr + @r12 src2_addr + @r14 i + + stmfd sp!, {r8-r12,r14} @ backup registers + + mov r10, r0 + mov r11, r1 + mov r12, r2 + mov r14, r3 + + cmp r14, #128 + blt LESS_THAN_128 + +LOOP_128: + vld1.8 {q0}, [r11]! + vld1.8 {q2}, [r11]! + vld1.8 {q4}, [r11]! + vld1.8 {q6}, [r11]! + vld1.8 {q8}, [r11]! + vld1.8 {q10}, [r11]! + vld1.8 {q12}, [r11]! + vld1.8 {q14}, [r11]! + vld1.8 {q1}, [r12]! + vld1.8 {q3}, [r12]! + vld1.8 {q5}, [r12]! + vld1.8 {q7}, [r12]! + vld1.8 {q9}, [r12]! + vld1.8 {q11}, [r12]! + vld1.8 {q13}, [r12]! + vld1.8 {q15}, [r12]! + + vst2.8 {q0, q1}, [r10]! + vst2.8 {q2, q3}, [r10]! + vst2.8 {q4, q5}, [r10]! + vst2.8 {q6, q7}, [r10]! + vst2.8 {q8, q9}, [r10]! + vst2.8 {q10, q11}, [r10]! + vst2.8 {q12, q13}, [r10]! + vst2.8 {q14, q15}, [r10]! + + sub r14, #128 + cmp r14, #128 + bgt LOOP_128 + +LESS_THAN_128: + cmp r14, #0 + beq RESTORE_REG + +LOOP_1: + ldrb r8, [r11], #1 + ldrb r9, [r12], #1 + strb r8, [r10], #1 + strb r9, [r10], #1 + subs r14, #1 + bne LOOP_1 + +RESTORE_REG: + ldmfd sp!, {r8-r12,r15} @ restore registers + .fnend diff --git a/exynos4/hal/libswconverter/csc_linear_to_tiled_crop_neon.s b/exynos4/hal/libswconverter/csc_linear_to_tiled_crop_neon.s new file mode 100644 index 0000000..8f59826 --- /dev/null +++ b/exynos4/hal/libswconverter/csc_linear_to_tiled_crop_neon.s @@ -0,0 +1,492 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.02.01 : Create + */ + +/* + * Converts linear data to tiled + * Crops left, top, right, buttom + * 1. Y of YUV420P to Y of NV12T + * 2. Y of YUV420S to Y of NV12T + * 3. UV of YUV420S to UV of NV12T + * + * @param nv12t_dest + * Y or UV plane address of NV12T[out] + * + * @param yuv420_src + * Y or UV plane address of YUV420P(S)[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_linear_to_tiled_crop_neon + .type csc_linear_to_tiled_crop_neon, %function +csc_linear_to_tiled_crop_neon: + .fnstart + + @r0 tiled_dest + @r1 linear_src + @r2 yuv420_width + @r3 yuv420_height + @r4 j + @r5 i + @r6 nn(tiled_addr) + @r7 mm(linear_addr) + @r8 aligned_x_size + @r9 aligned_y_size + @r10 temp1 + @r11 temp2 + @r12 temp3 + @r14 temp4 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r11, [sp, #44] @ top + ldr r14, [sp, #52] @ buttom + ldr r10, [sp, #40] @ left + ldr r12, [sp, #48] @ right + + sub r9, r3, r11 @ aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5 + sub r9, r9, r14 + bic r9, r9, #0x1F + + sub r8, r2, r10 @ aligned_x_size = ((yuv420_width-left-right)>>6)<<6 + sub r8, r8, r12 + bic r8, r8, #0x3F + + mov r5, #0 @ i = 0 +LOOP_ALIGNED_Y_SIZE: + + mov r4, #0 @ j = 0 +LOOP_ALIGNED_X_SIZE: + + bl GET_TILED_OFFSET + + ldr r10, [sp, #44] @ r10 = top + ldr r14, [sp, #40] @ r14 = left + add r10, r5, r10 @ temp1 = linear_x_size*(i+top) + mul r10, r2, r10 + add r7, r1, r4 @ linear_addr = linear_src+j + add r7, r7, r10 @ linear_addr = linear_addr+temp1 + add r7, r7, r14 @ linear_addr = linear_addr+left + sub r10, r2, #32 + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*1, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*2, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*3, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + add r6, r0, r6 @ tiled_addr = tiled_dest+tiled_addr + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*1} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*2} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*3} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*4, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*5, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*6, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*7, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*4} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*5} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*6} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*7} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*8, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*9, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*10, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*11, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*8} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*9} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*10} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*11} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*12, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*13, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*14, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*15, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*12} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*13} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*14} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*15} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*16, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*17, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*18, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*19, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*16} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*17} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*18} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*19} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*20, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*21, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*22, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*23, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*20} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*21} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*22} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*23} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*24, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*25, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*26, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + pld [r7, r2] + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*27, 64} + pld [r7, r2] + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*24} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*25} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*26} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*27} + vst1.8 {q14, q15}, [r6]! + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src+linear_x_size*28, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + pld [r7, r2] + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*29, 64} + pld [r7, r2] + vld1.8 {q6, q7}, [r7], r10 + pld [r7, r2] + vld1.8 {q8, q9}, [r7]! @ load {linear_src+linear_x_size*30, 64} + pld [r7, r2] + vld1.8 {q10, q11}, [r7], r10 + vld1.8 {q12, q13}, [r7]! @ load {linear_src+linear_x_size*31, 64} + vld1.8 {q14, q15}, [r7], r10 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr+64*28} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*29} + vst1.8 {q6, q7}, [r6]! + vst1.8 {q8, q9}, [r6]! @ store {tiled_addr+64*30} + vst1.8 {q10, q11}, [r6]! + vst1.8 {q12, q13}, [r6]! @ store {tiled_addr+64*31} + vst1.8 {q14, q15}, [r6]! + + add r4, r4, #64 @ j = j+64 + cmp r4, r8 @ j<aligned_x_size + blt LOOP_ALIGNED_X_SIZE + + add r5, r5, #32 @ i = i+32 + cmp r5, r9 @ i<aligned_y_size + blt LOOP_ALIGNED_Y_SIZE + + ldr r10, [sp, #44] @ r10 = top + ldr r11, [sp, #52] @ r11 = buttom + sub r10, r3, r10 + sub r10, r10, r11 + cmp r5, r10 @ i == (yuv420_height-top-buttom) + beq LOOP_LINEAR_Y_SIZE_2_START + +LOOP_LINEAR_Y_SIZE_1: + + mov r4, #0 @ j = 0 +LOOP_ALIGNED_X_SIZE_1: + + bl GET_TILED_OFFSET + + ldr r10, [sp, #44] @ r10 = top + ldr r14, [sp, #40] @ r14 = left + add r10, r5, r10 @ temp1 = yuv420_width*(i+top) + mul r10, r2, r10 + add r7, r1, r4 @ linear_addr = linear_src+j + add r7, r7, r10 @ linear_addr = linear_addr+temp1 + add r7, r7, r14 @ linear_addr = linear_addr+left + sub r10, r2, #32 @ temp1 = yuv420_width-32 + + pld [r7, r2] + vld1.8 {q0, q1}, [r7]! @ load {linear_src, 64} + pld [r7, r2] + vld1.8 {q2, q3}, [r7], r10 + vld1.8 {q4, q5}, [r7]! @ load {linear_src+linear_x_size*1, 64} + vld1.8 {q6, q7}, [r7] + add r6, r0, r6 @ tiled_addr = tiled_dest+tiled_addr + and r10, r5, #0x1F @ temp1 = i&0x1F + mov r10, r10, lsl #6 @ temp1 = 64*temp1 + add r6, r6, r10 @ tiled_addr = tiled_addr+temp1 + vst1.8 {q0, q1}, [r6]! @ store {tiled_addr} + vst1.8 {q2, q3}, [r6]! + vst1.8 {q4, q5}, [r6]! @ store {tiled_addr+64*1} + vst1.8 {q6, q7}, [r6]! + + add r4, r4, #64 @ j = j+64 + cmp r4, r8 @ j<aligned_x_size + blt LOOP_ALIGNED_X_SIZE_1 + + add r5, r5, #2 @ i = i+2 + ldr r10, [sp, #44] @ r10 = top + ldr r14, [sp, #52] @ r14 = buttom + sub r10, r3, r10 + sub r10, r10, r14 + cmp r5, r10 @ i<yuv420_height-top-buttom + blt LOOP_LINEAR_Y_SIZE_1 + +LOOP_LINEAR_Y_SIZE_2_START: + ldr r10, [sp, #40] @ r10 = left + ldr r11, [sp, #48] @ r11 = right + sub r10, r2, r10 + sub r10, r10, r11 + cmp r8, r10 @ aligned_x_size == (yuv420_width-left-right) + beq RESTORE_REG + + mov r5, #0 @ i = 0 +LOOP_LINEAR_Y_SIZE_2: + + mov r4, r8 @ j = aligned_x_size +LOOP_LINEAR_X_SIZE_2: + + bl GET_TILED_OFFSET + + ldr r10, [sp, #44] @ r14 = top + ldr r14, [sp, #40] @ r10 = left + add r10, r5, r10 + mul r10, r2, r10 @ temp1 = linear_x_size*(i+top) + add r7, r1, r4 @ linear_addr = linear_src+j + add r7, r7, r10 @ linear_addr = linear_addr+temp1 + add r7, r7, r14 @ linear_addr = linear_addr+left + + add r6, r0, r6 @ tiled_addr = tiled_dest+tiled_addr + and r11, r5, #0x1F @ temp2 = i&0x1F + mov r11, r11, lsl #6 @ temp2 = 64*temp2 + add r6, r6, r11 @ tiled_addr = tiled_addr+temp2 + and r11, r4, #0x3F @ temp2 = j&0x3F + add r6, r6, r11 @ tiled_addr = tiled_addr+temp2 + + ldrh r10, [r7], r2 + ldrh r11, [r7] + strh r10, [r6], #64 + strh r11, [r6] + + ldr r12, [sp, #40] @ r12 = left + ldr r14, [sp, #48] @ r14 = right + add r4, r4, #2 @ j = j+2 + sub r12, r2, r12 + sub r12, r12, r14 + cmp r4, r12 @ j<(yuv420_width-left-right) + blt LOOP_LINEAR_X_SIZE_2 + + ldr r12, [sp, #44] @ r12 = top + ldr r14, [sp, #52] @ r14 = buttom + add r5, r5, #2 @ i = i+2 + sub r12, r3, r12 + sub r12, r12, r14 + cmp r5, r12 @ i<(yuv420_height-top-buttom) + blt LOOP_LINEAR_Y_SIZE_2 + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + +GET_TILED_OFFSET: + + mov r11, r5, asr #5 @ temp2 = i>>5 + mov r10, r4, asr #6 @ temp1 = j>>6 + + and r12, r11, #0x1 @ if (temp2 & 0x1) + cmp r12, #0x1 + bne GET_TILED_OFFSET_EVEN_FORMULA_1 + +GET_TILED_OFFSET_ODD_FORMULA: + sub r6, r11, #1 @ tiled_addr = temp2-1 + + ldr r7, [sp, #40] @ left + add r12, r2, #127 @ temp3 = linear_x_size+127 + sub r12, r12, r7 + ldr r7, [sp, #48] @ right + sub r12, r12, r7 + bic r12, r12, #0x7F @ temp3 = (temp3 >>7)<<7 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + mul r6, r6, r12 @ tiled_addr = tiled_addr*temp3 + add r6, r6, r10 @ tiled_addr = tiled_addr+temp1 + add r6, r6, #2 @ tiled_addr = tiled_addr+2 + bic r12, r10, #0x3 @ temp3 = (temp1>>2)<<2 + add r6, r6, r12 @ tiled_addr = tiled_addr+temp3 + mov r6, r6, lsl #11 @ tiled_addr = tiled_addr<<11 + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_1: + ldr r7, [sp, #44] @ top + add r12, r3, #31 @ temp3 = linear_y_size+31 + sub r12, r12, r7 + ldr r7, [sp, #52] @ buttom + sub r12, r12, r7 + bic r12, r12, #0x1F @ temp3 = (temp3>>5)<<5 + sub r12, r12, #32 @ temp3 = temp3 - 32 + cmp r5, r12 @ if (i<(temp3-32)) { + bge GET_TILED_OFFSET_EVEN_FORMULA_2 + add r12, r10, #2 @ temp3 = temp1+2 + bic r12, r12, #3 @ temp3 = (temp3>>2)<<2 + add r6, r10, r12 @ tiled_addr = temp1+temp3 + ldr r7, [sp, #40] @ left + add r12, r2, #127 @ temp3 = linear_x_size+127 + sub r12, r12, r7 + ldr r7, [sp, #48] @ right + sub r12, r12, r7 + bic r12, r12, #0x7F @ temp3 = (temp3>>7)<<7 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + mul r11, r11, r12 @ tiled_y_index = tiled_y_index*temp3 + add r6, r6, r11 @ tiled_addr = tiled_addr+tiled_y_index + mov r6, r6, lsl #11 @ + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_2: + ldr r7, [sp, #40] @ left + add r12, r2, #127 @ temp3 = linear_x_size+127 + sub r12, r12, r7 + ldr r7, [sp, #48] @ right + sub r12, r12, r7 + bic r12, r12, #0x7F @ temp3 = (temp3>>7)<<7 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + mul r6, r11, r12 @ tiled_addr = temp2*temp3 + add r6, r6, r10 @ tiled_addr = tiled_addr+temp3 + mov r6, r6, lsl #11 @ tiled_addr = tiled_addr<<11@ + +GET_TILED_OFFSET_RETURN: + mov pc, lr + + .fnend diff --git a/exynos4/hal/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s b/exynos4/hal/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s new file mode 100644 index 0000000..33a31da --- /dev/null +++ b/exynos4/hal/libswconverter/csc_linear_to_tiled_interleave_crop_neon.s @@ -0,0 +1,563 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_linear_to_tiled_interleave_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.02.01 : Create + */ + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_linear_to_tiled_interleave_crop_neon + .type csc_linear_to_tiled_interleave_crop_neon, %function +csc_linear_to_tiled_interleave_crop_neon: + .fnstart + + @r0 tiled_dest + @r1 linear_src_u + @r2 linear_src_v + @r3 yuv420_width + @r4 yuv420_height + @r5 j + @r6 i + @r7 tiled_addr + @r8 linear_addr + @r9 aligned_x_size + @r10 aligned_y_size + @r11 temp1 + @r12 temp2 + @r14 temp3 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r4, [sp, #40] @ load linear_y_size to r4 + + ldr r10, [sp, #48] @ r10 = top + ldr r14, [sp, #56] @ r14 = buttom + ldr r11, [sp, #44] @ r11 = left + ldr r12, [sp, #52] @ r12 = right + + sub r10, r4, r10 @ aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5 + sub r10, r10, r14 + bic r10, r10, #0x1F + sub r11, r3, r11 @ aligned_x_size = ((yuv420_width-left-right)>>6)<<6 + sub r11, r11, r12 + bic r9, r11, #0x3F + + mov r6, #0 @ i = 0 +LOOP_ALIGNED_Y_SIZE: + + mov r5, #0 @ j = 0 +LOOP_ALIGNED_X_SIZE: + + bl GET_TILED_OFFSET + + ldr r12, [sp, #48] @ r12 = top + ldr r8, [sp, #44] @ r8 = left + + mov r11, r3, asr #1 @ temp1 = (yuv420_width/2)*(i+top) + add r12, r6, r12 + mul r11, r11, r12 + add r11, r11, r5, asr #1 @ temp1 = temp1+j/2 + add r11, r11, r8, asr #1 @ temp1 = temp1+left/2 + + mov r12, r3, asr #1 @ temp2 = yuv420_width/2 + sub r12, r12, #16 @ temp2 = yuv420_width-16 + + add r8, r1, r11 @ linear_addr = linear_src_u+temp1 + add r11, r2, r11 @ temp1 = linear_src_v+temp1 + add r7, r0, r7 @ tiled_addr = tiled_dest+tiled_addr + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*1, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*2, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*3, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*1, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*2, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*3, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*1} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*2} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*3} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*4, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*5, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*6, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*7, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*4, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*5, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*6, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*7, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*4} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*5} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*6} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*7} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*8, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*9, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*10, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*11, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*8, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*9, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*10, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*11, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*8} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*9} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*10} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*11} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*12, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*13, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*14, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*15, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*12, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*13, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*14, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*15, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*12} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*13} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*14} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*15} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*16, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*17, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*18, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*19, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*16, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*17, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*18, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*19, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*16} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*17} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*18} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*19} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*20, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*21, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*22, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*23, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*20, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*21, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*22, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*23, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*20} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*21} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*22} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*23} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*24, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*25, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*26, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*27, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*24, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*25, 32} + vld1.8 {q7}, [r11], r12 + pld [r8] + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*26, 32} + vld1.8 {q11}, [r11], r12 + pld [r8, r3, asr #1] + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*27, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*24} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*25} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*26} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*27} + vst2.8 {q14, q15}, [r7]! + + pld [r8, r3] + vld1.8 {q0}, [r8]! @ load {linear_src_u+(linear_x_size/2)*28, 32} + vld1.8 {q2}, [r8], r12 + pld [r8, r3] + vld1.8 {q4}, [r8]! @ load {linear_src_u+(linear_x_size/2)*29, 32} + vld1.8 {q6}, [r8], r12 + pld [r11] + vld1.8 {q8}, [r8]! @ load {linear_src_u+(linear_x_size/2)*30, 32} + vld1.8 {q10}, [r8], r12 + pld [r11, r3, asr #1] + vld1.8 {q12}, [r8]! @ load {linear_src_u+(linear_x_size/2)*31, 32} + vld1.8 {q14}, [r8], r12 + pld [r11, r3] + vld1.8 {q1}, [r11]! @ load {linear_src_v+(linear_x_size/2)*28, 32} + vld1.8 {q3}, [r11], r12 + pld [r11, r3] + vld1.8 {q5}, [r11]! @ load {linear_src_v+(linear_x_size/2)*29, 32} + vld1.8 {q7}, [r11], r12 + vld1.8 {q9}, [r11]! @ load {linear_src_v+(linear_x_size/2)*30, 32} + vld1.8 {q11}, [r11], r12 + vld1.8 {q13}, [r11]! @ load {linear_src_v+(linear_x_size/2)*31, 32} + vld1.8 {q15}, [r11], r12 + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr+64*28} + vst2.8 {q2, q3}, [r7]! + vst2.8 {q4, q5}, [r7]! @ store {tiled_addr+64*29} + vst2.8 {q6, q7}, [r7]! + vst2.8 {q8, q9}, [r7]! @ store {tiled_addr+64*30} + vst2.8 {q10, q11}, [r7]! + vst2.8 {q12, q13}, [r7]! @ store {tiled_addr+64*31} + vst2.8 {q14, q15}, [r7]! + + add r5, r5, #64 @ j = j+64 + cmp r5, r9 @ j<aligned_x_size + blt LOOP_ALIGNED_X_SIZE + + add r6, r6, #32 @ i = i+32 + cmp r6, r10 @ i<aligned_y_size + blt LOOP_ALIGNED_Y_SIZE + + cmp r6, r4 + beq LOOP_LINEAR_Y_SIZE_2_START + +LOOP_LINEAR_Y_SIZE_1: + + mov r5, #0 @ j = 0 +LOOP_ALIGNED_X_SIZE_1: + + bl GET_TILED_OFFSET + + ldr r12, [sp, #48] @ r12 = top + ldr r8, [sp, #44] @ r8 = left + + mov r11, r3, asr #1 @ temp1 = (yuv420_width/2)*(i+top) + add r12, r6, r12 + mul r11, r11, r12 + add r11, r11, r5, asr #1 @ temp1 = temp1+j/2 + add r11, r11, r8, asr #1 @ temp1 = temp1+left/2 + + add r8, r1, r11 @ linear_addr = linear_src_u+temp1 + add r11, r2, r11 @ temp1 = linear_src_v+temp1 + add r7, r0, r7 @ tiled_addr = tiled_dest+tiled_addr + and r14, r6, #0x1F @ temp3 = i&0x1F@ + mov r14, r14, lsl #6 @ temp3 = temp3*64 + add r7, r7, r14 @ tiled_addr = tiled_addr+temp3 + + vld1.8 {q0}, [r8]! @ load {linear_src_u, 32} + vld1.8 {q2}, [r8] + vld1.8 {q1}, [r11]! @ load {linear_src_v, 32} + vld1.8 {q3}, [r11] + vst2.8 {q0, q1}, [r7]! @ store {tiled_addr} + vst2.8 {q2, q3}, [r7]! + + add r5, r5, #64 @ j = j+64 + cmp r5, r9 @ j<aligned_x_size + blt LOOP_ALIGNED_X_SIZE_1 + + ldr r12, [sp, #48] @ r12 = top + ldr r8, [sp, #56] @ r8 = buttom + add r6, r6, #1 @ i = i+1 + sub r12, r4, r12 + sub r12, r12, r8 + cmp r6, r12 @ i<(yuv420_height-top-buttom) + blt LOOP_LINEAR_Y_SIZE_1 + +LOOP_LINEAR_Y_SIZE_2_START: + cmp r5, r3 + beq RESTORE_REG + + mov r6, #0 @ i = 0 +LOOP_LINEAR_Y_SIZE_2: + + mov r5, r9 @ j = aligned_x_size +LOOP_LINEAR_X_SIZE_2: + + bl GET_TILED_OFFSET + + ldr r12, [sp, #48] @ r12 = top + ldr r8, [sp, #44] @ r8 = left + + mov r11, r3, asr #1 @ temp1 = (yuv420_width/2)*(i+top) + add r12, r6, r12 + mul r11, r11, r12 + add r11, r11, r5, asr #1 @ temp1 = temp1+j/2 + add r11, r11, r8, asr #1 @ temp1 = temp1+left/2 + + mov r12, r3, asr #1 @ temp2 = linear_x_size/2 + sub r12, r12, #1 @ temp2 = linear_x_size-1 + + add r8, r1, r11 @ linear_addr = linear_src_u+temp1 + add r11, r2, r11 @ temp1 = linear_src_v+temp1 + add r7, r0, r7 @ tiled_addr = tiled_dest+tiled_addr + and r14, r6, #0x1F @ temp3 = i&0x1F@ + mov r14, r14, lsl #6 @ temp3 = temp3*64 + add r7, r7, r14 @ tiled_addr = tiled_addr+temp3 + and r14, r5, #0x3F @ temp3 = j&0x3F + add r7, r7, r14 @ tiled_addr = tiled_addr+temp3 + + ldrb r10, [r8], #1 + ldrb r14, [r11], #1 + mov r14, r14, lsl #8 + orr r10, r10, r14 + strh r10, [r7], #2 + + ldr r12, [sp, #44] @ r12 = left + ldr r8, [sp, #52] @ r8 = right + add r5, r5, #2 @ j = j+2 + sub r12, r3, r12 + sub r12, r12, r8 + cmp r5, r12 @ j<(yuv420_width-left-right) + blt LOOP_LINEAR_X_SIZE_2 + + ldr r12, [sp, #48] @ r12 = top + ldr r8, [sp, #56] @ r8 = buttom + add r6, r6, #1 @ i = i+1 + sub r12, r4, r12 + sub r12, r12, r8 + cmp r6, r12 @ i<(yuv420_height-top-buttom) + blt LOOP_LINEAR_Y_SIZE_2 + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + +GET_TILED_OFFSET: + stmfd sp!, {r14} + + mov r12, r6, asr #5 @ temp2 = i>>5 + mov r11, r5, asr #6 @ temp1 = j>>6 + + and r14, r12, #0x1 @ if (temp2 & 0x1) + cmp r14, #0x1 + bne GET_TILED_OFFSET_EVEN_FORMULA_1 + +GET_TILED_OFFSET_ODD_FORMULA: + + ldr r7, [sp, #48] @ r7 = left , (r14 was pushed to stack) + ldr r8, [sp, #56] @ r8 = right , (r14 was pushed to stack) + sub r14, r3, r7 + sub r14, r14, r8 + add r14, r14, #127 @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7 + bic r14, r14, #0x7F @ temp3 = (temp3 >>7)<<7 + mov r14, r14, asr #6 @ temp3 = temp3>>6 + sub r7, r12, #1 @ tiled_addr = temp2-1 + mul r7, r7, r14 @ tiled_addr = tiled_addr*temp3 + add r7, r7, r11 @ tiled_addr = tiled_addr+temp1 + add r7, r7, #2 @ tiled_addr = tiled_addr+2 + bic r14, r11, #0x3 @ temp3 = (temp1>>2)<<2 + add r7, r7, r14 @ tiled_addr = tiled_addr+temp3 + mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11 + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_1: + ldr r7, [sp, #52] @ r7 = top, (r14 was pushed to stack) + ldr r8, [sp, #60] @ r8 = buttom, (r14 was pushed to stack) + sub r14, r4, r7 + sub r14, r14, r8 + add r14, r14, #31 @ temp3 = (((yuv420_height-top-buttom)+31)>>5)<<5 + bic r14, r14, #0x1F @ temp3 = (temp3>>5)<<5 + sub r14, r14, #32 @ temp3 = temp3 - 32 + cmp r6, r14 @ if (i<(temp3-32)) { + bge GET_TILED_OFFSET_EVEN_FORMULA_2 + add r14, r11, #2 @ temp3 = temp1+2 + bic r14, r14, #3 @ temp3 = (temp3>>2)<<2 + add r7, r11, r14 @ tiled_addr = temp1+temp3 + ldr r8, [sp, #48] @ r8 = left, (r14 was pushed to stack) + sub r14, r3, r8 + ldr r8, [sp, #56] @ r8 = right, (r14 was pushed to stack) + sub r14, r14, r8 + add r14, r14, #127 @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7 + bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7 + mov r14, r14, asr #6 @ temp3 = temp3>>6 + mul r12, r12, r14 @ tiled_y_index = tiled_y_index*temp3 + add r7, r7, r12 @ tiled_addr = tiled_addr+tiled_y_index + mov r7, r7, lsl #11 @ + b GET_TILED_OFFSET_RETURN + +GET_TILED_OFFSET_EVEN_FORMULA_2: + ldr r8, [sp, #48] @ r8 = left, (r14 was pushed to stack) + sub r14, r3, r8 + ldr r8, [sp, #56] @ r8 = right, (r14 was pushed to stack) + sub r14, r14, r8 + add r14, r14, #127 @ temp3 = (((yuv420_width-left-right)+127)>>7)<<7 + bic r14, r14, #0x7F @ temp3 = (temp3>>7)<<7 + mov r14, r14, asr #6 @ temp3 = temp3>>6 + mul r7, r12, r14 @ tiled_addr = temp2*temp3 + add r7, r7, r11 @ tiled_addr = tiled_addr+temp3 + mov r7, r7, lsl #11 @ tiled_addr = tiled_addr<<11@ + +GET_TILED_OFFSET_RETURN: + ldmfd sp!, {r15} @ restore registers + + .fnend + diff --git a/exynos4/hal/libswconverter/csc_tiled_to_linear_crop_neon.s b/exynos4/hal/libswconverter/csc_tiled_to_linear_crop_neon.s new file mode 100644 index 0000000..9cb81b5 --- /dev/null +++ b/exynos4/hal/libswconverter/csc_tiled_to_linear_crop_neon.s @@ -0,0 +1,701 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_tiled_to_linear_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.02.01 : Create + */ + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_tiled_to_linear_crop_neon + .type csc_tiled_to_linear_crop_neon, %function +csc_tiled_to_linear_crop_neon: + .fnstart + + @r0 yuv420_dest + @r1 nv12t_src + @r2 yuv420_width + @r3 yuv420_height + @r4 + @r5 i + @r6 j + @r7 tiled_offset + @r8 tiled_offset1 + @r9 linear_offset + @r10 temp1 + @r11 temp2 + @r12 temp3 + @r14 temp4 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r12, [sp, #48] @ r12 = right + ldr r10, [sp, #40] @ r10 = left + sub r12, r2, r12 @ temp3 = yuv420_width-right@ + sub r10, r12, r10 @ temp1 = temp3-left@ + cmp r10, #256 @ if (temp1 >= 256) + blt LOOP_HEIGHT_64_START + + ldr r5, [sp, #44] @ i = top +LOOP_HEIGHT_256: + ldr r6, [sp, #40] @ j = left + mov r14, r5, asr #5 @ temp4 = i>>5 + bic r12, r6, #0xFF @ temp3 = (j>>8)<<8 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + and r11, r14, #0x1 @ if (temp4 & 0x1) + cmp r11, #0x1 + bne LOOP_HEIGHT_256_GET_TILED_EVEN +LOOP_HEIGHT_256_GET_TILED_ODD: + sub r7, r14, #1 @ tiled_offset = temp4-1 + add r10, r2, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6) + mul r7, r7, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + add r7, r7, #2 @ tiled_offset = tiled_offset+2 + bic r10, r12, #0x3 @ temp1 = (temp3>>2)<<2 + add r7, r7, r10 @ tiled_offset = tiled_offset+temp1 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN: + add r11, r3, #31 @ temp2 = ((yuv420_height+31)>>5)<<5 + bic r11, r11, #0x1F + add r10, r5, #32 @ if ((i+32)<temp2) + cmp r10, r11 + bge LOOP_HEIGHT_256_GET_TILED_EVEN1 + add r10, r12, #2 @ temp1 = temp3+2 + bic r10, r10, #0x3 @ temp1 = (temp1>>2)<<2 + add r7, r12, r10 @ tiled_offset = temp3+temp1@ + add r10, r2, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset+temp4*(temp1>>6) + mla r7, r14, r10, r7 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #12288 @ tiled_offset1 = tiled_offset+2048*6 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN1: + add r10, r2, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = temp4*(temp1>>6) + mul r7, r14, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #4 + +LOOP_HEIGHT_256_GET_TILED_END: + + ldr r12, [sp, #48] @ right + ldr r9, [sp, #44] @ top + and r10, r5, #0x1F @ temp1 = i&0x1F + add r7, r7, r10, lsl #6 @ tiled_offset = tiled_offset+64*(temp1) + add r8, r8, r10, lsl #6 @ tiled_offset1 = tiled_offset1+64*(temp1) + sub r11, r2, r6 @ temp2 = yuv420_width-left(==j)-right + sub r11, r11, r12 + sub r9, r5, r9 @ linear_offset = temp2*(i-top)@ + mul r9, r11, r9 + add r12, r6, #256 @ temp3 = ((j+256)>>8)<<8@ + bic r12, r12, #0xFF + sub r12, r12, r6 @ temp3 = temp3-j@ + and r10, r6, #0x3F @ temp1 = left(==j)&0x3F + + cmp r12, #192 @ if (temp3 > 192) + ble LOOP_HEIGHT_256_LEFT_192 + add r11, r1, r7 @ r11 = nv12t_src+tiled_offset+temp1 + add r11, r11, r10 + pld [r11] + add r12, r1, r7 @ r12 = nv12t_src+tiled_offset+2048 + pld [r11, #32] + add r12, r12, #2048 + pld [r12] + cmp r10, #0 + pld [r12, #32] + stmnefd sp!, {r9-r12, r14} @ backup registers + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_256_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_256_64: + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1 + pld [r11] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r11, #32] + vld1.8 {q6, q7}, [r12] + add r12, r11, #2048 @ r12 = nv12t_src+tiled_offset1+2048 + pld [r12] + vld1.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1, 64} + pld [r12, #32] + vld1.8 {q10, q11}, [r11] + vld1.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld1.8 {q14, q15}, [r12] + + sub r11, r0, r10 @ r11 = yuv420_dest+linear_offset+64-temp1 + add r12, r9, #64 + add r11, r11, r12 + + vst1.8 {q4, q5}, [r11]! @ store {yuv420_dest+linear_offset+64-temp1, 64} + vst1.8 {q6, q7}, [r11]! + vst1.8 {q8, q9}, [r11]! @ store {yuv420_dest+linear_offset+128-temp1, 64} + vst1.8 {q10, q11}, [r11]! + vst1.8 {q12, q13}, [r11]! @ store {yuv420_dest+linear_offset+192-temp1, 64} + vst1.8 {q14, q15}, [r11]! + + add r9, r9, #256 + sub r9, r9, r10 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_192: + cmp r12, #128 @ if (temp3 > 128) + ble LOOP_HEIGHT_256_LEFT_128 + add r11, r1, r7 @ r11 = nv12t_src+tiled_offset+2048+temp1 + add r11, r11, r10 + add r11, r11, #2048 + pld [r11] + add r12, r1, r8 @ r12 = nv12t_src+tiled_offset1 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r9-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_192_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+2048+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_192_64: + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1+2048 + add r11, r11, #2048 + pld [r11] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + pld [r11, #32] + vld1.8 {q6, q7}, [r12] + vld1.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld1.8 {q10, q11}, [r11] + + sub r11, r0, r10 @ r11 = yuv420_dest+linear_offset+64-temp1 + add r12, r9, #64 + add r11, r11, r12 + + vst1.8 {q4, q5}, [r11]! @ store {yuv420_dest+linear_offset+64-temp1, 64} + vst1.8 {q6, q7}, [r11]! + vst1.8 {q8, q9}, [r11]! @ store {yuv420_dest+linear_offset+128-temp1, 64} + vst1.8 {q10, q11}, [r11]! + + add r9, r9, #192 + sub r9, r9, r10 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_128: + cmp r12, #64 @ if (temp3 > 64) + ble LOOP_HEIGHT_256_LEFT_64 + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1+temp1 + add r11, r11, r10 + pld [r11] + add r12, r1, r8 @ r12 = nv12t_src+tiled_offset1 + add r12, r12, #2048 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r9-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_128_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_128_64: + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + vld1.8 {q6, q7}, [r12] + + sub r11, r0, r10 @ r11 = yuv420_dest+linear_offset+64-temp1 + add r12, r9, #64 + add r11, r11, r12 + + vst1.8 {q4, q5}, [r11]! @ store {yuv420_dest+linear_offset+64-temp1, 64} + vst1.8 {q6, q7}, [r11]! + + add r9, r9, #128 + sub r9, r9, r10 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_64: + add r11, r1, r8 @ r11 = nv12t_src+tiled_offset1+2048+temp1 + add r11, r11, #2048 + add r11, r11, r10 + cmp r10, #0 + pld [r11] + stmnefd sp!, {r9-r12, r14} @ backup registers + pld [r11, #32] + rsbne r10, r10, #64 + blne MEMCOPY_UNDER_64 + ldmnefd sp!, {r9-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_64_64 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld1.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_64_64: + add r9, r9, #64 + sub r9, r9, r10 + +LOOP_HEIGHT_256_LEFT_END: + + ldr r12, [sp, #48] @ right + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r1, r7 @ r10 = nv12t_src+tiled_offset + pld [r10] + bic r6, r6, #0xFF @ j = (left>>8)<<8 + pld [r10, #32] + add r6, r6, #256 @ j = j + 256 + sub r11, r2, r12 @ temp2 = yuv420_width-right-256 + sub r11, r11, #256 + cmp r6, r11 + bgt LOOP_HEIGHT_256_WIDTH_END + +LOOP_HEIGHT_256_WIDTH: + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset, 64} + pld [r12, #32] + vld1.8 {q2, q3}, [r10] + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + add r10, r1, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld1.8 {q6, q7}, [r12] + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld1.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r12, #32] + vld1.8 {q10, q11}, [r10] + + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r1, r7 + pld [r10] + vld1.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld1.8 {q14, q15}, [r12] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + vst1.8 {q4, q5}, [r12]! + vst1.8 {q6, q7}, [r12]! + vst1.8 {q8, q9}, [r12]! + vst1.8 {q10, q11}, [r12]! + vst1.8 {q12, q13}, [r12]! + vst1.8 {q14, q15}, [r12]! + add r9, r9, #256 @ linear_offset = linear_offset+256 + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + + add r6, r6, #256 @ j=j+256 + cmp r6, r11 @ j<=temp2 + ble LOOP_HEIGHT_256_WIDTH + +LOOP_HEIGHT_256_WIDTH_END: + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + ldr r14, [sp, #48] @ right + sub r11, r2, r6 @ temp2 = yuv420_width-right-j + sub r11, r11, r14 + cmp r11, #0 + beq LOOP_HEIGHT_256_RIGHT_END + cmp r11, #192 + ble LOOP_HEIGHT_256_RIGHT_192 + add r12, r10, #2048 + pld [r12] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld1.8 {q2, q3}, [r10] + + add r10, r1, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r10, #32] + vld1.8 {q6, q7}, [r12] + + add r14, r10, #2048 @ r10 = nv12t_src+tiled_offset1+2048 + pld [r14] + vld1.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset1} + pld [r14, #32] + vld1.8 {q10, q11}, [r10] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + vst1.8 {q4, q5}, [r12]! + vst1.8 {q6, q7}, [r12]! + vst1.8 {q8, q9}, [r12]! + vst1.8 {q10, q11}, [r12]! + add r9, r9, #192 @ linear_offset = linear_offset+192 + + stmfd sp!, {r9-r12, r14} @ backup registers + sub r10, r11, #192 + mov r11, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_192: + cmp r11, #128 + ble LOOP_HEIGHT_256_RIGHT_128 + add r12, r10, #2048 + pld [r12] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld1.8 {q2, q3}, [r10] + + add r14, r1, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r14] + vld1.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r14, #32] + vld1.8 {q6, q7}, [r12] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + vst1.8 {q4, q5}, [r12]! + vst1.8 {q6, q7}, [r12]! + add r9, r9, #128 @ linear_offset = linear_offset+128 + + stmfd sp!, {r9-r12, r14} @ backup registers + sub r10, r11, #128 + mov r11, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_128: + cmp r11, #64 + ble LOOP_HEIGHT_256_RIGHT_64 + add r14, r10, #2048 + pld [r14] + vld1.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r14, #32] + vld1.8 {q2, q3}, [r10] + + add r12, r0, r9 @ r12 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r12]! + vst1.8 {q2, q3}, [r12]! + add r9, r9, #64 @ linear_offset = linear_offset+64 + + stmfd sp!, {r9-r12, r14} @ backup registers + sub r10, r11, #64 + mov r11, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_64: + stmfd sp!, {r9-r12, r14} @ backup registers + mov r14, r11 + mov r11, r10 + mov r10, r14 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12, r14} @ restore registers + +LOOP_HEIGHT_256_RIGHT_END: + + ldr r14, [sp, #52] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r3, r14 @ i<yuv420_height-buttom + cmp r5, r14 + blt LOOP_HEIGHT_256 + b RESTORE_REG + +LOOP_HEIGHT_64_START: + cmp r10, #64 @ if (temp1 >= 64) + blt LOOP_HEIGHT_2_START + + ldr r5, [sp, #44] @ i = top +LOOP_HEIGHT_64: + ldr r6, [sp, #40] @ j = left + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + ldr r9, [sp, #44] @ linear_offset = top + add r11, r6, #64 @ temp2 = ((j+64)>>6)<<6 + bic r11, r11, #0x3F + sub r11, r11, r6 @ temp2 = temp2-j + sub r9, r5, r9 @ linear_offset = temp1*(i-top) + mul r9, r9, r10 + and r14, r6, #0x3 @ temp4 = j&0x3 + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r1, r7 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + add r9, r9, r11 @ linear_offset = linear_offset+temp2 + add r6, r6, r11 @ j = j+temp2@ + + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_1 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r1, r7 + vld1.8 {q0, q1}, [r7]! + vld1.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0, q1}, [r7]! + vst1.8 {q2, q3}, [r7] + add r9, r9, #64 + add r6, r6, #64 + +LOOP_HEIGHT_64_1: + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_2 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r1, r7 + vld1.8 {q0, q1}, [r7]! + vld1.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0, q1}, [r7]! + vst1.8 {q2, q3}, [r7] + add r9, r9, #64 + add r6, r6, #64 + +LOOP_HEIGHT_64_2: + cmp r6, r12 + bge LOOP_HEIGHT_64_3 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + sub r11, r12, r6 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r1, r7 + bl MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + +LOOP_HEIGHT_64_3: + + ldr r14, [sp, #52] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r3, r14 @ i<yuv420_height-buttom + cmp r5, r14 + blt LOOP_HEIGHT_64 + b RESTORE_REG + +LOOP_HEIGHT_2_START: + + ldr r5, [sp, #44] @ i = top +LOOP_HEIGHT_2: + + ldr r6, [sp, #40] @ j = left + ldr r9, [sp, #44] @ linear_offset = top + add r11, r6, #64 @ temp2 = ((j+64)>>6)<<6 + bic r11, r11, #0x3F + sub r11, r11, r6 @ temp2 = temp2-j + sub r9, r5, r9 @ linear_offset = temp1*(i-top) + mul r9, r10, r9 + add r9, r0, r9 @ linear_offset = linear_dst+linear_offset +LOOP_HEIGHT_2_WIDTH: + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + + and r14, r6, #0x3 @ temp4 = j&0x3@ + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4@ + add r7, r1, r7 + + ldrh r14, [r7] + strh r14, [r9], #2 + + ldr r14, [sp, #48] @ right + add r6, r6, #2 @ j=j+2 + sub r14, r2, r14 @ j<yuv420_width-right + cmp r6, r14 + blt LOOP_HEIGHT_2_WIDTH + + ldr r14, [sp, #52] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r3, r14 @ i<yuv420_height-buttom + cmp r5, r14 + blt LOOP_HEIGHT_2 + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + +MEMCOPY_UNDER_64: @ count=r10, src=r11 + cmp r10, #32 + add r9, r0, r9 @ r9 = yuv420_dest+linear_offset + blt MEMCOPY_UNDER_32 + vld1.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + sub r10, r10, #32 + cmp r10, #0 + vst1.8 {q0, q1}, [r9]! @ load {nv12t_src+tiled_offset+temp1, 64} + beq MEMCOPY_UNDER_END +MEMCOPY_UNDER_32: + cmp r10, #16 + blt MEMCOPY_UNDER_16 + vld1.8 {q0}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + sub r10, r10, #16 + cmp r10, #0 + vst1.8 {q0}, [r9]! @ load {nv12t_src+tiled_offset+temp1, 64} + beq MEMCOPY_UNDER_END +MEMCOPY_UNDER_16: + ldrb r12, [r11], #1 + strb r12, [r9], #1 + subs r10, r10, #1 + bne MEMCOPY_UNDER_16 + +MEMCOPY_UNDER_END: + and r10, r6, #0x3F @ temp1 = left(==j)&0x3F + cmp r10, #0 + mov pc, lr + +tile_4x2_read_asm: +LFB0: + add ip, r3, #32 + sub r0, r0, #1 + cmp r1, ip + cmple r3, r1 + mov ip, r2, asr #2 + mov r0, r0, asr #7 + stmfd sp!, {r4, r5, lr} +LCFI0: + add r0, r0, #1 + bge L2 + sub r1, r1, #1 + tst r1, #32 + bne L2 + tst r3, #32 + bne L2 + mov r4, r2, asr #7 + and r1, r3, #31 + eor r4, r4, r3, asr #5 + ubfx r3, r3, #6, #8 + tst r4, #1 + ubfx r4, r2, #8, #6 + and ip, ip, #15 + mov r2, r2, asr #6 + mla r3, r0, r3, r4 + orr r1, ip, r1, asl #4 + b L9 +L2: + mov r2, ip, asr #5 + and r4, r3, #31 + eor r1, r2, r3, asr #5 + and r5, r2, #127 + ubfx r3, r3, #6, #8 + tst r1, #1 + and r1, ip, #15 + mov r2, ip, asr #4 + mla r3, r0, r3, r5 + orr r1, r1, r4, asl #4 +L9: + andne r2, r2, #1 + andeq r2, r2, #1 + orrne r2, r2, #2 + mov r1, r1, asl #2 + orr r3, r1, r3, asl #13 + orr r0, r3, r2, asl #11 + ldmfd sp!, {r4, r5, pc} +LFE0: + .fnend + diff --git a/exynos4/hal/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s b/exynos4/hal/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s new file mode 100644 index 0000000..cdd101e --- /dev/null +++ b/exynos4/hal/libswconverter/csc_tiled_to_linear_deinterleave_crop_neon.s @@ -0,0 +1,786 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file csc_tiled_to_linear_deinterleave_crop_neon.s + * @brief SEC_OMX specific define + * @author ShinWon Lee (shinwon.lee@samsung.com) + * @version 1.0 + * @history + * 2012.02.01 : Create + */ + +/* + * Converts and Deinterleaves tiled data to linear + * Crops left, top, right, buttom + * 1. UV of NV12T to UV of YUV420P + * + * @param yuv420_u_dest + * U plane address of YUV420P[out] + * + * @param yuv420_v_dest + * V plane address of YUV420P[out] + * + * @param nv12t_src + * UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left. It should be even. + * + * @param top + * Crop size of top. It should be even. + * + * @param right + * Crop size of right. It should be even. + * + * @param buttom + * Crop size of buttom. It should be even. + */ + + .arch armv7-a + .text + .global csc_tiled_to_linear_deinterleave_crop_neon + .type csc_tiled_to_linear_deinterleave_crop_neon, %function +csc_tiled_to_linear_deinterleave_crop_neon: + .fnstart + + @r0 yuv420_u_dest + @r1 yuv420_v_dest + @r2 nv12t_src + @r3 yuv420_width + @r4 yuv420_height + @r5 i + @r6 j + @r7 tiled_offset + @r8 tiled_offset1 + @r9 linear_offset + @r10 temp1 + @r11 temp2 + @r12 temp3 + @r14 temp4 + + stmfd sp!, {r4-r12,r14} @ backup registers + + ldr r4, [sp, #40] @ r4 = yuv420_height + + ldr r12, [sp, #52] @ r12 = right + ldr r10, [sp, #44] @ r10 = left + sub r12, r3, r12 @ temp3 = yuv420_width-right@ + sub r10, r12, r10 @ temp1 = temp3-left@ + cmp r10, #256 @ if (temp1 >= 256) + blt LOOP_HEIGHT_64_START + + ldr r5, [sp, #48] @ top +LOOP_HEIGHT_256: + ldr r6, [sp, #44] @ j = left + mov r14, r5, asr #5 @ temp4 = i>>5 + bic r12, r6, #0xFF @ temp3 = (j>>8)<<8 + mov r12, r12, asr #6 @ temp3 = temp3>>6 + and r11, r14, #0x1 @ if (temp4 & 0x1) + cmp r11, #0x1 + bne LOOP_HEIGHT_256_GET_TILED_EVEN +LOOP_HEIGHT_256_GET_TILED_ODD: + sub r7, r14, #1 @ tiled_offset = temp4-1 + add r10, r3, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset*(temp1>>6) + mul r7, r7, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + add r7, r7, #2 @ tiled_offset = tiled_offset+2 + bic r10, r12, #0x3 @ temp1 = (temp3>>2)<<2 + add r7, r7, r10 @ tiled_offset = tiled_offset+temp1 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN: + add r11, r4, #31 @ temp2 = ((yuv420_height+31)>>5)<<5 + bic r11, r11, #0x1F + add r10, r5, #32 @ if ((i+32)<temp2) + cmp r10, r11 + bge LOOP_HEIGHT_256_GET_TILED_EVEN1 + add r10, r12, #2 @ temp1 = temp3+2 + bic r10, r10, #0x3 @ temp1 = (temp1>>2)<<2 + add r7, r12, r10 @ tiled_offset = temp3+temp1@ + add r10, r3, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = tiled_offset+temp4*(temp1>>6) + mla r7, r14, r10, r7 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #12288 @ tiled_offset1 = tiled_offset+2048*6 + mov r14, #8 + b LOOP_HEIGHT_256_GET_TILED_END + +LOOP_HEIGHT_256_GET_TILED_EVEN1: + add r10, r3, #127 @ temp1 = ((yuv420_width+127)>>7)<<7 + bic r10, r10, #0x7F + mov r10, r10, asr #6 @ tiled_offset = temp4*(temp1>>6) + mul r7, r14, r10 + add r7, r7, r12 @ tiled_offset = tiled_offset+temp3 + mov r7, r7, lsl #11 @ tiled_offset = tiled_offset<<11 + add r8, r7, #4096 @ tiled_offset1 = tiled_offset+2048*2 + mov r14, #4 + +LOOP_HEIGHT_256_GET_TILED_END: + + ldr r12, [sp, #52] @ right + ldr r9, [sp, #48] @ top + and r10, r5, #0x1F @ temp1 = i&0x1F + add r7, r7, r10, lsl #6 @ tiled_offset = tiled_offset+64*(temp1) + add r8, r8, r10, lsl #6 @ tiled_offset1 = tiled_offset1+64*(temp1) + sub r11, r3, r6 @ temp2 = yuv420_width-left(==j)-right + sub r11, r11, r12 + sub r9, r5, r9 @ linear_offset = temp2*(i-top)/2@ + mul r9, r11, r9 + mov r9, r9, asr #1 + add r12, r6, #256 @ temp3 = ((j+256)>>8)<<8@ + bic r12, r12, #0xFF + sub r12, r12, r6 @ temp3 = temp3-j@ + and r10, r6, #0x3F @ temp1 = left(==j)&0x3F + + cmp r12, #192 @ if (temp3 > 192) + ble LOOP_HEIGHT_256_LEFT_192 + add r11, r2, r7 @ r11 = nv12t_src+tiled_offset+temp1 + add r11, r11, r10 + pld [r11] + add r12, r2, r7 @ r12 = nv12t_src+tiled_offset+2048 + pld [r11, #32] + add r12, r12, #2048 + pld [r12] + cmp r10, #0 + pld [r12, #32] + stmnefd sp!, {r8-r12, r14} @ backup registers + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_256_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r11]! + vst1.8 {q2}, [r11]! + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r11]! + vst1.8 {q3}, [r11]! +LOOP_HEIGHT_256_LEFT_256_64: + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1 + pld [r11] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r11, #32] + vld2.8 {q6, q7}, [r12] + add r12, r11, #2048 @ r12 = nv12t_src+tiled_offset1+2048 + pld [r12] + vld2.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1, 64} + pld [r12, #32] + vld2.8 {q10, q11}, [r11] + vld2.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld2.8 {q14, q15}, [r12] + + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q4}, [r11]! + vst1.8 {q6}, [r11]! + vst1.8 {q8}, [r11]! + vst1.8 {q10}, [r11]! + vst1.8 {q12}, [r11]! + vst1.8 {q14}, [r11]! + + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q5}, [r11]! + vst1.8 {q7}, [r11]! + vst1.8 {q9}, [r11]! + vst1.8 {q11}, [r11]! + vst1.8 {q13}, [r11]! + vst1.8 {q15}, [r11]! + + add r9, r9, #128 + sub r9, r9, r10, asr #1 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_192: + cmp r12, #128 @ if (temp3 > 128) + ble LOOP_HEIGHT_256_LEFT_128 + add r11, r2, r7 @ r11 = nv12t_src+tiled_offset+2048+temp1 + add r11, r11, r10 + add r11, r11, #2048 + pld [r11] + add r12, r2, r8 @ r12 = nv12t_src+tiled_offset1 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r8-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_192_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+2048+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r11]! + vst1.8 {q2}, [r11]! + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r11]! + vst1.8 {q3}, [r11]! +LOOP_HEIGHT_256_LEFT_192_64: + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1+2048 + add r11, r11, #2048 + pld [r11] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + pld [r11, #32] + vld2.8 {q6, q7}, [r12] + vld2.8 {q8, q9}, [r11]! @ load {nv12t_src+tiled_offset1+2048, 64} + vld2.8 {q10, q11}, [r11] + + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q4}, [r11]! + vst1.8 {q6}, [r11]! + vst1.8 {q8}, [r11]! + vst1.8 {q10}, [r11]! + + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q5}, [r11]! + vst1.8 {q7}, [r11]! + vst1.8 {q9}, [r11]! + vst1.8 {q11}, [r11]! + + add r9, r9, #96 + sub r9, r9, r10, asr #1 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_128: + cmp r12, #64 @ if (temp3 > 64) + ble LOOP_HEIGHT_256_LEFT_64 + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1+temp1 + add r11, r11, r10 + pld [r11] + add r12, r2, r8 @ r12 = nv12t_src+tiled_offset1 + add r12, r12, #2048 + pld [r11, #32] + cmp r10, #0 + pld [r12] + stmnefd sp!, {r8-r12, r14} @ backup registers + pld [r12, #32] + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_128_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r11]! + vst1.8 {q2}, [r11]! + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r11]! + vst1.8 {q3}, [r11]! +LOOP_HEIGHT_256_LEFT_128_64: + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset1, 64} + vld2.8 {q6, q7}, [r12] + + add r11, r0, r9 @ r11 = yuv420_u_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q4}, [r11]! + vst1.8 {q6}, [r11]! + + add r11, r1, r9 @ r11 = yuv420_v_dest+linear_offset+32-temp1/2 + add r11, r11, #32 + sub r11, r11, r10, asr #1 + vst1.8 {q5}, [r11]! + vst1.8 {q7}, [r11]! + + add r9, r9, #64 + sub r9, r9, r10, asr #1 + b LOOP_HEIGHT_256_LEFT_END + +LOOP_HEIGHT_256_LEFT_64: + add r11, r2, r8 @ r11 = nv12t_src+tiled_offset1+2048+temp1 + add r11, r11, #2048 + add r11, r11, r10 + cmp r10, #0 + pld [r11] + stmnefd sp!, {r8-r12, r14} @ backup registers + pld [r11, #32] + rsbne r10, r10, #64 + blne INTERLEAVED_MEMCOPY_UNDER_64 + ldmnefd sp!, {r8-r12, r14} @ restore registers + bne LOOP_HEIGHT_256_LEFT_64_64 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset1+temp1, 64} + vld2.8 {q2, q3}, [r11] + add r11, r0, r9 @ r11 = yuv420_dest+linear_offset + vst1.8 {q0, q1}, [r11]! @ store {yuv420_dest+linear_offset, 64} + vst1.8 {q2, q3}, [r11]! +LOOP_HEIGHT_256_LEFT_64_64: + add r9, r9, #32 + sub r9, r9, r10, asr #1 + +LOOP_HEIGHT_256_LEFT_END: + + ldr r12, [sp, #52] @ right + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r2, r7 @ r10 = nv12t_src+tiled_offset + pld [r10] + bic r6, r6, #0xFF @ j = (left>>8)<<8 + pld [r10, #32] + add r6, r6, #256 @ j = j + 256 + sub r11, r3, r12 @ temp2 = yuv420_width-right-256 + sub r11, r11, #256 + cmp r6, r11 + bgt LOOP_HEIGHT_256_WIDTH_END + +LOOP_HEIGHT_256_WIDTH: + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset, 64} + pld [r12, #32] + vld2.8 {q2, q3}, [r10] + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + add r10, r2, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld2.8 {q6, q7}, [r12] + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + pld [r12] + vld2.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r12, #32] + vld2.8 {q10, q11}, [r10] + + add r7, r7, r14, lsl #11 @ tiled_offset = tiled_offset+temp4*2048 + add r10, r2, r7 + pld [r10] + vld2.8 {q12, q13}, [r12]! @ load {nv12t_src+tiled_offset+2048, 64} + pld [r10, #32] + vld2.8 {q14, q15}, [r12] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + vst1.8 {q4}, [r12]! + vst1.8 {q6}, [r12]! + vst1.8 {q8}, [r12]! + vst1.8 {q10}, [r12]! + vst1.8 {q12}, [r12]! + vst1.8 {q14}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + vst1.8 {q5}, [r12]! + vst1.8 {q7}, [r12]! + vst1.8 {q9}, [r12]! + vst1.8 {q11}, [r12]! + vst1.8 {q13}, [r12]! + vst1.8 {q15}, [r12]! + add r9, r9, #128 @ linear_offset = linear_offset+128 + + add r12, r10, #2048 @ r12 = nv12t_src+tiled_offset+2048 + + add r6, r6, #256 @ j=j+256 + cmp r6, r11 @ j<=temp2 + ble LOOP_HEIGHT_256_WIDTH + +LOOP_HEIGHT_256_WIDTH_END: + + add r8, r8, r14, lsl #11 @ tiled_offset1 = tiled_offset1+temp4*2048 + ldr r14, [sp, #52] @ right + sub r11, r3, r6 @ temp2 = yuv420_width-right-j + sub r11, r11, r14 + cmp r11, #0 + beq LOOP_HEIGHT_256_RIGHT_END + cmp r11, #192 + ble LOOP_HEIGHT_256_RIGHT_192 + add r12, r10, #2048 + pld [r12] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld2.8 {q2, q3}, [r10] + + add r10, r2, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r10] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r10, #32] + vld2.8 {q6, q7}, [r12] + + add r14, r10, #2048 @ r10 = nv12t_src+tiled_offset1+2048 + pld [r14] + vld2.8 {q8, q9}, [r10]! @ load {nv12t_src+tiled_offset1} + pld [r14, #32] + vld2.8 {q10, q11}, [r10] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + vst1.8 {q4}, [r12]! + vst1.8 {q6}, [r12]! + vst1.8 {q8}, [r12]! + vst1.8 {q10}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + vst1.8 {q5}, [r12]! + vst1.8 {q7}, [r12]! + vst1.8 {q9}, [r12]! + vst1.8 {q11}, [r12]! + add r9, r9, #96 @ linear_offset = linear_offset+96 + + stmfd sp!, {r8-r12, r14} @ backup registers + sub r10, r11, #192 + mov r11, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_192: + cmp r11, #128 + ble LOOP_HEIGHT_256_RIGHT_128 + add r12, r10, #2048 + pld [r12] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r12, #32] + vld2.8 {q2, q3}, [r10] + + add r14, r2, r8 @ r10 = nv12t_src+tiled_offset1 + pld [r14] + vld2.8 {q4, q5}, [r12]! @ load {nv12t_src+tiled_offset+2048} + pld [r14, #32] + vld2.8 {q6, q7}, [r12] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + vst1.8 {q4}, [r12]! + vst1.8 {q6}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + vst1.8 {q5}, [r12]! + vst1.8 {q7}, [r12]! + add r9, r9, #64 @ linear_offset = linear_offset+64 + + stmfd sp!, {r8-r12, r14} @ backup registers + sub r10, r11, #128 + mov r11, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_128: + cmp r11, #64 + ble LOOP_HEIGHT_256_RIGHT_64 + add r14, r10, #2048 + pld [r14] + vld2.8 {q0, q1}, [r10]! @ load {nv12t_src+tiled_offset} + pld [r14, #32] + vld2.8 {q2, q3}, [r10] + + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12]! + vst1.8 {q2}, [r12]! + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12]! + vst1.8 {q3}, [r12]! + add r9, r9, #32 @ linear_offset = linear_offset+32 + + stmfd sp!, {r8-r12, r14} @ backup registers + sub r10, r11, #64 + mov r11, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + b LOOP_HEIGHT_256_RIGHT_END + +LOOP_HEIGHT_256_RIGHT_64: + stmfd sp!, {r8-r12, r14} @ backup registers + mov r14, r11 + mov r11, r10 + mov r10, r14 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r8-r12, r14} @ restore registers + +LOOP_HEIGHT_256_RIGHT_END: + + ldr r14, [sp, #56] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r4, r14 @ i<yuv420_height-buttom + cmp r5, r14 + blt LOOP_HEIGHT_256 + b RESTORE_REG + +LOOP_HEIGHT_64_START: + cmp r10, #64 @ if (temp1 >= 64) + blt LOOP_HEIGHT_2_START + + ldr r5, [sp, #48] @ i = top +LOOP_HEIGHT_64: + ldr r6, [sp, #44] @ j = left + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + ldr r9, [sp, #48] @ linear_offset = top + ldr r12, [sp, #52] @ r12 = right + add r11, r6, #64 @ temp2 = ((j+64)>>6)<<6 + bic r11, r11, #0x3F + sub r11, r11, r6 @ temp2 = temp2-j + sub r12, r3, r12 @ temp3 = yuv420_width-right + sub r14, r12, r6 @ temp4 = temp3-left + sub r9, r5, r9 @ linear_offset = temp4*(i-top)/2 + mul r9, r9, r14 + mov r9, r9, asr #1 + and r14, r6, #0x3 @ temp4 = j&0x3 + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r2, r7 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + add r9, r9, r11, asr #1 @ linear_offset = linear_offset+temp2/2 + add r6, r6, r11 @ j = j+temp2@ + + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_1 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r2, r7 + vld2.8 {q0, q1}, [r7]! + vld2.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0}, [r7]! + vst1.8 {q2}, [r7] + add r7, r1, r9 + vst1.8 {q1}, [r7]! + vst1.8 {q3}, [r7] + add r9, r9, #32 + add r6, r6, #64 + +LOOP_HEIGHT_64_1: + add r14, r6, #64 + cmp r14, r12 + bgt LOOP_HEIGHT_64_2 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + add r7, r2, r7 + vld2.8 {q0, q1}, [r7]! + vld2.8 {q2, q3}, [r7] + add r7, r0, r9 + vst1.8 {q0}, [r7]! + vst1.8 {q2}, [r7] + add r7, r1, r9 + vst1.8 {q1}, [r7]! + vst1.8 {q3}, [r7] + add r9, r9, #32 + add r6, r6, #64 + +LOOP_HEIGHT_64_2: + cmp r6, r12 + bge LOOP_HEIGHT_64_3 + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r3 + mov r1, r4 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + sub r11, r12, r6 + stmfd sp!, {r9-r12} @ backup parameters + mov r10, r11 + add r11, r2, r7 + bl INTERLEAVED_MEMCOPY_UNDER_64 + ldmfd sp!, {r9-r12} @ restore parameters + +LOOP_HEIGHT_64_3: + + ldr r14, [sp, #56] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r4, r14 @ i<yuv420_height-buttom + cmp r5, r14 + blt LOOP_HEIGHT_64 + b RESTORE_REG + +LOOP_HEIGHT_2_START: + + ldr r5, [sp, #48] @ i = top +LOOP_HEIGHT_2: + + ldr r12, [sp, #52] @ linear_offset = right + ldr r6, [sp, #44] @ j = left + ldr r9, [sp, #48] @ linear_offset = top + + sub r12, r3, r12 @ temp3 = yuv420_width-right + sub r14, r12, r6 @ temp4 = temp3-left@ + sub r9, r5, r9 @ r9 = i-top + mul r9, r14, r9 @ temp4*(i-top) + mov r9, r9, lsr #1 @ linear_offset = temp4*(i-top)/2 + add r11, r0, r9 + add r12, r1, r9 +LOOP_HEIGHT_2_WIDTH: + stmfd sp!, {r0-r3, r12} @ backup parameters + mov r0, r2 + mov r1, r3 + mov r2, r6 + mov r3, r5 + bl tile_4x2_read_asm + mov r7, r0 + ldmfd sp!, {r0-r3, r12} @ restore parameters + + and r14, r6, #0x3 @ temp4 = j&0x3@ + add r7, r7, r14 @ tiled_offset = tiled_offset+temp4@ + add r7, r2, r7 + + ldrh r14, [r7] + strb r14, [r11], #1 + mov r14, r14, lsr #8 + strb r14, [r12], #1 + + ldr r14, [sp, #52] @ right + add r6, r6, #2 @ j=j+2 + sub r14, r3, r14 @ j<yuv420_width-right + cmp r6, r14 + blt LOOP_HEIGHT_2_WIDTH + + ldr r14, [sp, #56] @ buttom + add r5, r5, #1 @ i=i+1 + sub r14, r4, r14 @ i<yuv420_height-buttom + cmp r5, r14 + blt LOOP_HEIGHT_2 + +RESTORE_REG: + ldmfd sp!, {r4-r12,r15} @ restore registers + +INTERLEAVED_MEMCOPY_UNDER_64: @ count=r10, src=r11 + cmp r10, #32 + blt INTERLEAVED_MEMCOPY_UNDER_32 + vld2.8 {q0, q1}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + sub r10, r10, #32 + cmp r10, #0 + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {q0}, [r12] @ load {nv12t_src+tiled_offset+temp1, 64} + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {q1}, [r12] @ load {nv12t_src+tiled_offset+temp1, 64} + add r9, r9, #16 + beq INTERLEAVED_MEMCOPY_UNDER_END +INTERLEAVED_MEMCOPY_UNDER_32: + cmp r10, #16 + blt INTERLEAVED_MEMCOPY_UNDER_16 + vld2.8 {q0}, [r11]! @ load {nv12t_src+tiled_offset+temp1, 64} + sub r10, r10, #16 + cmp r10, #0 + add r12, r0, r9 @ r12 = yuv420_u_dest+linear_offset + vst1.8 {d0}, [r12]! @ load {nv12t_src+tiled_offset+temp1, 64} + add r12, r1, r9 @ r12 = yuv420_v_dest+linear_offset + vst1.8 {d1}, [r12]! @ load {nv12t_src+tiled_offset+temp1, 64} + add r9, r9, #8 + beq INTERLEAVED_MEMCOPY_UNDER_END +INTERLEAVED_MEMCOPY_UNDER_16: + ldrh r12, [r11], #2 + add r8, r0, r9 @ r8 = yuv420_u_dest+linear_offset + strb r12, [r8] + add r8, r1, r9 @ r8 = yuv420_v_dest+linear_offset + mov r12, r12, lsr #8 + strb r12, [r8] + subs r10, r10, #2 + add r9, r9, #1 + bne INTERLEAVED_MEMCOPY_UNDER_16 + +INTERLEAVED_MEMCOPY_UNDER_END: + and r10, r6, #0x3F @ temp1 = left(==j)&0x3F + cmp r10, #0 + mov pc, lr + +tile_4x2_read_asm: +LFB0: + add ip, r3, #32 + sub r0, r0, #1 + cmp r1, ip + cmple r3, r1 + mov ip, r2, asr #2 + mov r0, r0, asr #7 + stmfd sp!, {r4, r5, lr} +LCFI0: + add r0, r0, #1 + bge L2 + sub r1, r1, #1 + tst r1, #32 + bne L2 + tst r3, #32 + bne L2 + mov r4, r2, asr #7 + and r1, r3, #31 + eor r4, r4, r3, asr #5 + ubfx r3, r3, #6, #8 + tst r4, #1 + ubfx r4, r2, #8, #6 + and ip, ip, #15 + mov r2, r2, asr #6 + mla r3, r0, r3, r4 + orr r1, ip, r1, asl #4 + b L9 +L2: + mov r2, ip, asr #5 + and r4, r3, #31 + eor r1, r2, r3, asr #5 + and r5, r2, #127 + ubfx r3, r3, #6, #8 + tst r1, #1 + and r1, ip, #15 + mov r2, ip, asr #4 + mla r3, r0, r3, r5 + orr r1, r1, r4, asl #4 +L9: + andne r2, r2, #1 + andeq r2, r2, #1 + orrne r2, r2, #2 + mov r1, r1, asl #2 + orr r3, r1, r3, asl #13 + orr r0, r3, r2, asl #11 + ldmfd sp!, {r4, r5, pc} +LFE0: + .fnend + diff --git a/exynos4/hal/libswconverter/swconvertor.c b/exynos4/hal/libswconverter/swconvertor.c new file mode 100644 index 0000000..043add2 --- /dev/null +++ b/exynos4/hal/libswconverter/swconvertor.c @@ -0,0 +1,1828 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file swconvertor.c + * + * @brief SEC_OMX specific define + * + * @author ShinWon Lee (shinwon.lee@samsung.com) + * + * @version 1.0 + * + * @history + * 2012.02.01 : Create + */ + +#include "stdio.h" +#include "stdlib.h" +#include "swconverter.h" + +/* + * Get tiled address of position(x,y) + * + * @param x_size + * width of tiled[in] + * + * @param y_size + * height of tiled[in] + * + * @param x_pos + * x position of tield[in] + * + * @param src_size + * y position of tield[in] + * + * @return + * address of tiled data + */ +static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) +{ + int pixel_x_m1, pixel_y_m1; + int roundup_x, roundup_y; + int linear_addr0, linear_addr1, bank_addr ; + int x_addr; + int trans_addr; + + pixel_x_m1 = x_size -1; + pixel_y_m1 = y_size -1; + + roundup_x = ((pixel_x_m1 >> 7) + 1); + roundup_y = ((pixel_x_m1 >> 6) + 1); + + x_addr = x_pos >> 2; + + if ((y_size <= y_pos+32) && ( y_pos < y_size) && + (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) { + linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } else { + linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } + + linear_addr0 = linear_addr0 << 2; + trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0; + + return trans_addr; +} + +/* + * De-interleaves src to dest1, dest2 + * + * @param dest1 + * Address of de-interleaved data[out] + * + * @param dest2 + * Address of de-interleaved data[out] + * + * @param src + * Address of interleaved data[in] + * + * @param src_size + * Size of interleaved data[in] + */ +void csc_deinterleave_memcpy( + unsigned char *dest1, + unsigned char *dest2, + unsigned char *src, + unsigned int src_size) +{ + unsigned int i = 0; + for(i=0; i<src_size/2; i++) { + dest1[i] = src[i*2]; + dest2[i] = src[i*2+1]; + } +} + +/* + * Interleaves src1, src2 to dest + * + * @param dest + * Address of interleaved data[out] + * + * @param src1 + * Address of de-interleaved data[in] + * + * @param src2 + * Address of de-interleaved data[in] + * + * @param src_size + * Size of de-interleaved data[in] + */ +void csc_interleave_memcpy( + unsigned char *dest, + unsigned char *src1, + unsigned char *src2, + unsigned int src_size) +{ + unsigned int i = 0; + for(i=0; i<src_size; i++) { + dest[i * 2] = src1[i]; + dest[i * 2 + 1] = src2[i]; + } +} + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_tiled_to_linear_crop( + unsigned char *yuv420_dest, + unsigned char *nv12t_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_offset = 0, tiled_offset1 = 0; + unsigned int linear_offset = 0; + unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0; + + temp3 = yuv420_width-right; + temp1 = temp3-left; + /* real width is greater than or equal 256 */ + if (temp1 >= 256) { + for (i=top; i<yuv420_height-buttom; i=i+1) { + j = left; + temp3 = (j>>8)<<8; + temp3 = temp3>>6; + temp4 = i>>5; + if (temp4 & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = temp4-1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset+2; + temp1 = (temp3>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 8; + } else { + temp2 = ((yuv420_height+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = temp3+2; + temp1 = (temp1>>2)<<2; + tiled_offset = temp3+temp1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset+temp4*(temp1>>6); + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*6; + temp4 = 8; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = temp4*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 4; + } + } + + temp1 = i&0x1F; + tiled_offset = tiled_offset+64*(temp1); + tiled_offset1 = tiled_offset1+64*(temp1); + temp2 = yuv420_width-left-right; + linear_offset = temp2*(i-top); + temp3 = ((j+256)>>8)<<8; + temp3 = temp3-j; + temp1 = left&0x3F; + if (temp3 > 192) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1); + temp2 = ((left+63)>>6)<<6; + temp3 = ((yuv420_width-right)>>6)<<6; + if (temp2 == temp3) { + temp2 = yuv420_width-right-(64-temp1); + } + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+256-temp1; + } else if (temp3 > 128) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1); + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+192-temp1; + } else if (temp3 > 64) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1); + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128-temp1; + } else if (temp3 > 0) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1); + linear_offset = linear_offset+64-temp1; + } + + tiled_offset = tiled_offset+temp4*2048; + j = (left>>8)<<8; + j = j + 256; + temp2 = yuv420_width-right-256; + for (; j<=temp2; j=j+256) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + tiled_offset1 = tiled_offset1+temp4*2048; + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64); + tiled_offset = tiled_offset+temp4*2048; + memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+256; + } + + tiled_offset1 = tiled_offset1+temp4*2048; + temp2 = yuv420_width-right-j; + if (temp2 > 192) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192); + } else if (temp2 > 128) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128); + } else if (temp2 > 64) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64); + } else { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + } + } + } else if (temp1 >= 64) { + for (i=top; i<(yuv420_height-buttom); i=i+1) { + j = left; + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp2 = ((j+64)>>6)<<6; + temp2 = temp2-j; + linear_offset = temp1*(i-top); + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + linear_offset = linear_offset+temp2; + j = j+temp2; + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + linear_offset = linear_offset+64; + j = j+64; + } + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + linear_offset = linear_offset+64; + j = j+64; + } + if (j < temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp2 = temp3-j; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + } + } + } else { + for (i=top; i<(yuv420_height-buttom); i=i+1) { + linear_offset = temp1*(i-top); + for (j=left; j<(yuv420_width-right); j=j+2) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2); + linear_offset = linear_offset+2; + } + } + } +} + +/* + * Converts and Deinterleaves tiled data to linear + * Crops left, top, right, buttom + * 1. UV of NV12T to UV of YUV420P + * + * @param yuv420_u_dest + * U plane address of YUV420P[out] + * + * @param yuv420_v_dest + * V plane address of YUV420P[out] + * + * @param nv12t_src + * UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_tiled_to_linear_deinterleave_crop( + unsigned char *yuv420_u_dest, + unsigned char *yuv420_v_dest, + unsigned char *nv12t_uv_src, + unsigned int yuv420_width, + unsigned int yuv420_uv_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_offset = 0, tiled_offset1 = 0; + unsigned int linear_offset = 0; + unsigned int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0; + + temp3 = yuv420_width-right; + temp1 = temp3-left; + /* real width is greater than or equal 256 */ + if (temp1 >= 256) { + for (i=top; i<yuv420_uv_height-buttom; i=i+1) { + j = left; + temp3 = (j>>8)<<8; + temp3 = temp3>>6; + temp4 = i>>5; + if (temp4 & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = temp4-1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset+2; + temp1 = (temp3>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 8; + } else { + temp2 = ((yuv420_uv_height+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = temp3+2; + temp1 = (temp1>>2)<<2; + tiled_offset = temp3+temp1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset+temp4*(temp1>>6); + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*6; + temp4 = 8; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = temp4*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 4; + } + } + + temp1 = i&0x1F; + tiled_offset = tiled_offset+64*(temp1); + tiled_offset1 = tiled_offset1+64*(temp1); + temp2 = yuv420_width-left-right; + linear_offset = temp2*(i-top)/2; + temp3 = ((j+256)>>8)<<8; + temp3 = temp3-j; + temp1 = left&0x3F; + if (temp3 > 192) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, yuv420_v_dest+linear_offset, nv12t_uv_src+tiled_offset+temp1, 64-temp1); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2), + yuv420_v_dest+linear_offset+(32-temp1/2), + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2), + yuv420_v_dest+linear_offset+(64-temp1/2), + nv12t_uv_src+tiled_offset1, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(96-temp1/2), + yuv420_v_dest+linear_offset+(96-temp1/2), + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128-temp1/2; + } else if (temp3 > 128) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset+2048+temp1, 64-temp1); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2), + yuv420_v_dest+linear_offset+(32-temp1/2), + nv12t_uv_src+tiled_offset1, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(64-temp1/2), + yuv420_v_dest+linear_offset+(64-temp1/2), + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+96-temp1/2; + } else if (temp3 > 64) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset1+temp1, 64-temp1); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+(32-temp1/2), + yuv420_v_dest+linear_offset+(32-temp1/2), + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+64-temp1/2; + } else if (temp3 > 0) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset1+2048+temp1, 64-temp1); + linear_offset = linear_offset+32-temp1/2; + } + + tiled_offset = tiled_offset+temp4*2048; + j = (left>>8)<<8; + j = j + 256; + temp2 = yuv420_width-right-256; + for (; j<=temp2; j=j+256) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + tiled_offset1 = tiled_offset1+temp4*2048; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64, + yuv420_v_dest+linear_offset+64, + nv12t_uv_src+tiled_offset1, 64); + tiled_offset = tiled_offset+temp4*2048; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96, + yuv420_v_dest+linear_offset+96, + nv12t_uv_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128; + } + + tiled_offset1 = tiled_offset1+temp4*2048; + temp2 = yuv420_width-right-j; + if (temp2 > 192) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64, + yuv420_v_dest+linear_offset+64, + nv12t_uv_src+tiled_offset1, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+96, + yuv420_v_dest+linear_offset+96, + nv12t_uv_src+tiled_offset1+2048, temp2-192); + } else if (temp2 > 128) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+64, + yuv420_v_dest+linear_offset+64, + nv12t_uv_src+tiled_offset1, temp2-128); + } else if (temp2 > 64) { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset+32, + yuv420_v_dest+linear_offset+32, + nv12t_uv_src+tiled_offset+2048, temp2-64); + } else { + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, temp2); + } + } + } else if (temp1 >= 64) { + for (i=top; i<(yuv420_uv_height-buttom); i=i+1) { + j = left; + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + temp2 = ((j+64)>>6)<<6; + temp2 = temp2-j; + temp3 = yuv420_width-right; + temp4 = temp3-left; + linear_offset = temp4*(i-top)/2; + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, temp2); + linear_offset = linear_offset+temp2/2; + j = j+temp2; + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + linear_offset = linear_offset+32; + j = j+64; + } + if ((j+64) <= temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 64); + linear_offset = linear_offset+32; + j = j+64; + } + if (j < temp3) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + temp1 = temp3-j; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, temp1); + } + } + } else { + for (i=top; i<(yuv420_uv_height-buttom); i=i+1) { + temp3 = yuv420_width-right; + temp4 = temp3-left; + linear_offset = temp4*(i-top)/2; + for (j=left; j<(yuv420_width-right); j=j+2) { + tiled_offset = tile_4x2_read(yuv420_width, yuv420_uv_height, j, i); + temp3 = j&0x3; + tiled_offset = tiled_offset+temp3; + csc_deinterleave_memcpy(yuv420_u_dest+linear_offset, + yuv420_v_dest+linear_offset, + nv12t_uv_src+tiled_offset, 2); + linear_offset = linear_offset+1; + } + } + } +} + +/* + * Converts linear data to tiled + * Crops left, top, right, buttom + * 1. Y of YUV420P to Y of NV12T + * 2. Y of YUV420S to Y of NV12T + * 3. UV of YUV420S to UV of NV12T + * + * @param nv12t_dest + * Y or UV plane address of NV12T[out] + * + * @param yuv420_src + * Y or UV plane address of YUV420P(S)[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_linear_to_tiled_crop( + unsigned char *nv12t_dest, + unsigned char *yuv420_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_x_index = 0, tiled_y_index = 0; + unsigned int aligned_x_size = 0, aligned_y_size = 0; + unsigned int tiled_offset = 0; + unsigned int temp1 = 0, temp2 = 0; + + aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5; + aligned_x_size = ((yuv420_width-left-right)>>6)<<6; + + for (i=0; i<aligned_y_size; i=i+32) { + for (j=0; j<aligned_x_size; j=j+64) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + memcpy(nv12t_dest+tiled_offset, yuv420_src+left+j+yuv420_width*(i+top), 64); + memcpy(nv12t_dest+tiled_offset+64*1, yuv420_src+left+j+yuv420_width*(i+top+1), 64); + memcpy(nv12t_dest+tiled_offset+64*2, yuv420_src+left+j+yuv420_width*(i+top+2), 64); + memcpy(nv12t_dest+tiled_offset+64*3, yuv420_src+left+j+yuv420_width*(i+top+3), 64); + memcpy(nv12t_dest+tiled_offset+64*4, yuv420_src+left+j+yuv420_width*(i+top+4), 64); + memcpy(nv12t_dest+tiled_offset+64*5, yuv420_src+left+j+yuv420_width*(i+top+5), 64); + memcpy(nv12t_dest+tiled_offset+64*6, yuv420_src+left+j+yuv420_width*(i+top+6), 64); + memcpy(nv12t_dest+tiled_offset+64*7, yuv420_src+left+j+yuv420_width*(i+top+7), 64); + memcpy(nv12t_dest+tiled_offset+64*8, yuv420_src+left+j+yuv420_width*(i+top+8), 64); + memcpy(nv12t_dest+tiled_offset+64*9, yuv420_src+left+j+yuv420_width*(i+top+9), 64); + memcpy(nv12t_dest+tiled_offset+64*10, yuv420_src+left+j+yuv420_width*(i+top+10), 64); + memcpy(nv12t_dest+tiled_offset+64*11, yuv420_src+left+j+yuv420_width*(i+top+11), 64); + memcpy(nv12t_dest+tiled_offset+64*12, yuv420_src+left+j+yuv420_width*(i+top+12), 64); + memcpy(nv12t_dest+tiled_offset+64*13, yuv420_src+left+j+yuv420_width*(i+top+13), 64); + memcpy(nv12t_dest+tiled_offset+64*14, yuv420_src+left+j+yuv420_width*(i+top+14), 64); + memcpy(nv12t_dest+tiled_offset+64*15, yuv420_src+left+j+yuv420_width*(i+top+15), 64); + memcpy(nv12t_dest+tiled_offset+64*16, yuv420_src+left+j+yuv420_width*(i+top+16), 64); + memcpy(nv12t_dest+tiled_offset+64*17, yuv420_src+left+j+yuv420_width*(i+top+17), 64); + memcpy(nv12t_dest+tiled_offset+64*18, yuv420_src+left+j+yuv420_width*(i+top+18), 64); + memcpy(nv12t_dest+tiled_offset+64*19, yuv420_src+left+j+yuv420_width*(i+top+19), 64); + memcpy(nv12t_dest+tiled_offset+64*20, yuv420_src+left+j+yuv420_width*(i+top+20), 64); + memcpy(nv12t_dest+tiled_offset+64*21, yuv420_src+left+j+yuv420_width*(i+top+21), 64); + memcpy(nv12t_dest+tiled_offset+64*22, yuv420_src+left+j+yuv420_width*(i+top+22), 64); + memcpy(nv12t_dest+tiled_offset+64*23, yuv420_src+left+j+yuv420_width*(i+top+23), 64); + memcpy(nv12t_dest+tiled_offset+64*24, yuv420_src+left+j+yuv420_width*(i+top+24), 64); + memcpy(nv12t_dest+tiled_offset+64*25, yuv420_src+left+j+yuv420_width*(i+top+25), 64); + memcpy(nv12t_dest+tiled_offset+64*26, yuv420_src+left+j+yuv420_width*(i+top+26), 64); + memcpy(nv12t_dest+tiled_offset+64*27, yuv420_src+left+j+yuv420_width*(i+top+27), 64); + memcpy(nv12t_dest+tiled_offset+64*28, yuv420_src+left+j+yuv420_width*(i+top+28), 64); + memcpy(nv12t_dest+tiled_offset+64*29, yuv420_src+left+j+yuv420_width*(i+top+29), 64); + memcpy(nv12t_dest+tiled_offset+64*30, yuv420_src+left+j+yuv420_width*(i+top+30), 64); + memcpy(nv12t_dest+tiled_offset+64*31, yuv420_src+left+j+yuv420_width*(i+top+31), 64); + } + } + + for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+2) { + for (j=0; j<aligned_x_size; j=j+64) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + temp1 = i&0x1F; + memcpy(nv12t_dest+tiled_offset+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 64); + memcpy(nv12t_dest+tiled_offset+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 64); + } + } + + for (i=0; i<(yuv420_height-top-buttom); i=i+2) { + for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + temp1 = i&0x1F; + temp2 = j&0x3F; + memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1), yuv420_src+left+j+yuv420_width*(i+top), 2); + memcpy(nv12t_dest+tiled_offset+temp2+64*(temp1+1), yuv420_src+left+j+yuv420_width*(i+top+1), 2); + } + } + +} + +/* + * Converts and Interleaves linear to tiled + * Crops left, top, right, buttom + * 1. UV of YUV420P to UV of NV12T + * + * @param nv12t_uv_dest + * UV plane address of NV12T[out] + * + * @param yuv420p_u_src + * U plane address of YUV420P[in] + * + * @param yuv420p_v_src + * V plane address of YUV420P[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void csc_linear_to_tiled_interleave_crop( + unsigned char *nv12t_uv_dest, + unsigned char *yuv420_u_src, + unsigned char *yuv420_v_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom) +{ + unsigned int i, j; + unsigned int tiled_x_index = 0, tiled_y_index = 0; + unsigned int aligned_x_size = 0, aligned_y_size = 0; + unsigned int tiled_offset = 0; + unsigned int temp1 = 0, temp2 = 0; + + aligned_y_size = ((yuv420_height-top-buttom)>>5)<<5; + aligned_x_size = ((yuv420_width-left-right)>>6)<<6; + + for (i=0; i<aligned_y_size; i=i+32) { + for (j=0; j<aligned_x_size; j=j+64) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*1, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+1), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+1), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*2, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+2), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+2), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*3, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+3), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+3), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*4, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+4), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+4), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*5, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+5), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+5), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*6, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+6), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+6), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*7, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+7), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+7), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*8, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+8), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+8), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*9, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+9), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+9), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*10, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+10), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+10), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*11, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+11), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+11), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*12, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+12), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+12), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*13, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+13), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+13), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*14, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+14), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+14), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*15, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+15), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+15), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*16, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+16), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+16), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*17, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+17), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+17), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*18, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+18), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+18), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*19, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+19), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+19), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*20, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+20), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+20), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*21, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+21), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+21), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*22, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+22), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+22), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*23, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+23), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+23), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*24, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+24), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+24), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*25, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+25), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+25), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*26, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+26), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+26), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*27, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+27), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+27), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*28, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+28), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+28), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*29, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+29), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+29), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*30, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+30), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+30), 32); + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*31, + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top+31), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top+31), 32); + + } + } + + for (i=aligned_y_size; i<(yuv420_height-top-buttom); i=i+1) { + for (j=0; j<aligned_x_size; j=j+64) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + temp1 = i&0x1F; + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+64*(temp1), + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 32); + } + } + + for (i=0; i<(yuv420_height-top-buttom); i=i+1) { + for (j=aligned_x_size; j<(yuv420_width-left-right); j=j+2) { + tiled_offset = 0; + tiled_x_index = j>>6; + tiled_y_index = i>>5; + if (tiled_y_index & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = tiled_y_index-1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset+2; + temp1 = (tiled_x_index>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + } else { + temp2 = (((yuv420_height-top-buttom)+31)>>5)<<5; + if ((i+32)<temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = tiled_x_index+2; + temp1 = (temp1>>2)<<2; + tiled_offset = tiled_x_index+temp1; + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_offset+tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset<<11; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = (((yuv420_width-left-right)+127)>>7)<<7; + tiled_offset = tiled_y_index*(temp1>>6); + tiled_offset = tiled_offset+tiled_x_index; + tiled_offset = tiled_offset<<11; + } + } + temp1 = i&0x1F; + temp2 = j&0x3F; + csc_interleave_memcpy(nv12t_uv_dest+tiled_offset+temp2+64*(temp1), + yuv420_u_src+left/2+j/2+yuv420_width/2*(i+top), + yuv420_v_src+left/2+j/2+yuv420_width/2*(i+top), 1); + } + } + +} + + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_tiled_to_linear_crop_neon( + unsigned char *yuv420_dest, + unsigned char *nv12t_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts and Deinterleaves tiled data to linear + * Crops left, top, right, buttom + * 1. UV of NV12T to UV of YUV420P + * + * @param yuv420_u_dest + * U plane address of YUV420P[out] + * + * @param yuv420_v_dest + * V plane address of YUV420P[out] + * + * @param nv12t_src + * UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_tiled_to_linear_deinterleave_crop_neon( + unsigned char *yuv420_u_dest, + unsigned char *yuv420_v_dest, + unsigned char *nv12t_uv_src, + unsigned int yuv420_width, + unsigned int yuv420_uv_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts linear data to tiled + * Crops left, top, right, buttom + * 1. Y of YUV420P to Y of NV12T + * 2. Y of YUV420S to Y of NV12T + * 3. UV of YUV420S to UV of NV12T + * + * @param nv12t_dest + * Y or UV plane address of NV12T[out] + * + * @param yuv420_src + * Y or UV plane address of YUV420P(S)[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_linear_to_tiled_crop_neon( + unsigned char *nv12t_dest, + unsigned char *yuv420_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts and Interleaves linear to tiled + * Crops left, top, right, buttom + * 1. UV of YUV420P to UV of NV12T + * + * @param nv12t_uv_dest + * UV plane address of NV12T[out] + * + * @param yuv420p_u_src + * U plane address of YUV420P[in] + * + * @param yuv420p_v_src + * V plane address of YUV420P[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_uv_height + * Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +void csc_linear_to_tiled_interleave_crop_neon( + unsigned char *nv12t_uv_dest, + unsigned char *yuv420_u_src, + unsigned char *yuv420_v_src, + unsigned int yuv420_width, + unsigned int yuv420_height, + unsigned int left, + unsigned int top, + unsigned int right, + unsigned int buttom); + +/* + * Converts tiled data to linear. + * 1. y of nv12t to y of yuv420p + * 2. y of nv12t to y of yuv420s + * + * @param dst + * y address of yuv420[out] + * + * @param src + * y address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_tiled_to_linear_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear + * 1. uv of nv12t to y of yuv420s + * + * @param dst + * uv address of yuv420s[out] + * + * @param src + * uv address of nv12t[in] + * + * @param yuv420_width + * real width of yuv420s[in] + * + * @param yuv420_height + * real height of yuv420s[in] + * + */ +void csc_tiled_to_linear_uv( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop(uv_dst, uv_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear + * 1. uv of nt12t to uv of yuv420p + * + * @param u_dst + * u address of yuv420p[out] + * + * @param v_dst + * v address of yuv420p[out] + * + * @param uv_src + * uv address of nt12t[in] + * + * @param yuv420_width + * real width of yuv420p[in] + * + * @param yuv420_height + * real height of yuv420p[in] + */ +void csc_tiled_to_linear_uv_deinterleave( + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_deinterleave_crop(u_dst, v_dst, uv_src, width, height, + 0, 0, 0, 0); +} + +/* + * Converts linear data to tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_crop(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts and interleaves linear data to tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of nv12t[out] + * + * @param src + * u address of yuv420[in] + * + * @param src + * v address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv( + unsigned char *uv_dst, + unsigned char *u_src, + unsigned char *v_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_interleave_crop(uv_dst, u_src, v_src, width, height, + 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear for mfc 6.x + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * + * @param dst + * Y address of YUV420[out] + * + * @param src + * Y address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * Y: real height of YUV420[in] + * + */ +void csc_tiled_to_linear_y_neon( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear for mfc 6.x + * 1. UV of NV12T to Y of YUV420S + * + * @param u_dst + * UV plane address of YUV420P[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * (real height)/2 of YUV420[in] + */ +void csc_tiled_to_linear_uv_neon( + unsigned char *uv_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_crop_neon(uv_dst, uv_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts tiled data to linear for mfc 6.x + * Deinterleave src to u_dst, v_dst + * 1. UV of NV12T to Y of YUV420P + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * real width of YUV420[in] + * + * @param yuv420_height + * (real height)/2 of YUV420[in] + */ +void csc_tiled_to_linear_uv_deinterleave_neon( + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *uv_src, + unsigned int width, + unsigned int height) +{ + csc_tiled_to_linear_deinterleave_crop_neon(u_dst, v_dst, uv_src, width, height, + 0, 0, 0, 0); +} + +/* + * Converts linear data to tiled + * 1. y of yuv420 to y of nv12t + * + * @param dst + * y address of nv12t[out] + * + * @param src + * y address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * it should be even + * + * @param yuv420_height + * real height of yuv420[in] + * it should be even. + * + */ +void csc_linear_to_tiled_y_neon( + unsigned char *y_dst, + unsigned char *y_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_crop_neon(y_dst, y_src, width, height, 0, 0, 0, 0); +} + +/* + * Converts and interleaves linear data to tiled + * 1. uv of nv12t to uv of yuv420 + * + * @param dst + * uv address of nv12t[out] + * + * @param src + * u address of yuv420[in] + * + * @param src + * v address of yuv420[in] + * + * @param yuv420_width + * real width of yuv420[in] + * + * @param yuv420_height + * real height of yuv420[in] + * + */ +void csc_linear_to_tiled_uv_neon( + unsigned char *uv_dst, + unsigned char *u_src, + unsigned char *v_src, + unsigned int width, + unsigned int height) +{ + csc_linear_to_tiled_interleave_crop_neon(uv_dst, u_src, v_src, + width, height, 0, 0, 0, 0); +} + +/* + * Converts RGB565 to YUV420P + * + * @param y_dst + * Y plane address of YUV420P[out] + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420P( + unsigned char *y_dst, + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset1 = width * height; + unsigned int offset2 = width/2 * height/2; + + unsigned short int *pSrc = (unsigned short int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstU = (unsigned char *)u_dst; + unsigned char *pDstV = (unsigned char *)v_dst; + + unsigned int yIndex = 0; + unsigned int uIndex = 0; + unsigned int vIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x0000F800) >> 8; + G = (tmp & 0x000007E0) >> 3; + B = (tmp & 0x0000001F); + B = B << 3; + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstU[uIndex++] = (unsigned char)U; + pDstV[vIndex++] = (unsigned char)V; + } + } + } +} + +/* + * Converts RGB565 to YUV420SP + * + * @param y_dst + * Y plane address of YUV420SP[out] + * + * @param uv_dst + * UV plane address of YUV420SP[out] + * + * @param rgb_src + * Address of RGB565[in] + * + * @param width + * Width of RGB565[in] + * + * @param height + * Height of RGB565[in] + */ +void csc_RGB565_to_YUV420SP( + unsigned char *y_dst, + unsigned char *uv_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset = width * height; + + unsigned short int *pSrc = (unsigned short int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstUV = (unsigned char *)uv_dst; + + unsigned int yIndex = 0; + unsigned int uvIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x0000F800) >> 11; + R = R * 8; + G = (tmp & 0x000007E0) >> 5; + G = G * 4; + B = (tmp & 0x0000001F); + B = B * 8; + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstUV[uvIndex++] = (unsigned char)U; + pDstUV[uvIndex++] = (unsigned char)V; + } + } + } +} + +/* + * Converts ARGB8888 to YUV420P + * + * @param y_dst + * Y plane address of YUV420P[out] + * + * @param u_dst + * U plane address of YUV420P[out] + * + * @param v_dst + * V plane address of YUV420P[out] + * + * @param rgb_src + * Address of ARGB8888[in] + * + * @param width + * Width of ARGB8888[in] + * + * @param height + * Height of ARGB8888[in] + */ +void csc_ARGB8888_to_YUV420P( + unsigned char *y_dst, + unsigned char *u_dst, + unsigned char *v_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset1 = width * height; + unsigned int offset2 = width/2 * height/2; + + unsigned int *pSrc = (unsigned int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstU = (unsigned char *)u_dst; + unsigned char *pDstV = (unsigned char *)v_dst; + + unsigned int yIndex = 0; + unsigned int uIndex = 0; + unsigned int vIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x00FF0000) >> 16; + G = (tmp & 0x0000FF00) >> 8; + B = (tmp & 0x000000FF); + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstU[uIndex++] = (unsigned char)U; + pDstV[vIndex++] = (unsigned char)V; + } + } + } +} + + +/* + * Converts ARGB8888 to YUV420SP + * + * @param y_dst + * Y plane address of YUV420SP[out] + * + * @param uv_dst + * UV plane address of YUV420SP[out] + * + * @param rgb_src + * Address of ARGB8888[in] + * + * @param width + * Width of ARGB8888[in] + * + * @param height + * Height of ARGB8888[in] + */ +void csc_ARGB8888_to_YUV420SP( + unsigned char *y_dst, + unsigned char *uv_dst, + unsigned char *rgb_src, + unsigned int width, + unsigned int height) +{ + unsigned int i, j; + unsigned int tmp; + + unsigned int R, G, B; + unsigned int Y, U, V; + + unsigned int offset = width * height; + + unsigned int *pSrc = (unsigned int *)rgb_src; + + unsigned char *pDstY = (unsigned char *)y_dst; + unsigned char *pDstUV = (unsigned char *)uv_dst; + + unsigned int yIndex = 0; + unsigned int uvIndex = 0; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + tmp = pSrc[j * width + i]; + + R = (tmp & 0x00FF0000) >> 16; + G = (tmp & 0x0000FF00) >> 8; + B = (tmp & 0x000000FF); + + Y = ((66 * R) + (129 * G) + (25 * B) + 128); + Y = Y >> 8; + Y += 16; + + pDstY[yIndex++] = (unsigned char)Y; + + if ((j % 2) == 0 && (i % 2) == 0) { + U = ((-38 * R) - (74 * G) + (112 * B) + 128); + U = U >> 8; + U += 128; + V = ((112 * R) - (94 * G) - (18 * B) + 128); + V = V >> 8; + V += 128; + + pDstUV[uvIndex++] = (unsigned char)U; + pDstUV[uvIndex++] = (unsigned char)V; + } + } + } +}
\ No newline at end of file |