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