1 /* 2 * Copyright 2010 Samsung Electronics Co. LTD 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdlib.h> 18 #include <unistd.h> 19 #include <string.h> 20 #include <fcntl.h> 21 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <sys/ioctl.h> 25 #include <sys/mman.h> 26 #include <utils/Log.h> 27 28 #include "mfc_interface.h" 29 #include "SsbSipMfcApi.h" 30 31 #define _MFCLIB_MAGIC_NUMBER 0x92241000 32 33 #define USR_DATA_START_CODE (0x000001B2) 34 #define VOP_START_CODE (0x000001B6) 35 #define MP4_START_CODE (0x000001) 36 37 static void getAByte(char *buff, int *code) 38 { 39 int byte; 40 41 *code = (*code << 8); 42 byte = (int)*buff; 43 byte &= 0xFF; 44 *code |= byte; 45 } 46 47 static mfc_packed_mode isPBPacked(_MFCLIB *pCtx, int length) 48 { 49 char *strmBuffer = NULL; 50 char *strmBufferEnd = NULL; 51 int startCode = 0xFFFFFFFF; 52 53 strmBuffer = (char *)pCtx->virStrmBuf; 54 strmBufferEnd = (char *)pCtx->virStrmBuf + length; 55 56 while (1) { 57 while (startCode != USR_DATA_START_CODE) { 58 if (startCode == VOP_START_CODE) { 59 LOGV("isPBPacked: VOP START Found !!.....return\n"); 60 LOGV("isPBPacked: Non Packed PB\n"); 61 return MFC_UNPACKED_PB; 62 } 63 getAByte(strmBuffer, &startCode); 64 strmBuffer++; 65 if (strmBuffer >= strmBufferEnd) 66 goto out; 67 } 68 LOGV("isPBPacked: User Data Found !!\n"); 69 70 do { 71 if (*strmBuffer == 'p') { 72 LOGI("isPBPacked: Packed PB\n"); 73 return MFC_PACKED_PB; 74 } 75 getAByte(strmBuffer, &startCode); 76 strmBuffer++; 77 if (strmBuffer >= strmBufferEnd) 78 goto out; 79 } while ((startCode >> 8) != MP4_START_CODE); 80 } 81 82 out: 83 LOGV("isPBPacked: Non Packed PB\n"); 84 return MFC_UNPACKED_PB; 85 } 86 87 void *SsbSipMfcDecOpen(void) 88 { 89 int hMFCOpen; 90 unsigned int mapped_addr; 91 _MFCLIB *pCTX; 92 93 pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); 94 if (pCTX == NULL) { 95 LOGE("SsbSipMfcDecOpen: malloc failed.\n"); 96 return NULL; 97 } 98 memset(pCTX, 0, sizeof(_MFCLIB)); 99 100 hMFCOpen = open(S5PC110_MFC_DEV_NAME, O_RDWR | O_NDELAY); 101 if (hMFCOpen < 0) { 102 LOGE("SsbSipMfcDecOpen: MFC Open failure\n"); 103 return NULL; 104 } 105 106 mapped_addr = (unsigned int)mmap(0, MMAP_BUFFER_SIZE_MMAP, PROT_READ | PROT_WRITE, MAP_SHARED, hMFCOpen, 0); 107 if (!mapped_addr) { 108 LOGE("SsbSipMfcDecOpen: FIMV5.0 driver address mapping failed\n"); 109 return NULL; 110 } 111 112 pCTX->magic = _MFCLIB_MAGIC_NUMBER; 113 pCTX->hMFC = hMFCOpen; 114 pCTX->mapped_addr = mapped_addr; 115 pCTX->inter_buff_status = MFC_USE_NONE; 116 117 return (void *)pCTX; 118 } 119 120 SSBSIP_MFC_ERROR_CODE SsbSipMfcDecInit(void *openHandle, SSBSIP_MFC_CODEC_TYPE codec_type, int Frameleng) 121 { 122 int ret_code; 123 int packedPB = MFC_UNPACKED_PB; 124 mfc_common_args DecArg; 125 _MFCLIB *pCTX; 126 127 if (openHandle == NULL) { 128 LOGE("SsbSipMfcDecSetConfig: openHandle is NULL\n"); 129 return MFC_RET_INVALID_PARAM; 130 } 131 132 pCTX = (_MFCLIB *)openHandle; 133 memset(&DecArg, 0x00, sizeof(DecArg)); 134 135 if ((codec_type != MPEG4_DEC) && 136 (codec_type != H264_DEC) && 137 (codec_type != H263_DEC) && 138 (codec_type != MPEG1_DEC) && 139 (codec_type != MPEG2_DEC) && 140 (codec_type != FIMV1_DEC) && 141 (codec_type != FIMV2_DEC) && 142 (codec_type != FIMV3_DEC) && 143 (codec_type != FIMV4_DEC) && 144 (codec_type != XVID_DEC) && 145 (codec_type != VC1RCV_DEC) && 146 (codec_type != VC1_DEC)) { 147 LOGE("SsbSipMfcDecOpen: Undefined codec type.\n"); 148 return MFC_RET_INVALID_PARAM; 149 } 150 151 pCTX->codec_type = codec_type; 152 153 if ((pCTX->codec_type == MPEG4_DEC) || 154 (pCTX->codec_type == FIMV1_DEC) || 155 (pCTX->codec_type == FIMV2_DEC) || 156 (pCTX->codec_type == FIMV3_DEC) || 157 (pCTX->codec_type == FIMV4_DEC) || 158 (pCTX->codec_type == XVID_DEC)) 159 packedPB = isPBPacked(pCTX, Frameleng); 160 161 /* init args */ 162 DecArg.args.dec_init.in_codec_type = pCTX->codec_type; 163 DecArg.args.dec_init.in_strm_size = Frameleng; 164 DecArg.args.dec_init.in_strm_buf = pCTX->phyStrmBuf; 165 DecArg.args.dec_init.in_packed_PB = packedPB; 166 167 /* mem alloc args */ 168 DecArg.args.dec_init.in_mapped_addr = pCTX->mapped_addr; 169 170 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_DEC_INIT, &DecArg); 171 if (DecArg.ret_code != MFC_RET_OK) { 172 LOGE("SsbSipMfcDecInit: IOCTL_MFC_DEC_INIT (%d) failed\n", DecArg.ret_code); 173 return MFC_RET_DEC_INIT_FAIL; 174 } 175 176 pCTX->decOutInfo.img_width = DecArg.args.dec_init.out_img_width; 177 pCTX->decOutInfo.img_height = DecArg.args.dec_init.out_img_height; 178 pCTX->decOutInfo.buf_width = DecArg.args.dec_init.out_buf_width; 179 pCTX->decOutInfo.buf_height = DecArg.args.dec_init.out_buf_height; 180 181 /* by RainAde : crop information */ 182 pCTX->decOutInfo.crop_top_offset = DecArg.args.dec_init.out_crop_top_offset; 183 pCTX->decOutInfo.crop_bottom_offset = DecArg.args.dec_init.out_crop_bottom_offset; 184 pCTX->decOutInfo.crop_left_offset = DecArg.args.dec_init.out_crop_left_offset; 185 pCTX->decOutInfo.crop_right_offset = DecArg.args.dec_init.out_crop_right_offset; 186 187 pCTX->virFrmBuf.luma = DecArg.args.dec_init.out_u_addr.luma; 188 pCTX->virFrmBuf.chroma = DecArg.args.dec_init.out_u_addr.chroma; 189 190 pCTX->phyFrmBuf.luma = DecArg.args.dec_init.out_p_addr.luma; 191 pCTX->phyFrmBuf.chroma = DecArg.args.dec_init.out_p_addr.chroma; 192 pCTX->sizeFrmBuf.luma = DecArg.args.dec_init.out_frame_buf_size.luma; 193 pCTX->sizeFrmBuf.chroma = DecArg.args.dec_init.out_frame_buf_size.chroma; 194 pCTX->inter_buff_status |= MFC_USE_YUV_BUFF; 195 196 return MFC_RET_OK; 197 } 198 199 SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) 200 { 201 int ret_code; 202 int Yoffset; 203 int Coffset; 204 _MFCLIB *pCTX; 205 mfc_common_args DecArg; 206 207 if (openHandle == NULL) { 208 LOGE("SsbSipMfcDecExe: openHandle is NULL\n"); 209 return MFC_RET_INVALID_PARAM; 210 } 211 212 if ((lengthBufFill < 0) || (lengthBufFill > MAX_DECODER_INPUT_BUFFER_SIZE)) { 213 LOGE("SsbSipMfcDecExe: lengthBufFill is invalid. (lengthBufFill=%d)\n", lengthBufFill); 214 return MFC_RET_INVALID_PARAM; 215 } 216 217 pCTX = (_MFCLIB *)openHandle; 218 memset(&DecArg, 0x00, sizeof(DecArg)); 219 220 DecArg.args.dec_exe.in_codec_type = pCTX->codec_type; 221 DecArg.args.dec_exe.in_strm_buf = pCTX->phyStrmBuf; 222 DecArg.args.dec_exe.in_strm_size = lengthBufFill; 223 DecArg.args.dec_exe.in_frm_buf.luma = pCTX->phyFrmBuf.luma; 224 DecArg.args.dec_exe.in_frm_buf.chroma = pCTX->phyFrmBuf.chroma; 225 DecArg.args.dec_exe.in_frm_size.luma = pCTX->sizeFrmBuf.luma; 226 DecArg.args.dec_exe.in_frm_size.chroma = pCTX->sizeFrmBuf.chroma; 227 DecArg.args.dec_exe.in_frametag = pCTX->in_frametag; 228 229 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_DEC_EXE, &DecArg); 230 if (DecArg.ret_code != MFC_RET_OK) { 231 LOGE("SsbSipMfcDecExe: IOCTL_MFC_DEC_EXE failed(ret : %d)\n", DecArg.ret_code); 232 return MFC_RET_DEC_EXE_ERR; 233 } 234 235 Yoffset = DecArg.args.dec_exe.out_display_Y_addr - DecArg.args.dec_exe.in_frm_buf.luma; 236 Coffset = DecArg.args.dec_exe.out_display_C_addr - DecArg.args.dec_exe.in_frm_buf.chroma; 237 238 pCTX->decOutInfo.YPhyAddr = (void *)(DecArg.args.dec_exe.out_display_Y_addr); 239 pCTX->decOutInfo.CPhyAddr = (void *)(DecArg.args.dec_exe.out_display_C_addr); 240 pCTX->decOutInfo.YVirAddr = (void *)(pCTX->virFrmBuf.luma + Yoffset); 241 pCTX->decOutInfo.CVirAddr = (void *)(pCTX->virFrmBuf.chroma + Coffset); 242 pCTX->decOutInfo.timestamp_top = DecArg.args.dec_exe.out_timestamp_top; 243 pCTX->decOutInfo.timestamp_bottom = DecArg.args.dec_exe.out_timestamp_bottom; 244 pCTX->decOutInfo.consumedByte = DecArg.args.dec_exe.out_consume_bytes; 245 pCTX->decOutInfo.res_change = DecArg.args.dec_exe.out_res_change; 246 pCTX->decOutInfo.crop_top_offset = DecArg.args.dec_exe.out_crop_top_offset; 247 pCTX->decOutInfo.crop_bottom_offset = DecArg.args.dec_exe.out_crop_bottom_offset; 248 pCTX->decOutInfo.crop_left_offset = DecArg.args.dec_exe.out_crop_left_offset; 249 pCTX->decOutInfo.crop_right_offset = DecArg.args.dec_exe.out_crop_right_offset; 250 pCTX->out_frametag_top = DecArg.args.dec_exe.out_frametag_top; 251 pCTX->out_frametag_bottom = DecArg.args.dec_exe.out_frametag_bottom; 252 pCTX->displayStatus = DecArg.args.dec_exe.out_display_status; 253 254 return MFC_RET_OK; 255 } 256 257 SSBSIP_MFC_ERROR_CODE SsbSipMfcDecClose(void *openHandle) 258 { 259 int ret_code; 260 _MFCLIB *pCTX; 261 mfc_common_args free_arg; 262 263 if (openHandle == NULL) { 264 LOGE("SsbSipMfcDecClose: openHandle is NULL\n"); 265 return MFC_RET_INVALID_PARAM; 266 } 267 268 pCTX = (_MFCLIB *)openHandle; 269 270 if (pCTX->inter_buff_status & MFC_USE_YUV_BUFF) { 271 free_arg.args.mem_free.u_addr = pCTX->virFrmBuf.luma; 272 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); 273 free_arg.args.mem_free.u_addr = pCTX->virFrmBuf.chroma; 274 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); 275 } 276 277 if (pCTX->inter_buff_status & MFC_USE_STRM_BUFF) { 278 free_arg.args.mem_free.u_addr = pCTX->virStrmBuf; 279 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); 280 } 281 282 pCTX->inter_buff_status = MFC_USE_NONE; 283 284 munmap((void *)pCTX->mapped_addr, MMAP_BUFFER_SIZE_MMAP); 285 close(pCTX->hMFC); 286 free(pCTX); 287 288 return MFC_RET_OK; 289 } 290 291 void *SsbSipMfcDecGetInBuf(void *openHandle, void **phyInBuf, int inputBufferSize) 292 { 293 int ret_code; 294 _MFCLIB *pCTX; 295 mfc_common_args user_addr_arg, phys_addr_arg; 296 297 if (inputBufferSize < 0) { 298 LOGE("SsbSipMfcDecGetInBuf: inputBufferSize = %d is invalid\n", inputBufferSize); 299 return NULL; 300 } 301 302 if (openHandle == NULL) { 303 LOGE("SsbSipMfcDecGetInBuf: openHandle is NULL\n"); 304 return NULL; 305 } 306 307 pCTX = (_MFCLIB *)openHandle; 308 309 user_addr_arg.args.mem_alloc.codec_type = pCTX->codec_type; 310 user_addr_arg.args.mem_alloc.buff_size = inputBufferSize; 311 user_addr_arg.args.mem_alloc.mapped_addr = pCTX->mapped_addr; 312 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_IN_BUF, &user_addr_arg); 313 if (ret_code < 0) { 314 LOGE("SsbSipMfcDecGetInBuf: IOCTL_MFC_GET_IN_BUF failed\n"); 315 return NULL; 316 } 317 pCTX->virStrmBuf = user_addr_arg.args.mem_alloc.out_uaddr; 318 pCTX->phyStrmBuf = user_addr_arg.args.mem_alloc.out_paddr; 319 pCTX->sizeStrmBuf = inputBufferSize; 320 pCTX->inter_buff_status |= MFC_USE_STRM_BUFF; 321 322 *phyInBuf = (void *)pCTX->phyStrmBuf; 323 324 return (void *)pCTX->virStrmBuf; 325 } 326 327 SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetInBuf(void *openHandle, void *phyInBuf, void *virInBuf, int inputBufferSize) 328 { 329 _MFCLIB *pCTX; 330 331 if (openHandle == NULL) { 332 LOGE("SsbSipMfcDecSetInBuf: openHandle is NULL\n"); 333 return MFC_RET_INVALID_PARAM; 334 } 335 336 pCTX = (_MFCLIB *)openHandle; 337 338 pCTX->phyStrmBuf = (int)phyInBuf; 339 pCTX->virStrmBuf = (int)virInBuf; 340 pCTX->sizeStrmBuf = inputBufferSize; 341 return MFC_RET_OK; 342 } 343 344 SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecGetOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info) 345 { 346 _MFCLIB *pCTX; 347 348 if (openHandle == NULL) { 349 LOGE("SsbSipMfcDecGetOutBuf: openHandle is NULL\n"); 350 return MFC_GETOUTBUF_DISPLAY_END; 351 } 352 353 pCTX = (_MFCLIB *)openHandle; 354 355 output_info->YPhyAddr = pCTX->decOutInfo.YPhyAddr; 356 output_info->CPhyAddr = pCTX->decOutInfo.CPhyAddr; 357 358 output_info->YVirAddr = pCTX->decOutInfo.YVirAddr; 359 output_info->CVirAddr = pCTX->decOutInfo.CVirAddr; 360 361 output_info->img_width = pCTX->decOutInfo.img_width; 362 output_info->img_height= pCTX->decOutInfo.img_height; 363 364 output_info->buf_width = pCTX->decOutInfo.buf_width; 365 output_info->buf_height= pCTX->decOutInfo.buf_height; 366 367 /* by RainAde : for crop information */ 368 output_info->crop_top_offset = pCTX->decOutInfo.crop_top_offset; 369 output_info->crop_bottom_offset= pCTX->decOutInfo.crop_bottom_offset; 370 output_info->crop_left_offset = pCTX->decOutInfo.crop_left_offset; 371 output_info->crop_right_offset= pCTX->decOutInfo.crop_right_offset; 372 373 if (pCTX->displayStatus == 0) 374 return MFC_GETOUTBUF_DISPLAY_END; 375 else if (pCTX->displayStatus == 1) 376 return MFC_GETOUTBUF_DISPLAY_DECODING; 377 else if (pCTX->displayStatus == 2) 378 return MFC_GETOUTBUF_DISPLAY_ONLY; 379 else 380 return MFC_GETOUTBUF_DECODING_ONLY; 381 } 382 383 SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value) 384 { 385 int ret_code; 386 _MFCLIB *pCTX; 387 mfc_common_args DecArg; 388 SSBSIP_MFC_IMG_RESOLUTION *img_resolution; 389 390 if (openHandle == NULL) { 391 LOGE("SsbSipMfcDecSetConfig: openHandle is NULL\n"); 392 return MFC_RET_INVALID_PARAM; 393 } 394 395 if (value == NULL) { 396 LOGE("SsbSipMfcDecSetConfig: value is NULL\n"); 397 return MFC_RET_INVALID_PARAM; 398 } 399 400 pCTX = (_MFCLIB *)openHandle; 401 memset(&DecArg, 0x00, sizeof(DecArg)); 402 403 switch (conf_type) { 404 case MFC_DEC_SETCONF_POST_ENABLE: 405 case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM: 406 case MFC_DEC_SETCONF_DISPLAY_DELAY: 407 case MFC_DEC_SETCONF_IS_LAST_FRAME: 408 case MFC_DEC_SETCONF_SLICE_ENABLE: 409 case MFC_DEC_SETCONF_CRC_ENABLE: 410 DecArg.args.set_config.in_config_param = conf_type; 411 DecArg.args.set_config.in_config_value[0] = *((unsigned int *)value); 412 DecArg.args.set_config.in_config_value[1] = 0; 413 break; 414 415 case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT: 416 img_resolution = (SSBSIP_MFC_IMG_RESOLUTION *)value; 417 DecArg.args.set_config.in_config_param = conf_type; 418 DecArg.args.set_config.in_config_value[0] = img_resolution->width; 419 DecArg.args.set_config.in_config_value[1] = img_resolution->height; 420 break; 421 422 case MFC_DEC_SETCONF_FRAME_TAG: 423 pCTX->in_frametag = *((int *)value); 424 return MFC_RET_OK; 425 426 default: 427 LOGE("SsbSipMfcDecSetConfig: No such conf_type is supported.\n"); 428 return MFC_RET_INVALID_PARAM; 429 } 430 431 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_SET_CONFIG, &DecArg); 432 if (DecArg.ret_code != MFC_RET_OK) { 433 LOGE("SsbSipMfcDecSetConfig: IOCTL_MFC_SET_CONFIG failed(ret : %d, conf_type: %d)\n", DecArg.ret_code, conf_type); 434 return MFC_RET_DEC_SET_CONF_FAIL; 435 } 436 437 return MFC_RET_OK; 438 } 439 440 SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value) 441 { 442 int ret_code; 443 _MFCLIB *pCTX; 444 mfc_common_args DecArg; 445 446 SSBSIP_MFC_IMG_RESOLUTION *img_resolution; 447 SSBSIP_MFC_CROP_INFORMATION *crop_information; 448 MFC_CRC_DATA *crc_data; 449 450 if (openHandle == NULL) { 451 LOGE("SsbSipMfcDecGetConfig: openHandle is NULL\n"); 452 return MFC_RET_FAIL; 453 } 454 455 if (value == NULL) { 456 LOGE("SsbSipMfcDecGetConfig: value is NULL\n"); 457 return MFC_RET_FAIL; 458 } 459 460 pCTX = (_MFCLIB *)openHandle; 461 memset(&DecArg, 0x00, sizeof(DecArg)); 462 463 switch (conf_type) { 464 case MFC_DEC_GETCONF_BUF_WIDTH_HEIGHT: 465 img_resolution = (SSBSIP_MFC_IMG_RESOLUTION *)value; 466 img_resolution->width = pCTX->decOutInfo.img_width; 467 img_resolution->height = pCTX->decOutInfo.img_height; 468 img_resolution->buf_width = pCTX->decOutInfo.buf_width; 469 img_resolution->buf_height = pCTX->decOutInfo.buf_height; 470 break; 471 472 /* Added by RainAde */ 473 case MFC_DEC_GETCONF_CROP_INFO: 474 crop_information = (SSBSIP_MFC_CROP_INFORMATION*)value; 475 crop_information->crop_top_offset = pCTX->decOutInfo.crop_top_offset; 476 crop_information->crop_bottom_offset= pCTX->decOutInfo.crop_bottom_offset; 477 crop_information->crop_left_offset = pCTX->decOutInfo.crop_left_offset; 478 crop_information->crop_right_offset= pCTX->decOutInfo.crop_right_offset; 479 break; 480 481 case MFC_DEC_GETCONF_CRC_DATA: 482 crc_data = (MFC_CRC_DATA *)value; 483 484 DecArg.args.get_config.in_config_param = conf_type; 485 486 ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_CONFIG, &DecArg); 487 if (DecArg.ret_code != MFC_RET_OK) { 488 LOGE("SsbSipMfcDecGetConfig: IOCTL_MFC_GET_CONFIG failed(ret : %d, conf_type: %d)\n", DecArg.ret_code, conf_type); 489 return MFC_RET_DEC_GET_CONF_FAIL; 490 } 491 crc_data->luma0 = DecArg.args.get_config.out_config_value[0]; 492 crc_data->chroma0 = DecArg.args.get_config.out_config_value[1]; 493 break; 494 495 case MFC_DEC_GETCONF_FRAME_TAG: 496 *((unsigned int *)value) = pCTX->out_frametag_top; 497 break; 498 499 default: 500 LOGE("SsbSipMfcDecGetConfig: No such conf_type is supported.\n"); 501 return MFC_RET_INVALID_PARAM; 502 } 503 504 return MFC_RET_OK; 505 } 506 507 int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) 508 { 509 int pixel_x_m1, pixel_y_m1; 510 int roundup_x, roundup_y; 511 int linear_addr0, linear_addr1, bank_addr ; 512 int x_addr; 513 int trans_addr; 514 515 pixel_x_m1 = x_size -1; 516 pixel_y_m1 = y_size -1; 517 518 roundup_x = ((pixel_x_m1 >> 7) + 1); 519 roundup_y = ((pixel_x_m1 >> 6) + 1); 520 521 x_addr = x_pos >> 2; 522 523 if ((y_size <= y_pos+32) && ( y_pos < y_size) && 524 (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) { 525 linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf)); 526 linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); 527 528 if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) 529 bank_addr = ((x_addr >> 4) & 0x1); 530 else 531 bank_addr = 0x2 | ((x_addr >> 4) & 0x1); 532 } else { 533 linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); 534 linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); 535 536 if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) 537 bank_addr = ((x_addr >> 4) & 0x1); 538 else 539 bank_addr = 0x2 | ((x_addr >> 4) & 0x1); 540 } 541 542 linear_addr0 = linear_addr0 << 2; 543 trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0; 544 545 return trans_addr; 546 } 547 548 void Y_tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) 549 { 550 int trans_addr; 551 unsigned int i, j, k, index; 552 unsigned char data8[4]; 553 unsigned int max_index = x_size * y_size; 554 555 for (i = 0; i < y_size; i = i + 16) { 556 for (j = 0; j < x_size; j = j + 16) { 557 trans_addr = tile_4x2_read(x_size, y_size, j, i); 558 for (k = 0; k < 16; k++) { 559 /* limit check - prohibit segmentation fault */ 560 index = (i * x_size) + (x_size * k) + j; 561 /* remove equal condition to solve thumbnail bug */ 562 if (index + 16 > max_index) { 563 continue; 564 } 565 566 data8[0] = p_tiled_addr[trans_addr + 64 * k + 0]; 567 data8[1] = p_tiled_addr[trans_addr + 64 * k + 1]; 568 data8[2] = p_tiled_addr[trans_addr + 64 * k + 2]; 569 data8[3] = p_tiled_addr[trans_addr + 64 * k + 3]; 570 571 p_linear_addr[index] = data8[0]; 572 p_linear_addr[index + 1] = data8[1]; 573 p_linear_addr[index + 2] = data8[2]; 574 p_linear_addr[index + 3] = data8[3]; 575 576 data8[0] = p_tiled_addr[trans_addr + 64 * k + 4]; 577 data8[1] = p_tiled_addr[trans_addr + 64 * k + 5]; 578 data8[2] = p_tiled_addr[trans_addr + 64 * k + 6]; 579 data8[3] = p_tiled_addr[trans_addr + 64 * k + 7]; 580 581 p_linear_addr[index + 4] = data8[0]; 582 p_linear_addr[index + 5] = data8[1]; 583 p_linear_addr[index + 6] = data8[2]; 584 p_linear_addr[index + 7] = data8[3]; 585 586 data8[0] = p_tiled_addr[trans_addr + 64 * k + 8]; 587 data8[1] = p_tiled_addr[trans_addr + 64 * k + 9]; 588 data8[2] = p_tiled_addr[trans_addr + 64 * k + 10]; 589 data8[3] = p_tiled_addr[trans_addr + 64 * k + 11]; 590 591 p_linear_addr[index + 8] = data8[0]; 592 p_linear_addr[index + 9] = data8[1]; 593 p_linear_addr[index + 10] = data8[2]; 594 p_linear_addr[index + 11] = data8[3]; 595 596 data8[0] = p_tiled_addr[trans_addr + 64 * k + 12]; 597 data8[1] = p_tiled_addr[trans_addr + 64 * k + 13]; 598 data8[2] = p_tiled_addr[trans_addr + 64 * k + 14]; 599 data8[3] = p_tiled_addr[trans_addr + 64 * k + 15]; 600 601 p_linear_addr[index + 12] = data8[0]; 602 p_linear_addr[index + 13] = data8[1]; 603 p_linear_addr[index + 14] = data8[2]; 604 p_linear_addr[index + 15] = data8[3]; 605 } 606 } 607 } 608 } 609 610 void CbCr_tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) 611 { 612 int trans_addr; 613 unsigned int i, j, k, index; 614 unsigned char data8[4]; 615 unsigned int half_y_size = y_size / 2; 616 unsigned int max_index = x_size * half_y_size; 617 unsigned char *pUVAddr[2]; 618 619 pUVAddr[0] = p_linear_addr; 620 pUVAddr[1] = p_linear_addr + ((x_size * half_y_size) / 2); 621 622 for (i = 0; i < half_y_size; i = i + 16) { 623 for (j = 0; j < x_size; j = j + 16) { 624 trans_addr = tile_4x2_read(x_size, half_y_size, j, i); 625 for (k = 0; k < 16; k++) { 626 /* limit check - prohibit segmentation fault */ 627 index = (i * x_size) + (x_size * k) + j; 628 /* remove equal condition to solve thumbnail bug */ 629 if (index + 16 > max_index) { 630 continue; 631 } 632 633 data8[0] = p_tiled_addr[trans_addr + 64 * k + 0]; 634 data8[1] = p_tiled_addr[trans_addr + 64 * k + 1]; 635 data8[2] = p_tiled_addr[trans_addr + 64 * k + 2]; 636 data8[3] = p_tiled_addr[trans_addr + 64 * k + 3]; 637 638 pUVAddr[index%2][index/2] = data8[0]; 639 pUVAddr[(index+1)%2][(index+1)/2] = data8[1]; 640 pUVAddr[(index+2)%2][(index+2)/2] = data8[2]; 641 pUVAddr[(index+3)%2][(index+3)/2] = data8[3]; 642 643 data8[0] = p_tiled_addr[trans_addr + 64 * k + 4]; 644 data8[1] = p_tiled_addr[trans_addr + 64 * k + 5]; 645 data8[2] = p_tiled_addr[trans_addr + 64 * k + 6]; 646 data8[3] = p_tiled_addr[trans_addr + 64 * k + 7]; 647 648 pUVAddr[(index+4)%2][(index+4)/2] = data8[0]; 649 pUVAddr[(index+5)%2][(index+5)/2] = data8[1]; 650 pUVAddr[(index+6)%2][(index+6)/2] = data8[2]; 651 pUVAddr[(index+7)%2][(index+7)/2] = data8[3]; 652 653 data8[0] = p_tiled_addr[trans_addr + 64 * k + 8]; 654 data8[1] = p_tiled_addr[trans_addr + 64 * k + 9]; 655 data8[2] = p_tiled_addr[trans_addr + 64 * k + 10]; 656 data8[3] = p_tiled_addr[trans_addr + 64 * k + 11]; 657 658 pUVAddr[(index+8)%2][(index+8)/2] = data8[0]; 659 pUVAddr[(index+9)%2][(index+9)/2] = data8[1]; 660 pUVAddr[(index+10)%2][(index+10)/2] = data8[2]; 661 pUVAddr[(index+11)%2][(index+11)/2] = data8[3]; 662 663 data8[0] = p_tiled_addr[trans_addr + 64 * k + 12]; 664 data8[1] = p_tiled_addr[trans_addr + 64 * k + 13]; 665 data8[2] = p_tiled_addr[trans_addr + 64 * k + 14]; 666 data8[3] = p_tiled_addr[trans_addr + 64 * k + 15]; 667 668 pUVAddr[(index+12)%2][(index+12)/2] = data8[0]; 669 pUVAddr[(index+13)%2][(index+13)/2] = data8[1]; 670 pUVAddr[(index+14)%2][(index+14)/2] = data8[2]; 671 pUVAddr[(index+15)%2][(index+15)/2] = data8[3]; 672 } 673 } 674 } 675 } 676