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