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