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