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