]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/inputfifo/src/inputfifo.c
Merge tag 'sound-4.15-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / runtime / inputfifo / src / inputfifo.c
1 #ifndef ISP2401
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 #else
16 /*
17 Support for Intel Camera Imaging ISP subsystem.
18 Copyright (c) 2010 - 2015, Intel Corporation.
19
20 This program is free software; you can redistribute it and/or modify it
21 under the terms and conditions of the GNU General Public License,
22 version 2, as published by the Free Software Foundation.
23
24 This program is distributed in the hope it will be useful, but WITHOUT
25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
27 more details.
28 */
29 #endif
30
31 #include "platform_support.h"
32
33 #include "ia_css_inputfifo.h"
34
35 #include "device_access.h"
36
37 #define __INLINE_SP__
38 #include "sp.h"
39 #define __INLINE_ISP__
40 #include "isp.h"
41 #define __INLINE_IRQ__
42 #include "irq.h"
43 #define __INLINE_FIFO_MONITOR__
44 #include "fifo_monitor.h"
45
46 #define __INLINE_EVENT__
47 #include "event_fifo.h"
48 #define __INLINE_SP__
49
50 #if !defined(HAS_NO_INPUT_SYSTEM)
51 #include "input_system.h" /* MIPI_PREDICTOR_NONE,... */
52 #endif
53
54 #include "assert_support.h"
55
56 /* System independent */
57 #include "sh_css_internal.h"
58 #if !defined(HAS_NO_INPUT_SYSTEM)
59 #include "ia_css_isys.h"
60 #endif
61
62 #define HBLANK_CYCLES (187)
63 #define MARKER_CYCLES (6)
64
65 #if !defined(HAS_NO_INPUT_SYSTEM)
66 #include <hive_isp_css_streaming_to_mipi_types_hrt.h>
67 #endif
68
69 /* The data type is used to send special cases:
70 * yuv420: odd lines (1, 3 etc) are twice as wide as even
71 * lines (0, 2, 4 etc).
72 * rgb: for two pixels per clock, the R and B values are sent
73 * to output_0 while only G is sent to output_1. This means
74 * that output_1 only gets half the number of values of output_0.
75 * WARNING: This type should also be used for Legacy YUV420.
76 * regular: used for all other data types (RAW, YUV422, etc)
77 */
78 enum inputfifo_mipi_data_type {
79 inputfifo_mipi_data_type_regular,
80 inputfifo_mipi_data_type_yuv420,
81 inputfifo_mipi_data_type_yuv420_legacy,
82 inputfifo_mipi_data_type_rgb,
83 };
84 #if !defined(HAS_NO_INPUT_SYSTEM)
85 static unsigned int inputfifo_curr_ch_id, inputfifo_curr_fmt_type;
86 #endif
87 struct inputfifo_instance {
88 unsigned int ch_id;
89 enum ia_css_stream_format input_format;
90 bool two_ppc;
91 bool streaming;
92 unsigned int hblank_cycles;
93 unsigned int marker_cycles;
94 unsigned int fmt_type;
95 enum inputfifo_mipi_data_type type;
96 };
97 #if !defined(HAS_NO_INPUT_SYSTEM)
98 /*
99 * Maintain a basic streaming to Mipi administration with ch_id as index
100 * ch_id maps on the "Mipi virtual channel ID" and can have value 0..3
101 */
102 #define INPUTFIFO_NR_OF_S2M_CHANNELS (4)
103 static struct inputfifo_instance
104 inputfifo_inst_admin[INPUTFIFO_NR_OF_S2M_CHANNELS];
105
106 /* Streaming to MIPI */
107 static unsigned inputfifo_wrap_marker(
108 /* static inline unsigned inputfifo_wrap_marker( */
109 unsigned marker)
110 {
111 return marker |
112 (inputfifo_curr_ch_id << HIVE_STR_TO_MIPI_CH_ID_LSB) |
113 (inputfifo_curr_fmt_type << _HIVE_STR_TO_MIPI_FMT_TYPE_LSB);
114 }
115
116 static inline void
117 _sh_css_fifo_snd(unsigned token)
118 {
119 while (!can_event_send_token(STR2MIPI_EVENT_ID))
120 hrt_sleep();
121 event_send_token(STR2MIPI_EVENT_ID, token);
122 return;
123 }
124
125 static void inputfifo_send_data_a(
126 /* static inline void inputfifo_send_data_a( */
127 unsigned int data)
128 {
129 unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
130 (data << HIVE_STR_TO_MIPI_DATA_A_LSB);
131 _sh_css_fifo_snd(token);
132 return;
133 }
134
135
136
137 static void inputfifo_send_data_b(
138 /* static inline void inputfifo_send_data_b( */
139 unsigned int data)
140 {
141 unsigned int token = (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
142 (data << _HIVE_STR_TO_MIPI_DATA_B_LSB);
143 _sh_css_fifo_snd(token);
144 return;
145 }
146
147
148
149 static void inputfifo_send_data(
150 /* static inline void inputfifo_send_data( */
151 unsigned int a,
152 unsigned int b)
153 {
154 unsigned int token = ((1 << HIVE_STR_TO_MIPI_VALID_A_BIT) |
155 (1 << HIVE_STR_TO_MIPI_VALID_B_BIT) |
156 (a << HIVE_STR_TO_MIPI_DATA_A_LSB) |
157 (b << _HIVE_STR_TO_MIPI_DATA_B_LSB));
158 _sh_css_fifo_snd(token);
159 return;
160 }
161
162
163
164 static void inputfifo_send_sol(void)
165 /* static inline void inputfifo_send_sol(void) */
166 {
167 hrt_data token = inputfifo_wrap_marker(
168 1 << HIVE_STR_TO_MIPI_SOL_BIT);
169
170 _sh_css_fifo_snd(token);
171 return;
172 }
173
174
175
176 static void inputfifo_send_eol(void)
177 /* static inline void inputfifo_send_eol(void) */
178 {
179 hrt_data token = inputfifo_wrap_marker(
180 1 << HIVE_STR_TO_MIPI_EOL_BIT);
181 _sh_css_fifo_snd(token);
182 return;
183 }
184
185
186
187 static void inputfifo_send_sof(void)
188 /* static inline void inputfifo_send_sof(void) */
189 {
190 hrt_data token = inputfifo_wrap_marker(
191 1 << HIVE_STR_TO_MIPI_SOF_BIT);
192
193 _sh_css_fifo_snd(token);
194 return;
195 }
196
197
198
199 static void inputfifo_send_eof(void)
200 /* static inline void inputfifo_send_eof(void) */
201 {
202 hrt_data token = inputfifo_wrap_marker(
203 1 << HIVE_STR_TO_MIPI_EOF_BIT);
204 _sh_css_fifo_snd(token);
205 return;
206 }
207
208
209
210 #ifdef __ON__
211 static void inputfifo_send_ch_id(
212 /* static inline void inputfifo_send_ch_id( */
213 unsigned int ch_id)
214 {
215 hrt_data token;
216 inputfifo_curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
217 /* we send an zero marker, this will wrap the ch_id and
218 * fmt_type automatically.
219 */
220 token = inputfifo_wrap_marker(0);
221 _sh_css_fifo_snd(token);
222 return;
223 }
224
225 static void inputfifo_send_fmt_type(
226 /* static inline void inputfifo_send_fmt_type( */
227 unsigned int fmt_type)
228 {
229 hrt_data token;
230 inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
231 /* we send an zero marker, this will wrap the ch_id and
232 * fmt_type automatically.
233 */
234 token = inputfifo_wrap_marker(0);
235 _sh_css_fifo_snd(token);
236 return;
237 }
238 #endif /* __ON__ */
239
240
241
242 static void inputfifo_send_ch_id_and_fmt_type(
243 /* static inline
244 void inputfifo_send_ch_id_and_fmt_type( */
245 unsigned int ch_id,
246 unsigned int fmt_type)
247 {
248 hrt_data token;
249 inputfifo_curr_ch_id = ch_id & _HIVE_ISP_CH_ID_MASK;
250 inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
251 /* we send an zero marker, this will wrap the ch_id and
252 * fmt_type automatically.
253 */
254 token = inputfifo_wrap_marker(0);
255 _sh_css_fifo_snd(token);
256 return;
257 }
258
259
260
261 static void inputfifo_send_empty_token(void)
262 /* static inline void inputfifo_send_empty_token(void) */
263 {
264 hrt_data token = inputfifo_wrap_marker(0);
265 _sh_css_fifo_snd(token);
266 return;
267 }
268
269
270
271 static void inputfifo_start_frame(
272 /* static inline void inputfifo_start_frame( */
273 unsigned int ch_id,
274 unsigned int fmt_type)
275 {
276 inputfifo_send_ch_id_and_fmt_type(ch_id, fmt_type);
277 inputfifo_send_sof();
278 return;
279 }
280
281
282
283 static void inputfifo_end_frame(
284 unsigned int marker_cycles)
285 {
286 unsigned int i;
287 for (i = 0; i < marker_cycles; i++)
288 inputfifo_send_empty_token();
289 inputfifo_send_eof();
290 return;
291 }
292
293
294
295 static void inputfifo_send_line2(
296 const unsigned short *data,
297 unsigned int width,
298 const unsigned short *data2,
299 unsigned int width2,
300 unsigned int hblank_cycles,
301 unsigned int marker_cycles,
302 unsigned int two_ppc,
303 enum inputfifo_mipi_data_type type)
304 {
305 unsigned int i, is_rgb = 0, is_legacy = 0;
306
307 assert(data != NULL);
308 assert((data2 != NULL) || (width2 == 0));
309 if (type == inputfifo_mipi_data_type_rgb)
310 is_rgb = 1;
311
312 if (type == inputfifo_mipi_data_type_yuv420_legacy)
313 is_legacy = 1;
314
315 for (i = 0; i < hblank_cycles; i++)
316 inputfifo_send_empty_token();
317 inputfifo_send_sol();
318 for (i = 0; i < marker_cycles; i++)
319 inputfifo_send_empty_token();
320 for (i = 0; i < width; i++, data++) {
321 /* for RGB in two_ppc, we only actually send 2 pixels per
322 * clock in the even pixels (0, 2 etc). In the other cycles,
323 * we only send 1 pixel, to data[0].
324 */
325 unsigned int send_two_pixels = two_ppc;
326 if ((is_rgb || is_legacy) && (i % 3 == 2))
327 send_two_pixels = 0;
328 if (send_two_pixels) {
329 if (i + 1 == width) {
330 /* for jpg (binary) copy, this can occur
331 * if the file contains an odd number of bytes.
332 */
333 inputfifo_send_data(
334 data[0], 0);
335 } else {
336 inputfifo_send_data(
337 data[0], data[1]);
338 }
339 /* Additional increment because we send 2 pixels */
340 data++;
341 i++;
342 } else if (two_ppc && is_legacy) {
343 inputfifo_send_data_b(data[0]);
344 } else {
345 inputfifo_send_data_a(data[0]);
346 }
347 }
348
349 for (i = 0; i < width2; i++, data2++) {
350 /* for RGB in two_ppc, we only actually send 2 pixels per
351 * clock in the even pixels (0, 2 etc). In the other cycles,
352 * we only send 1 pixel, to data2[0].
353 */
354 unsigned int send_two_pixels = two_ppc;
355 if ((is_rgb || is_legacy) && (i % 3 == 2))
356 send_two_pixels = 0;
357 if (send_two_pixels) {
358 if (i + 1 == width2) {
359 /* for jpg (binary) copy, this can occur
360 * if the file contains an odd number of bytes.
361 */
362 inputfifo_send_data(
363 data2[0], 0);
364 } else {
365 inputfifo_send_data(
366 data2[0], data2[1]);
367 }
368 /* Additional increment because we send 2 pixels */
369 data2++;
370 i++;
371 } else if (two_ppc && is_legacy) {
372 inputfifo_send_data_b(data2[0]);
373 } else {
374 inputfifo_send_data_a(data2[0]);
375 }
376 }
377 for (i = 0; i < hblank_cycles; i++)
378 inputfifo_send_empty_token();
379 inputfifo_send_eol();
380 return;
381 }
382
383
384
385 static void
386 inputfifo_send_line(const unsigned short *data,
387 unsigned int width,
388 unsigned int hblank_cycles,
389 unsigned int marker_cycles,
390 unsigned int two_ppc,
391 enum inputfifo_mipi_data_type type)
392 {
393 assert(data != NULL);
394 inputfifo_send_line2(data, width, NULL, 0,
395 hblank_cycles,
396 marker_cycles,
397 two_ppc,
398 type);
399 }
400
401
402 /* Send a frame of data into the input network via the GP FIFO.
403 * Parameters:
404 * - data: array of 16 bit values that contains all data for the frame.
405 * - width: width of a line in number of subpixels, for yuv420 it is the
406 * number of Y components per line.
407 * - height: height of the frame in number of lines.
408 * - ch_id: channel ID.
409 * - fmt_type: format type.
410 * - hblank_cycles: length of horizontal blanking in cycles.
411 * - marker_cycles: number of empty cycles after start-of-line and before
412 * end-of-frame.
413 * - two_ppc: boolean, describes whether to send one or two pixels per clock
414 * cycle. In this mode, we sent pixels N and N+1 in the same cycle,
415 * to IF_PRIM_A and IF_PRIM_B respectively. The caller must make
416 * sure the input data has been formatted correctly for this.
417 * For example, for RGB formats this means that unused values
418 * must be inserted.
419 * - yuv420: boolean, describes whether (non-legacy) yuv420 data is used. In
420 * this mode, the odd lines (1,3,5 etc) are half as long as the
421 * even lines (2,4,6 etc).
422 * Note that the first line is odd (1) and the second line is even
423 * (2).
424 *
425 * This function does not do any reordering of pixels, the caller must make
426 * sure the data is in the righ format. Please refer to the CSS receiver
427 * documentation for details on the data formats.
428 */
429
430 static void inputfifo_send_frame(
431 const unsigned short *data,
432 unsigned int width,
433 unsigned int height,
434 unsigned int ch_id,
435 unsigned int fmt_type,
436 unsigned int hblank_cycles,
437 unsigned int marker_cycles,
438 unsigned int two_ppc,
439 enum inputfifo_mipi_data_type type)
440 {
441 unsigned int i;
442
443 assert(data != NULL);
444 inputfifo_start_frame(ch_id, fmt_type);
445
446 for (i = 0; i < height; i++) {
447 if ((type == inputfifo_mipi_data_type_yuv420) &&
448 (i & 1) == 1) {
449 inputfifo_send_line(data, 2 * width,
450 hblank_cycles,
451 marker_cycles,
452 two_ppc, type);
453 data += 2 * width;
454 } else {
455 inputfifo_send_line(data, width,
456 hblank_cycles,
457 marker_cycles,
458 two_ppc, type);
459 data += width;
460 }
461 }
462 inputfifo_end_frame(marker_cycles);
463 return;
464 }
465
466
467
468 static enum inputfifo_mipi_data_type inputfifo_determine_type(
469 enum ia_css_stream_format input_format)
470 {
471 enum inputfifo_mipi_data_type type;
472
473 type = inputfifo_mipi_data_type_regular;
474 if (input_format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) {
475 type =
476 inputfifo_mipi_data_type_yuv420_legacy;
477 } else if (input_format == IA_CSS_STREAM_FORMAT_YUV420_8 ||
478 input_format == IA_CSS_STREAM_FORMAT_YUV420_10 ||
479 input_format == IA_CSS_STREAM_FORMAT_YUV420_16) {
480 type =
481 inputfifo_mipi_data_type_yuv420;
482 } else if (input_format >= IA_CSS_STREAM_FORMAT_RGB_444 &&
483 input_format <= IA_CSS_STREAM_FORMAT_RGB_888) {
484 type =
485 inputfifo_mipi_data_type_rgb;
486 }
487 return type;
488 }
489
490
491
492 static struct inputfifo_instance *inputfifo_get_inst(
493 unsigned int ch_id)
494 {
495 return &inputfifo_inst_admin[ch_id];
496 }
497
498 void ia_css_inputfifo_send_input_frame(
499 const unsigned short *data,
500 unsigned int width,
501 unsigned int height,
502 unsigned int ch_id,
503 enum ia_css_stream_format input_format,
504 bool two_ppc)
505 {
506 unsigned int fmt_type, hblank_cycles, marker_cycles;
507 enum inputfifo_mipi_data_type type;
508
509 assert(data != NULL);
510 hblank_cycles = HBLANK_CYCLES;
511 marker_cycles = MARKER_CYCLES;
512 ia_css_isys_convert_stream_format_to_mipi_format(input_format,
513 MIPI_PREDICTOR_NONE,
514 &fmt_type);
515
516 type = inputfifo_determine_type(input_format);
517
518 inputfifo_send_frame(data, width, height,
519 ch_id, fmt_type, hblank_cycles, marker_cycles,
520 two_ppc, type);
521 }
522
523
524
525 void ia_css_inputfifo_start_frame(
526 unsigned int ch_id,
527 enum ia_css_stream_format input_format,
528 bool two_ppc)
529 {
530 struct inputfifo_instance *s2mi;
531 s2mi = inputfifo_get_inst(ch_id);
532
533 s2mi->ch_id = ch_id;
534 ia_css_isys_convert_stream_format_to_mipi_format(input_format,
535 MIPI_PREDICTOR_NONE,
536 &s2mi->fmt_type);
537 s2mi->two_ppc = two_ppc;
538 s2mi->type = inputfifo_determine_type(input_format);
539 s2mi->hblank_cycles = HBLANK_CYCLES;
540 s2mi->marker_cycles = MARKER_CYCLES;
541 s2mi->streaming = true;
542
543 inputfifo_start_frame(ch_id, s2mi->fmt_type);
544 return;
545 }
546
547
548
549 void ia_css_inputfifo_send_line(
550 unsigned int ch_id,
551 const unsigned short *data,
552 unsigned int width,
553 const unsigned short *data2,
554 unsigned int width2)
555 {
556 struct inputfifo_instance *s2mi;
557
558 assert(data != NULL);
559 assert((data2 != NULL) || (width2 == 0));
560 s2mi = inputfifo_get_inst(ch_id);
561
562
563 /* Set global variables that indicate channel_id and format_type */
564 inputfifo_curr_ch_id = (s2mi->ch_id) & _HIVE_ISP_CH_ID_MASK;
565 inputfifo_curr_fmt_type = (s2mi->fmt_type) & _HIVE_ISP_FMT_TYPE_MASK;
566
567 inputfifo_send_line2(data, width, data2, width2,
568 s2mi->hblank_cycles,
569 s2mi->marker_cycles,
570 s2mi->two_ppc,
571 s2mi->type);
572 }
573
574
575 void ia_css_inputfifo_send_embedded_line(
576 unsigned int ch_id,
577 enum ia_css_stream_format data_type,
578 const unsigned short *data,
579 unsigned int width)
580 {
581 struct inputfifo_instance *s2mi;
582 unsigned int fmt_type;
583
584 assert(data != NULL);
585 s2mi = inputfifo_get_inst(ch_id);
586 ia_css_isys_convert_stream_format_to_mipi_format(data_type,
587 MIPI_PREDICTOR_NONE, &fmt_type);
588
589 /* Set format_type for metadata line. */
590 inputfifo_curr_fmt_type = fmt_type & _HIVE_ISP_FMT_TYPE_MASK;
591
592 inputfifo_send_line(data, width, s2mi->hblank_cycles, s2mi->marker_cycles,
593 s2mi->two_ppc, inputfifo_mipi_data_type_regular);
594 }
595
596
597 void ia_css_inputfifo_end_frame(
598 unsigned int ch_id)
599 {
600 struct inputfifo_instance *s2mi;
601 s2mi = inputfifo_get_inst(ch_id);
602
603 /* Set global variables that indicate channel_id and format_type */
604 inputfifo_curr_ch_id = (s2mi->ch_id) & _HIVE_ISP_CH_ID_MASK;
605 inputfifo_curr_fmt_type = (s2mi->fmt_type) & _HIVE_ISP_FMT_TYPE_MASK;
606
607 /* Call existing HRT function */
608 inputfifo_end_frame(s2mi->marker_cycles);
609
610 s2mi->streaming = false;
611 return;
612 }
613 #endif /* #if !defined(HAS_NO_INPUT_SYSTEM) */