From 8e4bff4cab0ddac6060645b0715210484d02ff40 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Wed, 30 Aug 2017 08:25:59 +0000 Subject: Initial file dump from open source release --- drivers/media/sprd_gsp/scaler_coef_cal.c | 811 +++++++++++++++++++++++++++++++ 1 file changed, 811 insertions(+) create mode 100644 drivers/media/sprd_gsp/scaler_coef_cal.c (limited to 'drivers/media/sprd_gsp/scaler_coef_cal.c') diff --git a/drivers/media/sprd_gsp/scaler_coef_cal.c b/drivers/media/sprd_gsp/scaler_coef_cal.c new file mode 100644 index 00000000..9449a3a5 --- /dev/null +++ b/drivers/media/sprd_gsp/scaler_coef_cal.c @@ -0,0 +1,811 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sin_cos.h" +#include +#include +#include +#include "scaler_coef_cal.h" +#include "gsp_config_if.h" + + +#define GSC_FIX 24 +#define GSC_COUNT 64 +#define TRUE 1 +#define FALSE 0 + +#define GSC_ABS(_a) ((_a) < 0 ? -(_a) : (_a)) +#define GSC_SIGN2(input, p) {if (p>=0) input = 1; if (p < 0) input = -1;} +#define COEF_ARR_ROWS 9 +#define COEF_ARR_COLUMNS 8 +#define COEF_ARR_COL_MAX 16 +#define MIN_POOL_SIZE (6 * 1024) + +#define SCI_MEMSET memset +#define MAX( _x, _y ) (((_x) > (_y)) ? (_x) : (_y) ) + + + + +typedef struct { + ulong begin_addr; + ulong total_size; + ulong used_size; +} GSC_MEM_POOL; + + +static uint8_t _InitPool(void *buffer_ptr, + uint32_t buffer_size, + GSC_MEM_POOL * pool_ptr) +{ + if (NULL == buffer_ptr || 0 == buffer_size || NULL == pool_ptr) { + return FALSE; + } + if (buffer_size < MIN_POOL_SIZE) { + return FALSE; + } + pool_ptr->begin_addr = (ulong) buffer_ptr; + pool_ptr->total_size = buffer_size; + pool_ptr->used_size = 0; + //printk("GSP_InitPool:%d,begin_addr:0x%08x,total_size:%d,used_size:%d\n",__LINE__,pool_ptr->begin_addr,pool_ptr->total_size,pool_ptr->used_size); + return TRUE; +} + +static void *_Allocate(uint32_t size, + uint32_t align_shift, + GSC_MEM_POOL * pool_ptr) +{ + ulong begin_addr = 0; + ulong temp_addr = 0; + if (NULL == pool_ptr) { + //printk("GSP_Allocate:%d _Allocate error! \n",__LINE__); + return NULL; + } + begin_addr = pool_ptr->begin_addr; + temp_addr = begin_addr + pool_ptr->used_size; + temp_addr = (((temp_addr + (1UL << align_shift)-1) >> align_shift) << align_shift); + if (temp_addr + size > begin_addr + pool_ptr->total_size) { + //printk("GSP_Allocate err:%d,temp_addr:0x%08x,size:%d,begin_addr:0x%08x,total_size:%d,used_size:%d\n",__LINE__,temp_addr,size,begin_addr,pool_ptr->total_size,pool_ptr->used_size); + return NULL; + } + pool_ptr->used_size = (temp_addr + size) - begin_addr; + SCI_MEMSET((void *)temp_addr, 0, size); + //printk("GSP_Allocate:%d _Allocate success!%08x \n",__LINE__,temp_addr); + return (void *)temp_addr; +} + +static int64_t div64_s64_s64(int64_t dividend, int64_t divisor) +{ + int8_t sign = 1; + int64_t dividend_tmp = dividend; + int64_t divisor_tmp = divisor; + int64_t ret = 0; + if (0 == divisor) { + return 0; + } + if ((dividend >> 63) & 0x1) { + sign *= -1; + dividend_tmp = dividend * (-1); + } + if ((divisor >> 63) & 0x1) { + sign *= -1; + divisor_tmp = divisor * (-1); + } + ret = div64_s64(dividend_tmp, divisor_tmp); + ret *= sign; + return ret; +} + +static void normalize_inter(int64_t * data, int16_t * int_data, uint8_t ilen) +{ + uint8_t it; + int64_t tmp_d = 0; + int64_t *tmp_data = NULL; + int64_t tmp_sum_val = 0; + tmp_data = data; + tmp_sum_val = 0; + for (it = 0; it < ilen; it++) { + tmp_sum_val += tmp_data[it]; + } + if (0 == tmp_sum_val) { + uint8_t value = 256 / ilen; + for (it = 0; it < ilen; it++) { + tmp_d = value; + int_data[it] = (int16_t) tmp_d; + } + } else { + for (it = 0; it < ilen; it++) { + tmp_d = + div64_s64_s64(tmp_data[it] * (int64_t) 256, + tmp_sum_val); + int_data[it] = (uint16_t) tmp_d; + } + } +} +/* ------------------------------------------ */ +static int16_t sum_fun(int16_t *data, int8_t ilen) +{ + int8_t i ; + int16_t tmp_sum; + tmp_sum = 0; + + for (i = 0; i < ilen; i++) + tmp_sum += *data++; + + return tmp_sum; +} + + + +static void adjust_filter_inter(int16_t *filter, uint8_t ilen) +{ + int32_t i, midi; + int32_t tmpi, tmp_S ; + int32_t tmp_val = 0 ; + + tmpi = sum_fun(filter, ilen) - 256; + midi = ilen >> 1; + GSC_SIGN2(tmp_val, tmpi); + + if ((tmpi & 1) == 1) { // tmpi is odd + filter[midi] = filter[midi] - tmp_val; + tmpi -= tmp_val; + } + + //tmp_S = abs(tmpi>>1); + + tmp_S = GSC_ABS(tmpi / 2); + + if ((ilen & 1) == 1) { // ilen is odd + for (i = 0; i < tmp_S; i++) { + filter[midi - (i+1)] = filter[midi - (i+1)] - tmp_val; + filter[midi + (i+1)] = filter[midi + (i+1)] - tmp_val; + } + } else { // ilen is even + for (i = 0; i < tmp_S; i++) { + filter[midi - (i+1)] = filter[midi - (i+1)] - tmp_val; + filter[midi + i] = filter[midi + i] - tmp_val; + } + } + + if(filter[midi] > 255) { + tmp_val = filter[midi] ; + filter[midi] = 255 ; + filter[midi - 1] = filter[midi - 1] + tmp_val - 255 ; + } +} + +static int16_t CalYmodelCoef(int16_t coef_lenght, + int16_t * coef_data_ptr, + int16_t N, + int16_t M, + GSC_MEM_POOL * pool_ptr) +{ + int8_t mount; + int16_t i, mid_i, kk, j, sum_val; + int64_t *filter = _Allocate(GSC_COUNT * sizeof(int64_t), 3, pool_ptr); + int64_t *tmp_filter = _Allocate(GSC_COUNT * sizeof(int64_t), 3, pool_ptr); + int16_t *normal_filter = _Allocate(GSC_COUNT * sizeof(int16_t), 2, pool_ptr); + + if (NULL == filter || NULL == tmp_filter || NULL == normal_filter) { + return 1; + } + mid_i = coef_lenght >> 1; + filter[mid_i] = + div64_s64_s64((int64_t) ((int64_t) N << GSC_FIX), + (int64_t) MAX(M, N)); + for (i = 0; i < mid_i; i++) { + int64_t angle_x = + div64_s64_s64((int64_t) ARC_32_COEF * (int64_t) (i + 1) * + (int64_t) N, (int64_t) MAX(M, + N) * (int64_t) 8); + int64_t angle_y = + div64_s64_s64((int64_t) ARC_32_COEF * (int64_t) (i + 1) * + (int64_t) N, (int64_t) (M * N) * (int64_t) 8); + int32_t value_x = sin_32((int32_t) angle_x); + int32_t value_y = sin_32((int32_t) angle_y); + filter[mid_i + i + 1] = + div64_s64_s64((int64_t) + ((int64_t) value_x * + (int64_t) (1 << GSC_FIX)), + (int64_t) ((int64_t) M * (int64_t) value_y)); + filter[mid_i - (i + 1)] = filter[mid_i + i + 1]; + } + for (i = -1; i < mid_i; i++) { + int32_t angle_32 = + (int32_t) + div64_s64_s64((int64_t) + ((int64_t) 2 * (int64_t) (mid_i - i - 1) * + (int64_t) ARC_32_COEF), + (int64_t) coef_lenght); + int64_t a = (int64_t) 9059697; + int64_t b = (int64_t) 7717519; + int64_t t = a - ((b * cos_32(angle_32)) >> 30); + filter[mid_i + i + 1] = (t * filter[mid_i + i + 1]) >> GSC_FIX; + filter[mid_i - (i + 1)] = filter[mid_i + i + 1]; + } + for (i = 0; i < 8; i++) { + mount = 0; + for (j = i; j < coef_lenght; j += 8) { + tmp_filter[mount] = filter[j]; + mount++; + } + normalize_inter(tmp_filter, normal_filter, (int8_t) mount); + sum_val = sum_fun(normal_filter, mount); + if (256 != sum_val) { + adjust_filter_inter(normal_filter, mount); + } + mount = 0; + for (kk = i; kk < coef_lenght; kk += 8) { + coef_data_ptr[kk] = normal_filter[mount]; + mount++; + } + } + return 0; +} + +/* cal Y model */ +static int16_t CalY_ScalingCoef(int16_t tap, + int16_t D, + int16_t I, + int16_t * y_coef_data_ptr, + int16_t dir, GSC_MEM_POOL * pool_ptr) +{ + uint16_t coef_lenght; + + coef_lenght = (uint16_t) (tap * 8); + SCI_MEMSET(y_coef_data_ptr, 0, coef_lenght * sizeof(int16_t)); + CalYmodelCoef(coef_lenght, y_coef_data_ptr, I, D, pool_ptr); + return coef_lenght; +} + +static int16_t CalUV_ScalingCoef(int16_t tap, + int16_t D, + int16_t I, + int16_t * uv_coef_data_ptr, + int16_t dir, GSC_MEM_POOL * pool_ptr) +{ + int16_t uv_coef_lenght; + + if ((dir == 1)) { + uv_coef_lenght = (int16_t) (tap * 8); + CalYmodelCoef(uv_coef_lenght, uv_coef_data_ptr, I, D, pool_ptr); + } else { + if (D > I) { + uv_coef_lenght = (int16_t) (tap * 8); + } else { + uv_coef_lenght = (int16_t) (2 * 8); + } + CalYmodelCoef(uv_coef_lenght, uv_coef_data_ptr, I, D, pool_ptr); + } + return uv_coef_lenght; +} + +static void GetFilter(int16_t * coef_data_ptr, + int16_t * out_filter, + int16_t iI_hor, + int16_t coef_len, + int16_t * filter_len) +{ + int16_t i, pos_start; + + pos_start = coef_len / 2; + while (pos_start >= iI_hor) { + pos_start -= iI_hor; + } + for (i = 0; i < iI_hor; i++) { + int16_t len = 0; + int16_t j; + int16_t pos = pos_start + i; + while (pos >= iI_hor) { + pos -= iI_hor; + } + for (j = 0; j < coef_len; j+=iI_hor) { + *out_filter++ = coef_data_ptr[j + pos]; + len ++; + } + *filter_len++ = len; + } +} + +static void WriteScalarCoef(int16_t * dst_coef_ptr, + int16_t * coef_ptr, + int16_t dst_pitch, + int16_t src_pitch) +{ + int i, j; + + for (i = 0; i < 8; i++) { + for (j = 0; j < src_pitch; j++) { + *(dst_coef_ptr + j) = + *(coef_ptr + i * src_pitch + src_pitch - 1 - j); + } + dst_coef_ptr += dst_pitch; + } +} +/* +static void SetHorRegisterCoef(uint32_t * reg_coef_ptr, int16_t * y_coef_ptr, + int16_t * uv_coef_ptr) +{ + int32_t i = 0; + int16_t *y_coef_arr[COEF_ARR_ROWS] = { NULL }; + int16_t *uv_coef_arr[COEF_ARR_ROWS] = { NULL }; + + for (i = 0; i < COEF_ARR_ROWS; i++) + { + y_coef_arr[i] = y_coef_ptr; + uv_coef_arr[i] = uv_coef_ptr; + y_coef_ptr += COEF_ARR_COLUMNS; + uv_coef_ptr += COEF_ARR_COLUMNS; + } + + // horizontal Y Scaling Coef Config register + for (i = 0; i < 8; i++) + { + uint16_t p0, p1; + uint32_t reg; + + p0 = (uint16_t) y_coef_arr[i][7]; + p1 = (uint16_t) y_coef_arr[i][6]; + reg = ((p0 & 0x1ff)) | ((p1 & 0x1ff) << 9); + *reg_coef_ptr++ = reg; + p0 = (uint16_t) y_coef_arr[i][5]; + p1 = (uint16_t) y_coef_arr[i][4]; + reg = ((p0 & 0x1ff)) | ((p1 & 0x1ff) << 9); + *reg_coef_ptr++ = reg; + p0 = (uint16_t) y_coef_arr[i][3]; + p1 = (uint16_t) y_coef_arr[i][2]; + reg = ((p0 & 0x1ff)) | ((p1 & 0x1ff) << 9); + *reg_coef_ptr++ = reg; + p0 = (uint16_t) y_coef_arr[i][1]; + p1 = (uint16_t) y_coef_arr[i][0]; + reg = ((p0 & 0x1ff)) | ((p1 & 0x1ff) << 9); + *reg_coef_ptr++ = reg; + } + // horizontal UV Scaling Coef Config register + for (i = 0; i < 8; i++) + { + uint16_t p0, p1; + uint32_t reg; + + p0 = (uint16_t) uv_coef_arr[i][3]; + p1 = (uint16_t) uv_coef_arr[i][2]; + reg = ((p0 & 0x1ff)) | ((p1 & 0x1ff) << 9); + *reg_coef_ptr++ = reg; + p0 = (uint16_t) uv_coef_arr[i][1]; + p1 = (uint16_t) uv_coef_arr[i][0]; + reg = ((p0 & 0x1ff)) | ((p1 & 0x1ff) << 9); + *reg_coef_ptr++ = reg; + } +} +*/ + +static void CheckCoefRange(int16_t * coef_ptr, int16_t rows, int16_t columns, int16_t pitch) +{ + int16_t i, j; + int16_t value, diff, sign; + int16_t *coef_arr[COEF_ARR_ROWS] = { NULL }; + + for (i = 0; i < COEF_ARR_ROWS; i++) { + coef_arr[i] = coef_ptr; + coef_ptr += pitch; + } + for (i = 0; i < rows; i++) { + for (j = 0; j < columns; j++) { + value = coef_arr[i][j]; + if (value > 255) { + diff = value - 255; + coef_arr[i][j] = 255; + sign = GSC_ABS(diff); + if ((sign & 1) == 1) { // ilen is odd + coef_arr[i][j + 1] = + coef_arr[i][j + 1] + (diff + 1) / 2; + coef_arr[i][j - 1] = + coef_arr[i][j - 1] + (diff - 1) / 2; + } else { // ilen is even + coef_arr[i][j + 1] = + coef_arr[i][j + 1] + (diff) / 2; + coef_arr[i][j - 1] = + coef_arr[i][j - 1] + (diff) / 2; + } + } + } + } +} + + +static void GSP_Rearrang_Coeff(void* src, void*dst, int32_t tap) +{ + uint32_t i, j; + int16_t *src_ptr, *dst_ptr; + + src_ptr = (int16_t*)src; + dst_ptr = (int16_t*)dst; + if (src_ptr == NULL || dst_ptr == NULL) + return; + + if (0 != dst_ptr) { + memset((void*)dst_ptr, 0x00, 8 * 8 * sizeof(int16_t)); + } + + switch(tap) { + case 6: + case 2: { + for(i = 0; i<8; i++) { + for(j = 0; j< tap; j++) { + *(dst_ptr+i*8+1+j) = *(src_ptr+i*8+j); + } + } + } + break; + + case 4: + case 8: { + for(i = 0; i<8; i++) { + for(j = 0; j< tap; j++) { + *(dst_ptr + i * 8 + j) = *(src_ptr + i * 8 + j); + } + } + } + break; + } +} + +#define CACHE_COEF +#ifdef CACHE_COEF +//we use "Least Recently Used(LRU)" to implement the coef-matrix cache policy + +#include +#include +#include + + +#define COEF_MATRIX_ENTRY_SIZE (GSP_COEFF_COEF_SIZE/2) +#define CACHED_COEF_CNT_MAX 32 + +typedef struct _coef_entry { + struct _coef_entry* prev; + struct _coef_entry* next; + uint32_t coef[COEF_MATRIX_ENTRY_SIZE]; + uint16_t in_w; + uint16_t in_h; + uint16_t out_w; + uint16_t out_h; + uint16_t hor_tap; + uint16_t ver_tap; +} Coef_Entry; + + +Coef_Entry *Coef_Entry_List_Head = NULL; +#define LIST_ADD_TO_LIST_HEAD(pEntry)\ +{\ + Coef_Entry_List_Head->prev->next = (pEntry);\ + (pEntry)->prev = Coef_Entry_List_Head->prev;\ + (pEntry)->next = Coef_Entry_List_Head;\ + Coef_Entry_List_Head->prev = (pEntry);\ + Coef_Entry_List_Head = (pEntry);\ +} + +#define LIST_FETCH_FROM_LIST(pEntry)\ +{\ + pEntry->prev->next = pEntry->next;\ + pEntry->next->prev = pEntry->prev;\ +} + +#define LIST_SET_ENTRY_KEY(pEntry,i_w,i_h,o_w,o_h,h_t,v_t)\ +{\ + pEntry->in_w = i_w;\ + pEntry->in_h = i_h;\ + pEntry->out_w = o_w;\ + pEntry->out_h = o_h;\ + pEntry->hor_tap = h_t;\ + pEntry->ver_tap = v_t;\ +} + +#define LIST_GET_THE_TAIL_ENTRY() (Coef_Entry_List_Head->prev) + +static int32_t cache_coef_init(gsp_context_t *gspCtx) +{ + Coef_Entry *Coef_Entry_Array = NULL; + uint32_t i = 0; + pr_debug("GSP_CACHE_COEF:init\n"); + + if(gspCtx->cache_coef_init_flag == 0) { + Coef_Entry_Array = (Coef_Entry *)vmalloc(sizeof(Coef_Entry)*CACHED_COEF_CNT_MAX); + + if(Coef_Entry_Array) { + memset((void*)Coef_Entry_Array,0,sizeof(Coef_Entry)*CACHED_COEF_CNT_MAX); + + Coef_Entry_List_Head = &Coef_Entry_Array[0]; + Coef_Entry_Array[0].prev = &Coef_Entry_Array[0]; + Coef_Entry_Array[0].next = &Coef_Entry_Array[0]; + i++; + + while(i < CACHED_COEF_CNT_MAX) { + LIST_ADD_TO_LIST_HEAD(&Coef_Entry_Array[i]); + i++; + } + gspCtx->cache_coef_init_flag = 1; + } else { + return -1; + } + } + return 0; +} + +/* +func:cache_coef_hit_check +desc:find the entry have the same in_w in_h out_w out_h +return:if hit,return the entry pointer; else return null; +*/ +static Coef_Entry* cache_coef_hit_check(uint16_t in_w, uint16_t in_h, uint16_t out_w,uint16_t out_h, + uint16_t hor_tap, uint16_t ver_tap) +{ + static uint32_t total_cnt = 0; + static uint32_t hit_cnt = 0; + + Coef_Entry* walk = Coef_Entry_List_Head; + + total_cnt++; + while(walk->in_w != 0) { + if(walk->in_w == in_w + && walk->in_h == in_h + && walk->out_w == out_w + && walk->out_h == out_h + && walk->hor_tap == hor_tap + && walk->ver_tap == ver_tap) { + hit_cnt++; + pr_debug("GSP_CACHE_COEF:hit, hit_ratio:%d percent\n",hit_cnt*100/total_cnt); + return walk; + } + if(walk->next == Coef_Entry_List_Head) { + break; + } + walk = walk->next; + } + pr_debug("GSP_CACHE_COEF:miss\n"); + return NULL; +} + +static Coef_Entry* cache_coef_move_entry_to_list_head(Coef_Entry* pEntry) +{ + LIST_FETCH_FROM_LIST(pEntry); + LIST_ADD_TO_LIST_HEAD(pEntry); + return Coef_Entry_List_Head; +} + +#endif + +/**---------------------------------------------------------------------------* + ** Public Functions * + **---------------------------------------------------------------------------*/ +/****************************************************************************/ +/* Purpose: generate scale factor */ +/* Author: */ +/* Input: */ +/* i_w: source image width */ +/* i_h: source image height */ +/* o_w: target image width */ +/* o_h: target image height */ +/* Output: */ +/* coeff_h_ptr: pointer of horizontal coefficient buffer, the size of which must be at */ +/* least SCALER_COEF_TAP_NUM_HOR * 4 bytes */ +/* the output coefficient will be located in coeff_h_ptr[0], ......, */ +/* coeff_h_ptr[SCALER_COEF_TAP_NUM_HOR-1] */ +/* coeff_v_ptr: pointer of vertical coefficient buffer, the size of which must be at */ +/* least (SCALER_COEF_TAP_NUM_VER + 1) * 4 bytes */ +/* the output coefficient will be located in coeff_v_ptr[0], ......, */ +/* coeff_h_ptr[SCALER_COEF_TAP_NUM_VER-1] and the tap number */ +/* will be located in coeff_h_ptr[SCALER_COEF_TAP_NUM_VER] */ +/* temp_buf_ptr: temp buffer used while generate the coefficient */ +/* temp_buf_ptr: temp buffer size, 6k is the suggest size */ +/* Return: */ +/* Note: */ +/****************************************************************************/ +uint8_t GSP_Gen_Block_Ccaler_Coef(uint32_t i_w, + uint32_t i_h, + uint32_t o_w, + uint32_t o_h, + uint32_t hor_tap, + uint32_t ver_tap, + uint32_t *coeff_h_ptr, + uint32_t *coeff_v_ptr, + void *temp_buf_ptr, + uint32_t temp_buf_size, + gsp_context_t *gspCtx + ) +{ + int16_t D_hor = i_w; //decimition at horizontal + //int16_t D_ver = i_h; //decimition at vertical + int16_t I_hor = o_w; //interpolation at horizontal + //int16_t I_ver = o_h; //interpolation at vertical + //int16_t I_ver_bak_uv = o_h; + + int16_t *cong_com_hor = 0; + int16_t *cong_com_ver = 0; + int16_t *coeff_array = 0; + + //uint16_t luma_ver_tap, chrome_ver_tap; + //uint16_t luma_ver_maxtap = 8, chrome_ver_maxtap = 8; + + uint32_t coef_buf_size = 0; + int16_t *temp_filter_ptr = NULL; + int16_t *filter_ptr = NULL; + uint32_t filter_buf_size = GSC_COUNT * sizeof(int16_t); + int16_t filter_len[COEF_ARR_ROWS] = { 0 }; + int16_t coef_len = 0; + //uint8_t is_scaling_up = FALSE; + //uint8_t hor_tap = 8; + //uint8_t ver_tap = 8; + GSC_MEM_POOL pool = { 0 }; + uint32_t i = 0; + +#ifdef CACHE_COEF + Coef_Entry* pEntry = NULL; + + if(gspCtx->cache_coef_init_flag == 0) { + cache_coef_init(gspCtx); + } + + if(gspCtx->cache_coef_init_flag == 1) { + pEntry = cache_coef_hit_check(i_w,i_h,o_w,o_h,hor_tap,ver_tap); + if(pEntry) { //hit + if((ulong)coeff_h_ptr & MEM_OPS_ADDR_ALIGN_MASK || (ulong)pEntry->coef & MEM_OPS_ADDR_ALIGN_MASK) { + GSP_TRACE("%s[%d] memcpy use none 8B alignment address!",__func__,__LINE__); + } + memcpy((void*)coeff_h_ptr, (void*)pEntry->coef, COEF_MATRIX_ENTRY_SIZE*4); + cache_coef_move_entry_to_list_head(pEntry); + return TRUE; + } + } +#endif + + /* init pool and allocate static array */ + if (!_InitPool(temp_buf_ptr, temp_buf_size, &pool)) { + printk("GSP_Gen_Block_Ccaler_Coef: _InitPool error! \n"); + return FALSE; + } + + coef_buf_size = COEF_ARR_ROWS * COEF_ARR_COL_MAX * sizeof(int16_t); + cong_com_hor = (int16_t*)_Allocate(coef_buf_size, 2, &pool); + cong_com_ver = (int16_t*)_Allocate(coef_buf_size, 2, &pool); + coeff_array = (int16_t*)_Allocate(8 * 8, 2, &pool); + + if (NULL == cong_com_hor + || NULL == cong_com_ver + ||NULL == coeff_array) { + //printk("GSP_Gen_Block_Ccaler_Coef:%d _Allocate error!%08x,%08x,%08x\n",__LINE__,cong_com_hor,cong_com_ver,coeff_array); + return FALSE; + } + + temp_filter_ptr = _Allocate(filter_buf_size, 2, &pool); + filter_ptr = _Allocate(filter_buf_size, 2, &pool); + if (NULL == temp_filter_ptr || NULL == filter_ptr) { + //printk("GSP_Gen_Block_Ccaler_Coef:%d _Allocate error! \n",__LINE__); + return FALSE; + } + + /* calculate coefficients of Y component in horizontal direction */ + coef_len = CalY_ScalingCoef(hor_tap, D_hor, I_hor, temp_filter_ptr, 1, &pool); + GetFilter(temp_filter_ptr, filter_ptr, 8, coef_len, filter_len); + WriteScalarCoef(cong_com_hor, filter_ptr, 8, hor_tap); + CheckCoefRange(cong_com_hor, 8, hor_tap, 8); + GSP_Rearrang_Coeff(cong_com_hor, coeff_array, hor_tap); + { + uint32_t cnts = 0, reg = 0; + uint16_t p0, p1; + for (i = 0; i < 8; i++) { + p0 = (uint16_t)(*(coeff_array + i * 8 + 0)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 1)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_h_ptr[cnts + 0] = reg; + + p0 = (uint16_t)(*(coeff_array + i * 8 + 2)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 3)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_h_ptr[cnts + 1] = reg; + + p0 = (uint16_t)(*(coeff_array + i * 8 + 4)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 5)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_h_ptr[cnts + 2] = reg; + + p0 = (uint16_t)(*(coeff_array + i * 8 + 6)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 7)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_h_ptr[cnts + 3] = reg; + + cnts += 4; + } + } + + /* calculate coefficients of UV component in horizontal direction */ + coef_len = CalUV_ScalingCoef(ver_tap, D_hor, I_hor, temp_filter_ptr, 1, &pool); + GetFilter(temp_filter_ptr, filter_ptr, 8, coef_len, filter_len); + WriteScalarCoef(cong_com_ver, filter_ptr, 8, ver_tap); + CheckCoefRange(cong_com_ver, 8, ver_tap, 8); + memset(coeff_array, 0x00, 8 * 8 * sizeof(int16_t)); + GSP_Rearrang_Coeff(cong_com_ver, coeff_array, ver_tap); + { + uint32_t cnts = 0, reg = 0; + uint16_t p0, p1; + for (i = 0; i < 8; i++) { + p0 = (uint16_t)(*(coeff_array + i * 8 + 0)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 1)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_v_ptr[cnts + 0] = reg; + + p0 = (uint16_t)(*(coeff_array + i * 8 + 2)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 3)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_v_ptr[cnts + 1] = reg; + + p0 = (uint16_t)(*(coeff_array + i * 8 + 4)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 5)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_v_ptr[cnts + 2] = reg; + + p0 = (uint16_t)(*(coeff_array + i * 8 + 6)); + p1 = (uint16_t)(*(coeff_array + i * 8 + 7)); + reg = (p0 & 0x1ff)|((p1 & 0x1ff)<<16); + coeff_v_ptr[cnts + 3] = reg; + + cnts += 4; + } + } + +#ifdef CACHE_COEF + if(gspCtx->cache_coef_init_flag == 1) { + pEntry = LIST_GET_THE_TAIL_ENTRY(); + if(pEntry->in_w == 0) { + pr_debug("GSP_CACHE_COEF:add\n"); + } else { + pr_debug("GSP_CACHE_COEF:swap\n"); + } + if((ulong)coeff_h_ptr & MEM_OPS_ADDR_ALIGN_MASK || (ulong)pEntry->coef & MEM_OPS_ADDR_ALIGN_MASK) { + GSP_TRACE("%s[%d] memcpy use none 8B alignment address!",__func__,__LINE__); + } + memcpy((void*)pEntry->coef,(void*)coeff_h_ptr,COEF_MATRIX_ENTRY_SIZE*4); + cache_coef_move_entry_to_list_head(pEntry); + LIST_SET_ENTRY_KEY(pEntry,i_w,i_h,o_w,o_h,hor_tap,ver_tap); + } +#endif + + return TRUE; +} +void GSP_Scale_Coef_Tab_Config(uint32_t *p_h_coeff,uint32_t *p_v_coeff) +{ + uint32_t i=0, j = 0; + uint32_t *s_scaling_reg_hor_ptr =0, *s_scaling_reg_ver_ptr=0; + ulong scale_h_coef_addr = GSP_HOR_COEF_BASE, scale_v_coef_addr = GSP_VER_COEF_BASE; + + + s_scaling_reg_hor_ptr = p_h_coeff; + + for( i = 0; i < 8; i++) { + for(j = 0; j < 4; j++) { + *(volatile uint32_t*)scale_h_coef_addr = *s_scaling_reg_hor_ptr; + scale_h_coef_addr += 4; + s_scaling_reg_hor_ptr++; + } + } + + s_scaling_reg_ver_ptr = p_v_coeff; + for( i = 0; i < 8; i++) { + for(j = 0; j < 4; j++) { + *(volatile uint32_t*)scale_v_coef_addr = *s_scaling_reg_ver_ptr; + scale_v_coef_addr += 4; + s_scaling_reg_ver_ptr++; + } + } +} -- cgit v1.3.1