1
2
3
4
5
6
7
8
9
10
11
12
13
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
31
32static 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
38static 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
44static 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
51static 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
57static 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
62static 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
68static void frame_init_rgb_planes(struct ia_css_frame *frame,
69 unsigned int bytes_per_element);
70
71static void frame_init_qplane6_planes(struct ia_css_frame *frame);
72
73static int frame_allocate_buffer_data(struct ia_css_frame *frame);
74
75static 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
83static 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
91static unsigned
92ia_css_elems_bytes_from_info(
93 const struct ia_css_frame_info *info);
94
95
96
97
98
99void ia_css_frame_zero(struct ia_css_frame *frame)
100{
101 assert(frame);
102 hmm_set(frame->data, 0, frame->data_bytes);
103}
104
105int 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
123int 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
154int 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
166 err = ia_css_frame_create_from_info(&me, info);
167
168 if (err)
169 return err;
170
171 if (!err) {
172 if (pgnr < ((PAGE_ALIGN(me->data_bytes)) >> PAGE_SHIFT)) {
173 dev_err(atomisp_dev,
174 "user space memory size is less than the expected size..\n");
175 err = -ENOMEM;
176 goto error;
177 } else if (pgnr > ((PAGE_ALIGN(me->data_bytes)) >> PAGE_SHIFT)) {
178 dev_err(atomisp_dev,
179 "user space memory size is large than the expected size..\n");
180 err = -ENOMEM;
181 goto error;
182 }
183
184 me->data = hmm_alloc(me->data_bytes, HMM_BO_USER, 0, data,
185 attribute & ATOMISP_MAP_FLAG_CACHED);
186
187 if (me->data == mmgr_NULL)
188 err = -EINVAL;
189 }
190
191error:
192 if (err) {
193 kvfree(me);
194 me = NULL;
195 }
196
197 *frame = me;
198
199 return err;
200}
201
202int ia_css_frame_create_from_info(struct ia_css_frame **frame,
203 const struct ia_css_frame_info *info)
204{
205 int err = 0;
206 struct ia_css_frame *me;
207
208 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
209 "ia_css_frame_create_from_info() enter:\n");
210 if (!frame || !info) {
211 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
212 "ia_css_frame_create_from_info() leave: invalid arguments\n");
213 return -EINVAL;
214 }
215
216 me = frame_create(info->res.width,
217 info->res.height,
218 info->format,
219 info->padded_width,
220 info->raw_bit_depth,
221 false,
222 false);
223 if (!me) {
224 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
225 "ia_css_frame_create_from_info() leave: frame create failed\n");
226 return -ENOMEM;
227 }
228
229 err = ia_css_frame_init_planes(me);
230
231 if (err) {
232 kvfree(me);
233 me = NULL;
234 }
235
236 *frame = me;
237
238 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
239 "ia_css_frame_create_from_info() leave:\n");
240
241 return err;
242}
243
244int ia_css_frame_set_data(struct ia_css_frame *frame,
245 const ia_css_ptr mapped_data,
246 size_t data_bytes)
247{
248 int err = 0;
249
250 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
251 "ia_css_frame_set_data() enter:\n");
252 if (!frame) {
253 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
254 "ia_css_frame_set_data() leave: NULL frame\n");
255 return -EINVAL;
256 }
257
258
259
260
261
262 if ((mapped_data != mmgr_NULL) && (frame->data_bytes > data_bytes)) {
263 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
264 "ia_css_frame_set_data() leave: invalid arguments\n");
265 return -EINVAL;
266 }
267
268 frame->data = mapped_data;
269
270 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_set_data() leave:\n");
271
272 return err;
273}
274
275int ia_css_frame_allocate_contiguous(struct ia_css_frame **frame,
276 unsigned int width,
277 unsigned int height,
278 enum ia_css_frame_format format,
279 unsigned int padded_width,
280 unsigned int raw_bit_depth)
281{
282 int err = 0;
283
284 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
285 "ia_css_frame_allocate_contiguous() enter: width=%d, height=%d, format=%d, padded_width=%d, raw_bit_depth=%d\n",
286 width, height, format, padded_width, raw_bit_depth);
287
288 err = frame_allocate_with_data(frame, width, height, format,
289 padded_width, raw_bit_depth, true);
290
291 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
292 "ia_css_frame_allocate_contiguous() leave: frame=%p\n",
293 frame ? *frame : (void *)-1);
294
295 return err;
296}
297
298int ia_css_frame_allocate_contiguous_from_info(
299 struct ia_css_frame **frame,
300 const struct ia_css_frame_info *info)
301{
302 int err = 0;
303
304 assert(frame);
305 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
306 "ia_css_frame_allocate_contiguous_from_info() enter:\n");
307 err = ia_css_frame_allocate_contiguous(frame,
308 info->res.width,
309 info->res.height,
310 info->format,
311 info->padded_width,
312 info->raw_bit_depth);
313 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
314 "ia_css_frame_allocate_contiguous_from_info() leave:\n");
315 return err;
316}
317
318void ia_css_frame_free(struct ia_css_frame *frame)
319{
320 IA_CSS_ENTER_PRIVATE("frame = %p", frame);
321
322 if (frame) {
323 hmm_free(frame->data);
324 kvfree(frame);
325 }
326
327 IA_CSS_LEAVE_PRIVATE("void");
328}
329
330
331
332
333
334int ia_css_frame_check_info(const struct ia_css_frame_info *info)
335{
336 assert(info);
337 if (info->res.width == 0 || info->res.height == 0)
338 return -EINVAL;
339 return 0;
340}
341
342int ia_css_frame_init_planes(struct ia_css_frame *frame)
343{
344 assert(frame);
345
346 switch (frame->info.format) {
347 case IA_CSS_FRAME_FORMAT_MIPI:
348 frame_init_mipi_plane(frame, &frame->planes.raw,
349 frame->info.res.height,
350 frame->info.padded_width,
351 frame->info.raw_bit_depth <= 8 ? 1 : 2);
352 break;
353 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
354 frame_init_raw_single_plane(frame, &frame->planes.raw,
355 frame->info.res.height,
356 frame->info.padded_width,
357 frame->info.raw_bit_depth);
358 break;
359 case IA_CSS_FRAME_FORMAT_RAW:
360 frame_init_single_plane(frame, &frame->planes.raw,
361 frame->info.res.height,
362 frame->info.padded_width,
363 frame->info.raw_bit_depth <= 8 ? 1 : 2);
364 break;
365 case IA_CSS_FRAME_FORMAT_RGB565:
366 frame_init_single_plane(frame, &frame->planes.rgb,
367 frame->info.res.height,
368 frame->info.padded_width, 2);
369 break;
370 case IA_CSS_FRAME_FORMAT_RGBA888:
371 frame_init_single_plane(frame, &frame->planes.rgb,
372 frame->info.res.height,
373 frame->info.padded_width * 4, 1);
374 break;
375 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
376 frame_init_rgb_planes(frame, 1);
377 break;
378
379
380
381 case IA_CSS_FRAME_FORMAT_YUYV:
382 case IA_CSS_FRAME_FORMAT_UYVY:
383 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
384 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
385 frame_init_single_plane(frame, &frame->planes.yuyv,
386 frame->info.res.height,
387 frame->info.padded_width * 2, 1);
388 break;
389 case IA_CSS_FRAME_FORMAT_YUV_LINE:
390
391 frame_init_single_plane(frame, &frame->planes.yuyv,
392 frame->info.res.height * 3 / 2 + 3,
393 frame->info.padded_width, 1);
394 break;
395 case IA_CSS_FRAME_FORMAT_NV11:
396 frame_init_nv_planes(frame, 4, 1, 1);
397 break;
398
399
400
401 case IA_CSS_FRAME_FORMAT_NV12:
402 case IA_CSS_FRAME_FORMAT_NV21:
403 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
404 frame_init_nv_planes(frame, 2, 2, 1);
405 break;
406 case IA_CSS_FRAME_FORMAT_NV12_16:
407 frame_init_nv_planes(frame, 2, 2, 2);
408 break;
409
410
411
412 case IA_CSS_FRAME_FORMAT_NV16:
413 case IA_CSS_FRAME_FORMAT_NV61:
414 frame_init_nv_planes(frame, 2, 1, 1);
415 break;
416 case IA_CSS_FRAME_FORMAT_YUV420:
417 frame_init_yuv_planes(frame, 2, 2, false, 1);
418 break;
419 case IA_CSS_FRAME_FORMAT_YUV422:
420 frame_init_yuv_planes(frame, 2, 1, false, 1);
421 break;
422 case IA_CSS_FRAME_FORMAT_YUV444:
423 frame_init_yuv_planes(frame, 1, 1, false, 1);
424 break;
425 case IA_CSS_FRAME_FORMAT_YUV420_16:
426 frame_init_yuv_planes(frame, 2, 2, false, 2);
427 break;
428 case IA_CSS_FRAME_FORMAT_YUV422_16:
429 frame_init_yuv_planes(frame, 2, 1, false, 2);
430 break;
431 case IA_CSS_FRAME_FORMAT_YV12:
432 frame_init_yuv_planes(frame, 2, 2, true, 1);
433 break;
434 case IA_CSS_FRAME_FORMAT_YV16:
435 frame_init_yuv_planes(frame, 2, 1, true, 1);
436 break;
437 case IA_CSS_FRAME_FORMAT_QPLANE6:
438 frame_init_qplane6_planes(frame);
439 break;
440 case IA_CSS_FRAME_FORMAT_BINARY_8:
441 frame_init_single_plane(frame, &frame->planes.binary.data,
442 frame->info.res.height,
443 frame->info.padded_width, 1);
444 frame->planes.binary.size = 0;
445 break;
446 default:
447 return -EINVAL;
448 }
449 return 0;
450}
451
452void ia_css_frame_info_set_width(struct ia_css_frame_info *info,
453 unsigned int width,
454 unsigned int min_padded_width)
455{
456 unsigned int align;
457
458 IA_CSS_ENTER_PRIVATE("info = %p,width = %d, minimum padded width = %d",
459 info, width, min_padded_width);
460 if (!info) {
461 IA_CSS_ERROR("NULL input parameter");
462 IA_CSS_LEAVE_PRIVATE("");
463 return;
464 }
465 if (min_padded_width > width)
466 align = min_padded_width;
467 else
468 align = width;
469
470 info->res.width = width;
471
472
473
474 if (info->format == IA_CSS_FRAME_FORMAT_YUV420 ||
475 info->format == IA_CSS_FRAME_FORMAT_YV12 ||
476 info->format == IA_CSS_FRAME_FORMAT_NV12 ||
477 info->format == IA_CSS_FRAME_FORMAT_NV21 ||
478 info->format == IA_CSS_FRAME_FORMAT_BINARY_8 ||
479 info->format == IA_CSS_FRAME_FORMAT_YUV_LINE)
480 info->padded_width =
481 CEIL_MUL(align, 2 * HIVE_ISP_DDR_WORD_BYTES);
482 else if (info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY)
483 info->padded_width = CEIL_MUL(align, NV12_TILEY_TILE_WIDTH);
484 else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
485 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
486 info->padded_width = CEIL_MUL(align, 2 * ISP_VEC_NELEMS);
487 else {
488 info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES);
489 }
490 IA_CSS_LEAVE_PRIVATE("");
491}
492
493void ia_css_frame_info_set_format(struct ia_css_frame_info *info,
494 enum ia_css_frame_format format)
495{
496 assert(info);
497 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
498 "ia_css_frame_info_set_format() enter:\n");
499 info->format = format;
500}
501
502void ia_css_frame_info_init(struct ia_css_frame_info *info,
503 unsigned int width,
504 unsigned int height,
505 enum ia_css_frame_format format,
506 unsigned int aligned)
507{
508 IA_CSS_ENTER_PRIVATE("info = %p, width = %d, height = %d, format = %d, aligned = %d",
509 info, width, height, format, aligned);
510 if (!info) {
511 IA_CSS_ERROR("NULL input parameter");
512 IA_CSS_LEAVE_PRIVATE("");
513 return;
514 }
515 info->res.height = height;
516 info->format = format;
517 ia_css_frame_info_set_width(info, width, aligned);
518 IA_CSS_LEAVE_PRIVATE("");
519}
520
521void ia_css_frame_free_multiple(unsigned int num_frames,
522 struct ia_css_frame **frames_array)
523{
524 unsigned int i;
525
526 for (i = 0; i < num_frames; i++) {
527 if (frames_array[i]) {
528 ia_css_frame_free(frames_array[i]);
529 frames_array[i] = NULL;
530 }
531 }
532}
533
534int ia_css_frame_allocate_with_buffer_size(
535 struct ia_css_frame **frame,
536 const unsigned int buffer_size_bytes,
537 const bool contiguous)
538{
539
540 int err;
541 struct ia_css_frame *me = frame_create(0, 0,
542 IA_CSS_FRAME_FORMAT_NUM,
543 0, 0, contiguous, false);
544
545 if (!me)
546 return -ENOMEM;
547
548
549 me->data_bytes = buffer_size_bytes;
550
551 err = frame_allocate_buffer_data(me);
552
553 if (err) {
554 kvfree(me);
555 me = NULL;
556 }
557
558 *frame = me;
559
560 return err;
561}
562
563bool ia_css_frame_info_is_same_resolution(
564 const struct ia_css_frame_info *info_a,
565 const struct ia_css_frame_info *info_b)
566{
567 if (!info_a || !info_b)
568 return false;
569 return (info_a->res.width == info_b->res.width) &&
570 (info_a->res.height == info_b->res.height);
571}
572
573bool ia_css_frame_is_same_type(const struct ia_css_frame *frame_a,
574 const struct ia_css_frame *frame_b)
575{
576 bool is_equal = false;
577 const struct ia_css_frame_info *info_a = &frame_a->info,
578 *info_b = &frame_b->info;
579
580 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
581 "ia_css_frame_is_same_type() enter:\n");
582
583 if (!info_a || !info_b)
584 return false;
585 if (info_a->format != info_b->format)
586 return false;
587 if (info_a->padded_width != info_b->padded_width)
588 return false;
589 is_equal = ia_css_frame_info_is_same_resolution(info_a, info_b);
590
591 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
592 "ia_css_frame_is_same_type() leave:\n");
593
594 return is_equal;
595}
596
597void
598ia_css_dma_configure_from_info(
599 struct dma_port_config *config,
600 const struct ia_css_frame_info *info)
601{
602 unsigned int is_raw_packed = info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED;
603 unsigned int bits_per_pixel = is_raw_packed ? info->raw_bit_depth :
604 ia_css_elems_bytes_from_info(info) * 8;
605 unsigned int pix_per_ddrword = HIVE_ISP_DDR_WORD_BITS / bits_per_pixel;
606 unsigned int words_per_line = CEIL_DIV(info->padded_width, pix_per_ddrword);
607 unsigned int elems_b = pix_per_ddrword;
608
609 config->stride = HIVE_ISP_DDR_WORD_BYTES * words_per_line;
610 config->elems = (uint8_t)elems_b;
611 config->width = (uint16_t)info->res.width;
612 config->crop = 0;
613 assert(config->width <= info->padded_width);
614}
615
616
617
618
619
620static void frame_init_plane(struct ia_css_frame_plane *plane,
621 unsigned int width,
622 unsigned int stride,
623 unsigned int height,
624 unsigned int offset)
625{
626 plane->height = height;
627 plane->width = width;
628 plane->stride = stride;
629 plane->offset = offset;
630}
631
632static void frame_init_single_plane(struct ia_css_frame *frame,
633 struct ia_css_frame_plane *plane,
634 unsigned int height,
635 unsigned int subpixels_per_line,
636 unsigned int bytes_per_pixel)
637{
638 unsigned int stride;
639
640 stride = subpixels_per_line * bytes_per_pixel;
641
642
643
644
645
646
647 frame->data_bytes = stride * CEIL_MUL2(height, 2);
648 frame_init_plane(plane, subpixels_per_line, stride, height, 0);
649 return;
650}
651
652static void frame_init_raw_single_plane(
653 struct ia_css_frame *frame,
654 struct ia_css_frame_plane *plane,
655 unsigned int height,
656 unsigned int subpixels_per_line,
657 unsigned int bits_per_pixel)
658{
659 unsigned int stride;
660
661 assert(frame);
662
663 stride = HIVE_ISP_DDR_WORD_BYTES *
664 CEIL_DIV(subpixels_per_line,
665 HIVE_ISP_DDR_WORD_BITS / bits_per_pixel);
666 frame->data_bytes = stride * height;
667 frame_init_plane(plane, subpixels_per_line, stride, height, 0);
668 return;
669}
670
671static void frame_init_mipi_plane(struct ia_css_frame *frame,
672 struct ia_css_frame_plane *plane,
673 unsigned int height,
674 unsigned int subpixels_per_line,
675 unsigned int bytes_per_pixel)
676{
677 unsigned int stride;
678
679 stride = subpixels_per_line * bytes_per_pixel;
680 frame->data_bytes = 8388608;
681 frame->valid = false;
682 frame->contiguous = true;
683 frame_init_plane(plane, subpixels_per_line, stride, height, 0);
684 return;
685}
686
687static void frame_init_nv_planes(struct ia_css_frame *frame,
688 unsigned int horizontal_decimation,
689 unsigned int vertical_decimation,
690 unsigned int bytes_per_element)
691{
692 unsigned int y_width = frame->info.padded_width;
693 unsigned int y_height = frame->info.res.height;
694 unsigned int uv_width;
695 unsigned int uv_height;
696 unsigned int y_bytes;
697 unsigned int uv_bytes;
698 unsigned int y_stride;
699 unsigned int uv_stride;
700
701 assert(horizontal_decimation != 0 && vertical_decimation != 0);
702
703 uv_width = 2 * (y_width / horizontal_decimation);
704 uv_height = y_height / vertical_decimation;
705
706 if (frame->info.format == IA_CSS_FRAME_FORMAT_NV12_TILEY) {
707 y_width = CEIL_MUL(y_width, NV12_TILEY_TILE_WIDTH);
708 uv_width = CEIL_MUL(uv_width, NV12_TILEY_TILE_WIDTH);
709 y_height = CEIL_MUL(y_height, NV12_TILEY_TILE_HEIGHT);
710 uv_height = CEIL_MUL(uv_height, NV12_TILEY_TILE_HEIGHT);
711 }
712
713 y_stride = y_width * bytes_per_element;
714 uv_stride = uv_width * bytes_per_element;
715 y_bytes = y_stride * y_height;
716 uv_bytes = uv_stride * uv_height;
717
718 frame->data_bytes = y_bytes + uv_bytes;
719 frame_init_plane(&frame->planes.nv.y, y_width, y_stride, y_height, 0);
720 frame_init_plane(&frame->planes.nv.uv, uv_width,
721 uv_stride, uv_height, y_bytes);
722 return;
723}
724
725static void frame_init_yuv_planes(struct ia_css_frame *frame,
726 unsigned int horizontal_decimation,
727 unsigned int vertical_decimation,
728 bool swap_uv,
729 unsigned int bytes_per_element)
730{
731 unsigned int y_width = frame->info.padded_width,
732 y_height = frame->info.res.height,
733 uv_width = y_width / horizontal_decimation,
734 uv_height = y_height / vertical_decimation,
735 y_stride, y_bytes, uv_bytes, uv_stride;
736
737 y_stride = y_width * bytes_per_element;
738 uv_stride = uv_width * bytes_per_element;
739 y_bytes = y_stride * y_height;
740 uv_bytes = uv_stride * uv_height;
741
742 frame->data_bytes = y_bytes + 2 * uv_bytes;
743 frame_init_plane(&frame->planes.yuv.y, y_width, y_stride, y_height, 0);
744 if (swap_uv) {
745 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
746 uv_height, y_bytes);
747 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
748 uv_height, y_bytes + uv_bytes);
749 } else {
750 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
751 uv_height, y_bytes);
752 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
753 uv_height, y_bytes + uv_bytes);
754 }
755 return;
756}
757
758static void frame_init_rgb_planes(struct ia_css_frame *frame,
759 unsigned int bytes_per_element)
760{
761 unsigned int width = frame->info.res.width,
762 height = frame->info.res.height, stride, bytes;
763
764 stride = width * bytes_per_element;
765 bytes = stride * height;
766 frame->data_bytes = 3 * bytes;
767 frame_init_plane(&frame->planes.planar_rgb.r, width, stride, height, 0);
768 frame_init_plane(&frame->planes.planar_rgb.g,
769 width, stride, height, 1 * bytes);
770 frame_init_plane(&frame->planes.planar_rgb.b,
771 width, stride, height, 2 * bytes);
772 return;
773}
774
775static void frame_init_qplane6_planes(struct ia_css_frame *frame)
776{
777 unsigned int width = frame->info.padded_width / 2,
778 height = frame->info.res.height / 2, bytes, stride;
779
780 stride = width * 2;
781 bytes = stride * height;
782
783 frame->data_bytes = 6 * bytes;
784 frame_init_plane(&frame->planes.plane6.r,
785 width, stride, height, 0 * bytes);
786 frame_init_plane(&frame->planes.plane6.r_at_b,
787 width, stride, height, 1 * bytes);
788 frame_init_plane(&frame->planes.plane6.gr,
789 width, stride, height, 2 * bytes);
790 frame_init_plane(&frame->planes.plane6.gb,
791 width, stride, height, 3 * bytes);
792 frame_init_plane(&frame->planes.plane6.b,
793 width, stride, height, 4 * bytes);
794 frame_init_plane(&frame->planes.plane6.b_at_r,
795 width, stride, height, 5 * bytes);
796 return;
797}
798
799static int frame_allocate_buffer_data(struct ia_css_frame *frame)
800{
801#ifdef ISP2401
802 IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes);
803#endif
804 frame->data = hmm_alloc(frame->data_bytes,
805 HMM_BO_PRIVATE, 0, NULL,
806 frame->contiguous ?
807 ATOMISP_MAP_FLAG_CONTIGUOUS : 0);
808
809 if (frame->data == mmgr_NULL)
810 return -ENOMEM;
811 return 0;
812}
813
814static int frame_allocate_with_data(struct ia_css_frame **frame,
815 unsigned int width,
816 unsigned int height,
817 enum ia_css_frame_format format,
818 unsigned int padded_width,
819 unsigned int raw_bit_depth,
820 bool contiguous)
821{
822 int err;
823 struct ia_css_frame *me = frame_create(width,
824 height,
825 format,
826 padded_width,
827 raw_bit_depth,
828 contiguous,
829 true);
830
831 if (!me)
832 return -ENOMEM;
833
834 err = ia_css_frame_init_planes(me);
835
836 if (!err)
837 err = frame_allocate_buffer_data(me);
838
839 if (err) {
840 kvfree(me);
841#ifndef ISP2401
842 return err;
843#else
844 me = NULL;
845#endif
846 }
847
848 *frame = me;
849
850 return err;
851}
852
853static struct ia_css_frame *frame_create(unsigned int width,
854 unsigned int height,
855 enum ia_css_frame_format format,
856 unsigned int padded_width,
857 unsigned int raw_bit_depth,
858 bool contiguous,
859 bool valid)
860{
861 struct ia_css_frame *me = kvmalloc(sizeof(*me), GFP_KERNEL);
862
863 if (!me)
864 return NULL;
865
866 memset(me, 0, sizeof(*me));
867 me->info.res.width = width;
868 me->info.res.height = height;
869 me->info.format = format;
870 me->info.padded_width = padded_width;
871 me->info.raw_bit_depth = raw_bit_depth;
872 me->contiguous = contiguous;
873 me->valid = valid;
874 me->data_bytes = 0;
875 me->data = mmgr_NULL;
876
877 me->dynamic_queue_id = (int)SH_CSS_INVALID_QUEUE_ID;
878 me->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
879
880 return me;
881}
882
883static unsigned
884ia_css_elems_bytes_from_info(const struct ia_css_frame_info *info)
885{
886 if (info->format == IA_CSS_FRAME_FORMAT_RGB565)
887 return 2;
888 if (info->format == IA_CSS_FRAME_FORMAT_YUV420_16)
889 return 2;
890 if (info->format == IA_CSS_FRAME_FORMAT_YUV422_16)
891 return 2;
892
893
894
895
896
897 if (info->format == IA_CSS_FRAME_FORMAT_NV12_16)
898 return 1;
899
900 if (info->format == IA_CSS_FRAME_FORMAT_RAW
901 || (info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)) {
902 if (info->raw_bit_depth)
903 return CEIL_DIV(info->raw_bit_depth, 8);
904 else
905 return 2;
906 }
907 if (info->format == IA_CSS_FRAME_FORMAT_PLANAR_RGB888)
908 return 3;
909 if (info->format == IA_CSS_FRAME_FORMAT_RGBA888)
910 return 4;
911 if (info->format == IA_CSS_FRAME_FORMAT_QPLANE6)
912 return 2;
913 return 1;
914}
915
916void ia_css_frame_info_to_frame_sp_info(
917 struct ia_css_frame_sp_info *to,
918 const struct ia_css_frame_info *from)
919{
920 ia_css_resolution_to_sp_resolution(&to->res, &from->res);
921 to->padded_width = (uint16_t)from->padded_width;
922 to->format = (uint8_t)from->format;
923 to->raw_bit_depth = (uint8_t)from->raw_bit_depth;
924 to->raw_bayer_order = from->raw_bayer_order;
925}
926
927void ia_css_resolution_to_sp_resolution(
928 struct ia_css_sp_resolution *to,
929 const struct ia_css_resolution *from)
930{
931 to->width = (uint16_t)from->width;
932 to->height = (uint16_t)from->height;
933}
934
935
936int
937ia_css_frame_find_crop_resolution(const struct ia_css_resolution *in_res,
938 const struct ia_css_resolution *out_res,
939 struct ia_css_resolution *crop_res) {
940 u32 wd_even_ceil, ht_even_ceil;
941 u32 in_ratio, out_ratio;
942
943 if ((!in_res) || (!out_res) || (!crop_res))
944 return -EINVAL;
945
946 IA_CSS_ENTER_PRIVATE("in(%ux%u) -> out(%ux%u)", in_res->width,
947 in_res->height, out_res->width, out_res->height);
948
949 if ((in_res->width == 0)
950 || (in_res->height == 0)
951 || (out_res->width == 0)
952 || (out_res->height == 0))
953 return -EINVAL;
954
955 if ((out_res->width > in_res->width) ||
956 (out_res->height > in_res->height))
957 return -EINVAL;
958
959
960
961
962
963 in_ratio = in_res->width * out_res->height;
964 out_ratio = out_res->width * in_res->height;
965
966 if (in_ratio == out_ratio)
967 {
968 crop_res->width = in_res->width;
969 crop_res->height = in_res->height;
970 } else if (out_ratio > in_ratio)
971 {
972 crop_res->width = in_res->width;
973 crop_res->height = ROUND_DIV(out_res->height * crop_res->width,
974 out_res->width);
975 } else
976 {
977 crop_res->height = in_res->height;
978 crop_res->width = ROUND_DIV(out_res->width * crop_res->height,
979 out_res->height);
980 }
981
982
983
984
985
986
987
988 wd_even_ceil = EVEN_CEIL(crop_res->width);
989 ht_even_ceil = EVEN_CEIL(crop_res->height);
990 if ((wd_even_ceil > in_res->width) || (ht_even_ceil > in_res->height))
991 {
992 crop_res->width = EVEN_FLOOR(crop_res->width);
993 crop_res->height = EVEN_FLOOR(crop_res->height);
994 } else
995 {
996 crop_res->width = wd_even_ceil;
997 crop_res->height = ht_even_ceil;
998 }
999
1000 IA_CSS_LEAVE_PRIVATE("in(%ux%u) -> out(%ux%u)", crop_res->width,
1001 crop_res->height, out_res->width, out_res->height);
1002 return 0;
1003}
1004