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