1 #ifndef ISP2401 2 /* 3 * Support for Intel Camera Imaging ISP subsystem. 4 * Copyright (c) 2015, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 #else 16 /* 17 Support for Intel Camera Imaging ISP subsystem. 18 Copyright (c) 2010 - 2015, Intel Corporation. 19 20 This program is free software; you can redistribute it and/or modify it 21 under the terms and conditions of the GNU General Public License, 22 version 2, as published by the Free Software Foundation. 23 24 This program is distributed in the hope it will be useful, but WITHOUT 25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 26 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 27 more details. 28 */ 29 #endif 30 31 #include "ia_css_frame.h" 32 #include <math_support.h> 33 #include "assert_support.h" 34 #include "ia_css_debug.h" 35 #include "isp.h" 36 #include "sh_css_internal.h" 37 #include "memory_access.h" 38 39 #define NV12_TILEY_TILE_WIDTH 128 40 #define NV12_TILEY_TILE_HEIGHT 32 41 42 /************************************************************************** 43 ** Static functions declarations 44 **************************************************************************/ 45 static void frame_init_plane(struct ia_css_frame_plane *plane, 46 unsigned int width, 47 unsigned int stride, 48 unsigned int height, 49 unsigned int offset); 50 51 static void frame_init_single_plane(struct ia_css_frame *frame, 52 struct ia_css_frame_plane *plane, 53 unsigned int height, 54 unsigned int subpixels_per_line, 55 unsigned int bytes_per_pixel); 56 57 static void frame_init_raw_single_plane( 58 struct ia_css_frame *frame, 59 struct ia_css_frame_plane *plane, 60 unsigned int height, 61 unsigned int subpixels_per_line, 62 unsigned int bits_per_pixel); 63 64 static void frame_init_mipi_plane(struct ia_css_frame *frame, 65 struct ia_css_frame_plane *plane, 66 unsigned int height, 67 unsigned int subpixels_per_line, 68 unsigned int bytes_per_pixel); 69 70 static void frame_init_nv_planes(struct ia_css_frame *frame, 71 unsigned int horizontal_decimation, 72 unsigned int vertical_decimation, 73 unsigned int bytes_per_element); 74 75 static void frame_init_yuv_planes(struct ia_css_frame *frame, 76 unsigned int horizontal_decimation, 77 unsigned int vertical_decimation, 78 bool swap_uv, 79 unsigned int bytes_per_element); 80 81 static void frame_init_rgb_planes(struct ia_css_frame *frame, 82 unsigned int bytes_per_element); 83 84 static void frame_init_qplane6_planes(struct ia_css_frame *frame); 85 86 static enum ia_css_err frame_allocate_buffer_data(struct ia_css_frame *frame); 87 88 static enum ia_css_err frame_allocate_with_data(struct ia_css_frame **frame, 89 unsigned int width, 90 unsigned int height, 91 enum ia_css_frame_format format, 92 unsigned int padded_width, 93 unsigned int raw_bit_depth, 94 bool contiguous); 95 96 static struct ia_css_frame *frame_create(unsigned int width, 97 unsigned int height, 98 enum ia_css_frame_format format, 99 unsigned int padded_width, 100 unsigned int raw_bit_depth, 101 bool contiguous, 102 bool valid); 103 104 static unsigned 105 ia_css_elems_bytes_from_info( 106 const struct ia_css_frame_info *info); 107 108 /************************************************************************** 109 ** CSS API functions, exposed by ia_css.h 110 **************************************************************************/ 111 112 void ia_css_frame_zero(struct ia_css_frame *frame) 113 { 114 assert(frame); 115 mmgr_clear(frame->data, frame->data_bytes); 116 } 117 118 enum ia_css_err ia_css_frame_allocate_from_info(struct ia_css_frame **frame, 119 const struct ia_css_frame_info *info) 120 { 121 enum ia_css_err err = IA_CSS_SUCCESS; 122 123 if (!frame || !info) 124 return IA_CSS_ERR_INVALID_ARGUMENTS; 125 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 126 "ia_css_frame_allocate_from_info() enter:\n"); 127 err = 128 ia_css_frame_allocate(frame, info->res.width, info->res.height, 129 info->format, info->padded_width, 130 info->raw_bit_depth); 131 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 132 "ia_css_frame_allocate_from_info() leave:\n"); 133 return err; 134 } 135 136 enum ia_css_err ia_css_frame_allocate(struct ia_css_frame **frame, 137 unsigned int width, 138 unsigned int height, 139 enum ia_css_frame_format format, 140 unsigned int padded_width, 141 unsigned int raw_bit_depth) 142 { 143 enum ia_css_err err = IA_CSS_SUCCESS; 144 145 if (!frame || width == 0 || height == 0) 146 return IA_CSS_ERR_INVALID_ARGUMENTS; 147 148 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 149 #ifndef ISP2401 150 "ia_css_frame_allocate() enter: width=%d, height=%d, format=%d\n", 151 width, height, format); 152 #else 153 "ia_css_frame_allocate() enter: width=%d, height=%d, format=%d, padded_width=%d, raw_bit_depth=%d\n", 154 width, height, format, padded_width, raw_bit_depth); 155 #endif 156 157 err = frame_allocate_with_data(frame, width, height, format, 158 padded_width, raw_bit_depth, false); 159 160 #ifndef ISP2401 161 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 162 "ia_css_frame_allocate() leave: frame=%p\n", *frame); 163 #else 164 if ((*frame) && err == IA_CSS_SUCCESS) 165 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 166 "ia_css_frame_allocate() leave: frame=%p, data(DDR address)=0x%x\n", *frame, 167 (*frame)->data); 168 else 169 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 170 "ia_css_frame_allocate() leave: frame=%p, data(DDR address)=0x%x\n", 171 (void *)-1, (unsigned int)-1); 172 #endif 173 174 return err; 175 } 176 177 enum ia_css_err ia_css_frame_map(struct ia_css_frame **frame, 178 const struct ia_css_frame_info *info, 179 const void __user *data, 180 u16 attribute, 181 void *context) 182 { 183 enum ia_css_err err = IA_CSS_SUCCESS; 184 struct ia_css_frame *me; 185 186 assert(frame); 187 188 /* Create the frame structure */ 189 err = ia_css_frame_create_from_info(&me, info); 190 191 if (err != IA_CSS_SUCCESS) 192 return err; 193 194 if (err == IA_CSS_SUCCESS) { 195 /* use mmgr_mmap to map */ 196 me->data = (ia_css_ptr) mmgr_mmap(data, 197 me->data_bytes, 198 attribute, context); 199 if (me->data == mmgr_NULL) 200 err = IA_CSS_ERR_INVALID_ARGUMENTS; 201 } 202 203 if (err != IA_CSS_SUCCESS) { 204 sh_css_free(me); 205 #ifndef ISP2401 206 return err; 207 #else 208 me = NULL; 209 #endif 210 } 211 212 *frame = me; 213 214 return err; 215 } 216 217 enum ia_css_err ia_css_frame_create_from_info(struct ia_css_frame **frame, 218 const struct ia_css_frame_info *info) 219 { 220 enum ia_css_err err = IA_CSS_SUCCESS; 221 struct ia_css_frame *me; 222 223 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 224 "ia_css_frame_create_from_info() enter:\n"); 225 if (!frame || !info) { 226 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 227 "ia_css_frame_create_from_info() leave: invalid arguments\n"); 228 return IA_CSS_ERR_INVALID_ARGUMENTS; 229 } 230 231 me = frame_create(info->res.width, 232 info->res.height, 233 info->format, 234 info->padded_width, 235 info->raw_bit_depth, 236 false, 237 false); 238 if (!me) { 239 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 240 "ia_css_frame_create_from_info() leave: frame create failed\n"); 241 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 242 } 243 244 err = ia_css_frame_init_planes(me); 245 246 #ifndef ISP2401 247 if (err == IA_CSS_SUCCESS) 248 *frame = me; 249 else 250 #else 251 if (err != IA_CSS_SUCCESS) { 252 #endif 253 sh_css_free(me); 254 #ifdef ISP2401 255 me = NULL; 256 } 257 258 *frame = me; 259 #endif 260 261 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 262 "ia_css_frame_create_from_info() leave:\n"); 263 264 return err; 265 } 266 267 enum ia_css_err ia_css_frame_set_data(struct ia_css_frame *frame, 268 const ia_css_ptr mapped_data, 269 size_t data_bytes) 270 { 271 enum ia_css_err err = IA_CSS_SUCCESS; 272 273 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 274 "ia_css_frame_set_data() enter:\n"); 275 if (!frame) { 276 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 277 "ia_css_frame_set_data() leave: NULL frame\n"); 278 return IA_CSS_ERR_INVALID_ARGUMENTS; 279 } 280 281 /* If we are setting a valid data. 282 * Make sure that there is enough 283 * room for the expected frame format 284 */ 285 if ((mapped_data != mmgr_NULL) && (frame->data_bytes > data_bytes)) { 286 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 287 "ia_css_frame_set_data() leave: invalid arguments\n"); 288 return IA_CSS_ERR_INVALID_ARGUMENTS; 289 } 290 291 frame->data = mapped_data; 292 293 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_set_data() leave:\n"); 294 295 return err; 296 } 297 298 enum ia_css_err ia_css_frame_allocate_contiguous(struct ia_css_frame **frame, 299 unsigned int width, 300 unsigned int height, 301 enum ia_css_frame_format format, 302 unsigned int padded_width, 303 unsigned int raw_bit_depth) 304 { 305 enum ia_css_err err = IA_CSS_SUCCESS; 306 307 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 308 "ia_css_frame_allocate_contiguous() " 309 #ifndef ISP2401 310 "enter: width=%d, height=%d, format=%d\n", 311 width, height, format); 312 #else 313 "enter: width=%d, height=%d, format=%d, padded_width=%d, raw_bit_depth=%d\n", 314 width, height, format, padded_width, raw_bit_depth); 315 #endif 316 317 err = frame_allocate_with_data(frame, width, height, format, 318 padded_width, raw_bit_depth, true); 319 320 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 321 "ia_css_frame_allocate_contiguous() leave: frame=%p\n", 322 frame ? *frame : (void *)-1); 323 324 return err; 325 } 326 327 enum ia_css_err ia_css_frame_allocate_contiguous_from_info( 328 struct ia_css_frame **frame, 329 const struct ia_css_frame_info *info) 330 { 331 enum ia_css_err err = IA_CSS_SUCCESS; 332 333 assert(frame); 334 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 335 "ia_css_frame_allocate_contiguous_from_info() enter:\n"); 336 err = ia_css_frame_allocate_contiguous(frame, 337 info->res.width, 338 info->res.height, 339 info->format, 340 info->padded_width, 341 info->raw_bit_depth); 342 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 343 "ia_css_frame_allocate_contiguous_from_info() leave:\n"); 344 return err; 345 } 346 347 void ia_css_frame_free(struct ia_css_frame *frame) 348 { 349 IA_CSS_ENTER_PRIVATE("frame = %p", frame); 350 351 if (frame) { 352 hmm_free(frame->data); 353 sh_css_free(frame); 354 } 355 356 IA_CSS_LEAVE_PRIVATE("void"); 357 } 358 359 /************************************************************************** 360 ** Module public functions 361 **************************************************************************/ 362 363 enum ia_css_err ia_css_frame_check_info(const struct ia_css_frame_info *info) 364 { 365 assert(info); 366 if (info->res.width == 0 || info->res.height == 0) 367 return IA_CSS_ERR_INVALID_ARGUMENTS; 368 return IA_CSS_SUCCESS; 369 } 370 371 enum ia_css_err ia_css_frame_init_planes(struct ia_css_frame *frame) 372 { 373 assert(frame); 374 375 switch (frame->info.format) { 376 case IA_CSS_FRAME_FORMAT_MIPI: 377 frame_init_mipi_plane(frame, &frame->planes.raw, 378 frame->info.res.height, 379 frame->info.padded_width, 380 frame->info.raw_bit_depth <= 8 ? 1 : 2); 381 break; 382 case IA_CSS_FRAME_FORMAT_RAW_PACKED: 383 frame_init_raw_single_plane(frame, &frame->planes.raw, 384 frame->info.res.height, 385 frame->info.padded_width, 386 frame->info.raw_bit_depth); 387 break; 388 case IA_CSS_FRAME_FORMAT_RAW: 389 frame_init_single_plane(frame, &frame->planes.raw, 390 frame->info.res.height, 391 frame->info.padded_width, 392 frame->info.raw_bit_depth <= 8 ? 1 : 2); 393 break; 394 case IA_CSS_FRAME_FORMAT_RGB565: 395 frame_init_single_plane(frame, &frame->planes.rgb, 396 frame->info.res.height, 397 frame->info.padded_width, 2); 398 break; 399 case IA_CSS_FRAME_FORMAT_RGBA888: 400 frame_init_single_plane(frame, &frame->planes.rgb, 401 frame->info.res.height, 402 frame->info.padded_width * 4, 1); 403 break; 404 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888: 405 frame_init_rgb_planes(frame, 1); 406 break; 407 /* yuyv and uyvu have the same frame layout, only the data 408 * positioning differs. 409 */ 410 case IA_CSS_FRAME_FORMAT_YUYV: 411 case IA_CSS_FRAME_FORMAT_UYVY: 412 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8: 413 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8: 414 frame_init_single_plane(frame, &frame->planes.yuyv, 415 frame->info.res.height, 416 frame->info.padded_width * 2, 1); 417 break; 418 case IA_CSS_FRAME_FORMAT_YUV_LINE: 419 /* Needs 3 extra lines to allow vf_pp prefetching */ 420 frame_init_single_plane(frame, &frame->planes.yuyv, 421 frame->info.res.height * 3 / 2 + 3, 422 frame->info.padded_width, 1); 423 break; 424 case IA_CSS_FRAME_FORMAT_NV11: 425 frame_init_nv_planes(frame, 4, 1, 1); 426 break; 427 /* nv12 and nv21 have the same frame layout, only the data 428 * positioning differs. 429 */ 430 case IA_CSS_FRAME_FORMAT_NV12: 431 case IA_CSS_FRAME_FORMAT_NV21: 432 case IA_CSS_FRAME_FORMAT_NV12_TILEY: 433 frame_init_nv_planes(frame, 2, 2, 1); 434 break; 435 case IA_CSS_FRAME_FORMAT_NV12_16: 436 frame_init_nv_planes(frame, 2, 2, 2); 437 break; 438 /* nv16 and nv61 have the same frame layout, only the data 439 * positioning differs. 440 */ 441 case IA_CSS_FRAME_FORMAT_NV16: 442 case IA_CSS_FRAME_FORMAT_NV61: 443 frame_init_nv_planes(frame, 2, 1, 1); 444 break; 445 case IA_CSS_FRAME_FORMAT_YUV420: 446 frame_init_yuv_planes(frame, 2, 2, false, 1); 447 break; 448 case IA_CSS_FRAME_FORMAT_YUV422: 449 frame_init_yuv_planes(frame, 2, 1, false, 1); 450 break; 451 case IA_CSS_FRAME_FORMAT_YUV444: 452 frame_init_yuv_planes(frame, 1, 1, false, 1); 453 break; 454 case IA_CSS_FRAME_FORMAT_YUV420_16: 455 frame_init_yuv_planes(frame, 2, 2, false, 2); 456 break; 457 case IA_CSS_FRAME_FORMAT_YUV422_16: 458 frame_init_yuv_planes(frame, 2, 1, false, 2); 459 break; 460 case IA_CSS_FRAME_FORMAT_YV12: 461 frame_init_yuv_planes(frame, 2, 2, true, 1); 462 break; 463 case IA_CSS_FRAME_FORMAT_YV16: 464 frame_init_yuv_planes(frame, 2, 1, true, 1); 465 break; 466 case IA_CSS_FRAME_FORMAT_QPLANE6: 467 frame_init_qplane6_planes(frame); 468 break; 469 case IA_CSS_FRAME_FORMAT_BINARY_8: 470 frame_init_single_plane(frame, &frame->planes.binary.data, 471 frame->info.res.height, 472 frame->info.padded_width, 1); 473 frame->planes.binary.size = 0; 474 break; 475 default: 476 return IA_CSS_ERR_INVALID_ARGUMENTS; 477 } 478 return IA_CSS_SUCCESS; 479 } 480 481 void ia_css_frame_info_set_width(struct ia_css_frame_info *info, 482 unsigned int width, 483 unsigned int min_padded_width) 484 { 485 unsigned int align; 486 487 IA_CSS_ENTER_PRIVATE("info = %p,width = %d, minimum padded width = %d", 488 info, width, min_padded_width); 489 if (!info) { 490 IA_CSS_ERROR("NULL input parameter"); 491 IA_CSS_LEAVE_PRIVATE(""); 492 return; 493 } 494 if (min_padded_width > width) 495 align = min_padded_width; 496 else 497 align = width; 498 499 info->res.width = width; 500 /* frames with a U and V plane of 8 bits per pixel need to have 501 all planes aligned, this means double the alignment for the 502 Y plane if the horizontal decimation is 2. */ 503 if (info->format == IA_CSS_FRAME_FORMAT_YUV420 || 504 info->format == IA_CSS_FRAME_FORMAT_YV12 || 505 info->format == IA_CSS_FRAME_FORMAT_NV12 || 506 info->format == IA_CSS_FRAME_FORMAT_NV21 || 507 info->format == IA_CSS_FRAME_FORMAT_BINARY_8 || 508 info->format == IA_CSS_FRAME_FORMAT_YUV_LINE) 509 info->padded_width = 510 CEIL_MUL(align, 2 * HIVE_ISP_DDR_WORD_BYTES); 511 else if (info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY) 512 info->padded_width = CEIL_MUL(align, NV12_TILEY_TILE_WIDTH); 513 else if (info->format == IA_CSS_FRAME_FORMAT_RAW || 514 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) 515 info->padded_width = CEIL_MUL(align, 2 * ISP_VEC_NELEMS); 516 else { 517 info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES); 518 } 519 IA_CSS_LEAVE_PRIVATE(""); 520 } 521 522 void ia_css_frame_info_set_format(struct ia_css_frame_info *info, 523 enum ia_css_frame_format format) 524 { 525 assert(info); 526 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 527 "ia_css_frame_info_set_format() enter:\n"); 528 info->format = format; 529 } 530 531 void ia_css_frame_info_init(struct ia_css_frame_info *info, 532 unsigned int width, 533 unsigned int height, 534 enum ia_css_frame_format format, 535 unsigned int aligned) 536 { 537 IA_CSS_ENTER_PRIVATE("info = %p, width = %d, height = %d, format = %d, aligned = %d", 538 info, width, height, format, aligned); 539 if (!info) { 540 IA_CSS_ERROR("NULL input parameter"); 541 IA_CSS_LEAVE_PRIVATE(""); 542 return; 543 } 544 info->res.height = height; 545 info->format = format; 546 ia_css_frame_info_set_width(info, width, aligned); 547 IA_CSS_LEAVE_PRIVATE(""); 548 } 549 550 void ia_css_frame_free_multiple(unsigned int num_frames, 551 struct ia_css_frame **frames_array) 552 { 553 unsigned int i; 554 555 for (i = 0; i < num_frames; i++) { 556 if (frames_array[i]) { 557 ia_css_frame_free(frames_array[i]); 558 frames_array[i] = NULL; 559 } 560 } 561 } 562 563 enum ia_css_err ia_css_frame_allocate_with_buffer_size( 564 struct ia_css_frame **frame, 565 const unsigned int buffer_size_bytes, 566 const bool contiguous) 567 { 568 /* AM: Body coppied from frame_allocate_with_data(). */ 569 enum ia_css_err err; 570 struct ia_css_frame *me = frame_create(0, 0, 571 IA_CSS_FRAME_FORMAT_NUM,/* Not valid format yet */ 572 0, 0, contiguous, false); 573 574 if (!me) 575 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 576 577 /* Get the data size */ 578 me->data_bytes = buffer_size_bytes; 579 580 err = frame_allocate_buffer_data(me); 581 582 if (err != IA_CSS_SUCCESS) { 583 sh_css_free(me); 584 #ifndef ISP2401 585 return err; 586 #else 587 me = NULL; 588 #endif 589 } 590 591 *frame = me; 592 593 return err; 594 } 595 596 bool ia_css_frame_info_is_same_resolution( 597 const struct ia_css_frame_info *info_a, 598 const struct ia_css_frame_info *info_b) 599 { 600 if (!info_a || !info_b) 601 return false; 602 return (info_a->res.width == info_b->res.width) && 603 (info_a->res.height == info_b->res.height); 604 } 605 606 bool ia_css_frame_is_same_type(const struct ia_css_frame *frame_a, 607 const struct ia_css_frame *frame_b) 608 { 609 bool is_equal = false; 610 const struct ia_css_frame_info *info_a = &frame_a->info, 611 *info_b = &frame_b->info; 612 613 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 614 "ia_css_frame_is_same_type() enter:\n"); 615 616 if (!info_a || !info_b) 617 return false; 618 if (info_a->format != info_b->format) 619 return false; 620 if (info_a->padded_width != info_b->padded_width) 621 return false; 622 is_equal = ia_css_frame_info_is_same_resolution(info_a, info_b); 623 624 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 625 "ia_css_frame_is_same_type() leave:\n"); 626 627 return is_equal; 628 } 629 630 void 631 ia_css_dma_configure_from_info( 632 struct dma_port_config *config, 633 const struct ia_css_frame_info *info) 634 { 635 unsigned int is_raw_packed = info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED; 636 unsigned int bits_per_pixel = is_raw_packed ? info->raw_bit_depth : 637 ia_css_elems_bytes_from_info(info) * 8; 638 unsigned int pix_per_ddrword = HIVE_ISP_DDR_WORD_BITS / bits_per_pixel; 639 unsigned int words_per_line = CEIL_DIV(info->padded_width, pix_per_ddrword); 640 unsigned int elems_b = pix_per_ddrword; 641 642 config->stride = HIVE_ISP_DDR_WORD_BYTES * words_per_line; 643 config->elems = (uint8_t)elems_b; 644 config->width = (uint16_t)info->res.width; 645 config->crop = 0; 646 assert(config->width <= info->padded_width); 647 } 648 649 /************************************************************************** 650 ** Static functions 651 **************************************************************************/ 652 653 static void frame_init_plane(struct ia_css_frame_plane *plane, 654 unsigned int width, 655 unsigned int stride, 656 unsigned int height, 657 unsigned int offset) 658 { 659 plane->height = height; 660 plane->width = width; 661 plane->stride = stride; 662 plane->offset = offset; 663 } 664 665 static void frame_init_single_plane(struct ia_css_frame *frame, 666 struct ia_css_frame_plane *plane, 667 unsigned int height, 668 unsigned int subpixels_per_line, 669 unsigned int bytes_per_pixel) 670 { 671 unsigned int stride; 672 673 stride = subpixels_per_line * bytes_per_pixel; 674 /* Frame height needs to be even number - needed by hw ISYS2401 675 In case of odd number, round up to even. 676 Images won't be impacted by this round up, 677 only needed by jpeg/embedded data. 678 As long as buffer allocation and release are using data_bytes, 679 there won't be memory leak. */ 680 frame->data_bytes = stride * CEIL_MUL2(height, 2); 681 frame_init_plane(plane, subpixels_per_line, stride, height, 0); 682 return; 683 } 684 685 static void frame_init_raw_single_plane( 686 struct ia_css_frame *frame, 687 struct ia_css_frame_plane *plane, 688 unsigned int height, 689 unsigned int subpixels_per_line, 690 unsigned int bits_per_pixel) 691 { 692 unsigned int stride; 693 694 assert(frame); 695 696 stride = HIVE_ISP_DDR_WORD_BYTES * 697 CEIL_DIV(subpixels_per_line, 698 HIVE_ISP_DDR_WORD_BITS / bits_per_pixel); 699 frame->data_bytes = stride * height; 700 frame_init_plane(plane, subpixels_per_line, stride, height, 0); 701 return; 702 } 703 704 static void frame_init_mipi_plane(struct ia_css_frame *frame, 705 struct ia_css_frame_plane *plane, 706 unsigned int height, 707 unsigned int subpixels_per_line, 708 unsigned int bytes_per_pixel) 709 { 710 unsigned int stride; 711 712 stride = subpixels_per_line * bytes_per_pixel; 713 frame->data_bytes = 8388608; /* 8*1024*1024 */ 714 frame->valid = false; 715 frame->contiguous = true; 716 frame_init_plane(plane, subpixels_per_line, stride, height, 0); 717 return; 718 } 719 720 static void frame_init_nv_planes(struct ia_css_frame *frame, 721 unsigned int horizontal_decimation, 722 unsigned int vertical_decimation, 723 unsigned int bytes_per_element) 724 { 725 unsigned int y_width = frame->info.padded_width; 726 unsigned int y_height = frame->info.res.height; 727 unsigned int uv_width; 728 unsigned int uv_height; 729 unsigned int y_bytes; 730 unsigned int uv_bytes; 731 unsigned int y_stride; 732 unsigned int uv_stride; 733 734 assert(horizontal_decimation != 0 && vertical_decimation != 0); 735 736 uv_width = 2 * (y_width / horizontal_decimation); 737 uv_height = y_height / vertical_decimation; 738 739 if (frame->info.format == IA_CSS_FRAME_FORMAT_NV12_TILEY) { 740 y_width = CEIL_MUL(y_width, NV12_TILEY_TILE_WIDTH); 741 uv_width = CEIL_MUL(uv_width, NV12_TILEY_TILE_WIDTH); 742 y_height = CEIL_MUL(y_height, NV12_TILEY_TILE_HEIGHT); 743 uv_height = CEIL_MUL(uv_height, NV12_TILEY_TILE_HEIGHT); 744 } 745 746 y_stride = y_width * bytes_per_element; 747 uv_stride = uv_width * bytes_per_element; 748 y_bytes = y_stride * y_height; 749 uv_bytes = uv_stride * uv_height; 750 751 frame->data_bytes = y_bytes + uv_bytes; 752 frame_init_plane(&frame->planes.nv.y, y_width, y_stride, y_height, 0); 753 frame_init_plane(&frame->planes.nv.uv, uv_width, 754 uv_stride, uv_height, y_bytes); 755 return; 756 } 757 758 static void frame_init_yuv_planes(struct ia_css_frame *frame, 759 unsigned int horizontal_decimation, 760 unsigned int vertical_decimation, 761 bool swap_uv, 762 unsigned int bytes_per_element) 763 { 764 unsigned int y_width = frame->info.padded_width, 765 y_height = frame->info.res.height, 766 uv_width = y_width / horizontal_decimation, 767 uv_height = y_height / vertical_decimation, 768 y_stride, y_bytes, uv_bytes, uv_stride; 769 770 y_stride = y_width * bytes_per_element; 771 uv_stride = uv_width * bytes_per_element; 772 y_bytes = y_stride * y_height; 773 uv_bytes = uv_stride * uv_height; 774 775 frame->data_bytes = y_bytes + 2 * uv_bytes; 776 frame_init_plane(&frame->planes.yuv.y, y_width, y_stride, y_height, 0); 777 if (swap_uv) { 778 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride, 779 uv_height, y_bytes); 780 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride, 781 uv_height, y_bytes + uv_bytes); 782 } else { 783 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride, 784 uv_height, y_bytes); 785 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride, 786 uv_height, y_bytes + uv_bytes); 787 } 788 return; 789 } 790 791 static void frame_init_rgb_planes(struct ia_css_frame *frame, 792 unsigned int bytes_per_element) 793 { 794 unsigned int width = frame->info.res.width, 795 height = frame->info.res.height, stride, bytes; 796 797 stride = width * bytes_per_element; 798 bytes = stride * height; 799 frame->data_bytes = 3 * bytes; 800 frame_init_plane(&frame->planes.planar_rgb.r, width, stride, height, 0); 801 frame_init_plane(&frame->planes.planar_rgb.g, 802 width, stride, height, 1 * bytes); 803 frame_init_plane(&frame->planes.planar_rgb.b, 804 width, stride, height, 2 * bytes); 805 return; 806 } 807 808 static void frame_init_qplane6_planes(struct ia_css_frame *frame) 809 { 810 unsigned int width = frame->info.padded_width / 2, 811 height = frame->info.res.height / 2, bytes, stride; 812 813 stride = width * 2; 814 bytes = stride * height; 815 816 frame->data_bytes = 6 * bytes; 817 frame_init_plane(&frame->planes.plane6.r, 818 width, stride, height, 0 * bytes); 819 frame_init_plane(&frame->planes.plane6.r_at_b, 820 width, stride, height, 1 * bytes); 821 frame_init_plane(&frame->planes.plane6.gr, 822 width, stride, height, 2 * bytes); 823 frame_init_plane(&frame->planes.plane6.gb, 824 width, stride, height, 3 * bytes); 825 frame_init_plane(&frame->planes.plane6.b, 826 width, stride, height, 4 * bytes); 827 frame_init_plane(&frame->planes.plane6.b_at_r, 828 width, stride, height, 5 * bytes); 829 return; 830 } 831 832 static enum ia_css_err frame_allocate_buffer_data(struct ia_css_frame *frame) 833 { 834 #ifdef ISP2401 835 IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes); 836 #endif 837 frame->data = mmgr_alloc_attr(frame->data_bytes, 838 frame->contiguous ? 839 MMGR_ATTRIBUTE_CONTIGUOUS : 840 MMGR_ATTRIBUTE_DEFAULT); 841 842 if (frame->data == mmgr_NULL) 843 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 844 return IA_CSS_SUCCESS; 845 } 846 847 static enum ia_css_err frame_allocate_with_data(struct ia_css_frame **frame, 848 unsigned int width, 849 unsigned int height, 850 enum ia_css_frame_format format, 851 unsigned int padded_width, 852 unsigned int raw_bit_depth, 853 bool contiguous) 854 { 855 enum ia_css_err err; 856 struct ia_css_frame *me = frame_create(width, 857 height, 858 format, 859 padded_width, 860 raw_bit_depth, 861 contiguous, 862 true); 863 864 if (!me) 865 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 866 867 err = ia_css_frame_init_planes(me); 868 869 if (err == IA_CSS_SUCCESS) 870 err = frame_allocate_buffer_data(me); 871 872 if (err != IA_CSS_SUCCESS) { 873 sh_css_free(me); 874 #ifndef ISP2401 875 return err; 876 #else 877 me = NULL; 878 #endif 879 } 880 881 *frame = me; 882 883 return err; 884 } 885 886 static struct ia_css_frame *frame_create(unsigned int width, 887 unsigned int height, 888 enum ia_css_frame_format format, 889 unsigned int padded_width, 890 unsigned int raw_bit_depth, 891 bool contiguous, 892 bool valid) 893 { 894 struct ia_css_frame *me = sh_css_malloc(sizeof(*me)); 895 896 if (!me) 897 return NULL; 898 899 memset(me, 0, sizeof(*me)); 900 me->info.res.width = width; 901 me->info.res.height = height; 902 me->info.format = format; 903 me->info.padded_width = padded_width; 904 me->info.raw_bit_depth = raw_bit_depth; 905 me->contiguous = contiguous; 906 me->valid = valid; 907 me->data_bytes = 0; 908 me->data = mmgr_NULL; 909 /* To indicate it is not valid frame. */ 910 me->dynamic_queue_id = (int)SH_CSS_INVALID_QUEUE_ID; 911 me->buf_type = IA_CSS_BUFFER_TYPE_INVALID; 912 913 return me; 914 } 915 916 static unsigned 917 ia_css_elems_bytes_from_info(const struct ia_css_frame_info *info) 918 { 919 if (info->format == IA_CSS_FRAME_FORMAT_RGB565) 920 return 2; /* bytes per pixel */ 921 if (info->format == IA_CSS_FRAME_FORMAT_YUV420_16) 922 return 2; /* bytes per pixel */ 923 if (info->format == IA_CSS_FRAME_FORMAT_YUV422_16) 924 return 2; /* bytes per pixel */ 925 /* Note: Essentially NV12_16 is a 2 bytes per pixel format, this return value is used 926 * to configure DMA for the output buffer, 927 * At least in SKC this data is overwritten by isp_output_init.sp.c except for elements(elems), 928 * which is configured from this return value, 929 * NV12_16 is implemented by a double buffer of 8 bit elements hence elems should be configured as 8 */ 930 if (info->format == IA_CSS_FRAME_FORMAT_NV12_16) 931 return 1; /* bytes per pixel */ 932 933 if (info->format == IA_CSS_FRAME_FORMAT_RAW 934 || (info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)) { 935 if (info->raw_bit_depth) 936 return CEIL_DIV(info->raw_bit_depth, 8); 937 else 938 return 2; /* bytes per pixel */ 939 } 940 if (info->format == IA_CSS_FRAME_FORMAT_PLANAR_RGB888) 941 return 3; /* bytes per pixel */ 942 if (info->format == IA_CSS_FRAME_FORMAT_RGBA888) 943 return 4; /* bytes per pixel */ 944 if (info->format == IA_CSS_FRAME_FORMAT_QPLANE6) 945 return 2; /* bytes per pixel */ 946 return 1; /* Default is 1 byte per pixel */ 947 } 948 949 void ia_css_frame_info_to_frame_sp_info( 950 struct ia_css_frame_sp_info *to, 951 const struct ia_css_frame_info *from) 952 { 953 ia_css_resolution_to_sp_resolution(&to->res, &from->res); 954 to->padded_width = (uint16_t)from->padded_width; 955 to->format = (uint8_t)from->format; 956 to->raw_bit_depth = (uint8_t)from->raw_bit_depth; 957 to->raw_bayer_order = from->raw_bayer_order; 958 } 959 960 void ia_css_resolution_to_sp_resolution( 961 struct ia_css_sp_resolution *to, 962 const struct ia_css_resolution *from) 963 { 964 to->width = (uint16_t)from->width; 965 to->height = (uint16_t)from->height; 966 } 967 968 #ifdef ISP2401 969 970 enum ia_css_err 971 ia_css_frame_find_crop_resolution(const struct ia_css_resolution *in_res, 972 const struct ia_css_resolution *out_res, 973 struct ia_css_resolution *crop_res) { 974 u32 wd_even_ceil, ht_even_ceil; 975 u32 in_ratio, out_ratio; 976 977 if ((!in_res) || (!out_res) || (!crop_res)) 978 return IA_CSS_ERR_INVALID_ARGUMENTS; 979 980 IA_CSS_ENTER_PRIVATE("in(%ux%u) -> out(%ux%u)", in_res->width, 981 in_res->height, out_res->width, out_res->height); 982 983 if ((in_res->width == 0) 984 || (in_res->height == 0) 985 || (out_res->width == 0) 986 || (out_res->height == 0)) 987 return IA_CSS_ERR_INVALID_ARGUMENTS; 988 989 if ((out_res->width > in_res->width) || 990 (out_res->height > in_res->height)) 991 return IA_CSS_ERR_INVALID_ARGUMENTS; 992 993 /* If aspect ratio (width/height) of out_res is higher than the aspect 994 * ratio of the in_res, then we crop vertically, otherwise we crop 995 * horizontally. 996 */ 997 in_ratio = in_res->width * out_res->height; 998 out_ratio = out_res->width * in_res->height; 999 1000 if (in_ratio == out_ratio) 1001 { 1002 crop_res->width = in_res->width; 1003 crop_res->height = in_res->height; 1004 } else if (out_ratio > in_ratio) 1005 { 1006 crop_res->width = in_res->width; 1007 crop_res->height = ROUND_DIV(out_res->height * crop_res->width, 1008 out_res->width); 1009 } else 1010 { 1011 crop_res->height = in_res->height; 1012 crop_res->width = ROUND_DIV(out_res->width * crop_res->height, 1013 out_res->height); 1014 } 1015 1016 /* Round new (cropped) width and height to an even number. 1017 * binarydesc_calculate_bds_factor is such that we should consider as 1018 * much of the input as possible. This is different only when we end up 1019 * with an odd number in the last step. So, we take the next even number 1020 * if it falls within the input, otherwise take the previous even no. 1021 */ 1022 wd_even_ceil = EVEN_CEIL(crop_res->width); 1023 ht_even_ceil = EVEN_CEIL(crop_res->height); 1024 if ((wd_even_ceil > in_res->width) || (ht_even_ceil > in_res->height)) 1025 { 1026 crop_res->width = EVEN_FLOOR(crop_res->width); 1027 crop_res->height = EVEN_FLOOR(crop_res->height); 1028 } else 1029 { 1030 crop_res->width = wd_even_ceil; 1031 crop_res->height = ht_even_ceil; 1032 } 1033 1034 IA_CSS_LEAVE_PRIVATE("in(%ux%u) -> out(%ux%u)", crop_res->width, 1035 crop_res->height, out_res->width, out_res->height); 1036 return IA_CSS_SUCCESS; 1037 } 1038 #endif 1039