]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/staging/media/atomisp/pci/atomisp2/css2400/hive_isp_css_common/host/vmem.c
2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2010 - 2016, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 #include "vmem_local.h"
19 #if !defined(HRT_MEMORY_ACCESS)
20 #include "ia_css_device_access.h"
22 #include "assert_support.h"
23 #include "platform_support.h" /* hrt_sleep() */
25 typedef unsigned long long hive_uedge
;
26 typedef hive_uedge
*hive_wide
;
28 /* Copied from SDK: sim_semantics.c */
30 /* subword bits move like this: MSB[____xxxx____]LSB -> MSB[00000000xxxx]LSB */
31 #define SUBWORD(w, start, end) (((w) & (((1ULL << ((end)-1))-1) << 1 | 1)) >> (start))
33 /* inverse subword bits move like this: MSB[xxxx____xxxx]LSB -> MSB[xxxx0000xxxx]LSB */
34 #define INV_SUBWORD(w, start, end) ((w) & (~(((1ULL << ((end)-1))-1) << 1 | 1) | ((1ULL << (start))-1)) )
36 #define uedge_bits (8*sizeof(hive_uedge))
37 #define move_lower_bits(target, target_bit, src, src_bit) move_subword(target, target_bit, src, 0, src_bit)
38 #define move_upper_bits(target, target_bit, src, src_bit) move_subword(target, target_bit, src, src_bit, uedge_bits)
39 #define move_word(target, target_bit, src) move_subword(target, target_bit, src, 0, uedge_bits)
49 unsigned int start_elem
= target_bit
/ uedge_bits
;
50 unsigned int start_bit
= target_bit
% uedge_bits
;
51 unsigned subword_width
= src_end
- src_start
;
53 hive_uedge src_subword
= SUBWORD(src
, src_start
, src_end
);
55 if (subword_width
+ start_bit
> uedge_bits
) { /* overlap */
57 hive_uedge old_val0
= INV_SUBWORD(target
[start_elem
], start_bit
, uedge_bits
);
58 target
[start_elem
] = old_val0
| (src_subword
<< start_bit
);
59 old_val1
= INV_SUBWORD(target
[start_elem
+1], 0, subword_width
+ start_bit
- uedge_bits
);
60 target
[start_elem
+1] = old_val1
| (src_subword
>> ( uedge_bits
- start_bit
));
62 hive_uedge old_val
= INV_SUBWORD(target
[start_elem
], start_bit
, start_bit
+ subword_width
);
63 target
[start_elem
] = old_val
| (src_subword
<< start_bit
);
74 /* pointers into wide_type: */
75 unsigned int start_elem
= (elem_bits
* index
) / uedge_bits
;
76 unsigned int start_bit
= (elem_bits
* index
) % uedge_bits
;
77 unsigned int end_elem
= (elem_bits
* (index
+ 1) - 1) / uedge_bits
;
78 unsigned int end_bit
= ((elem_bits
* (index
+ 1) - 1) % uedge_bits
) + 1;
80 if (elem_bits
== uedge_bits
) {
81 /* easy case for speedup: */
82 elem
[0] = vector
[index
];
83 } else if (start_elem
== end_elem
) {
84 /* only one (<=64 bits) element needs to be (partly) copied: */
85 move_subword(elem
, 0, vector
[start_elem
], start_bit
, end_bit
);
87 /* general case: handles edge spanning cases (includes >64bit elements) */
88 unsigned int bits_written
= 0;
90 move_upper_bits(elem
, bits_written
, vector
[start_elem
], start_bit
);
91 bits_written
+= (64 - start_bit
);
92 for(i
= start_elem
+1; i
< end_elem
; i
++) {
93 move_word(elem
, bits_written
, vector
[i
]);
94 bits_written
+= uedge_bits
;
96 move_lower_bits(elem
, bits_written
, vector
[end_elem
], end_bit
);
107 /* pointers into wide_type: */
108 unsigned int start_elem
= (elem_bits
* index
) / uedge_bits
;
110 /* easy case for speedup: */
111 if (elem_bits
== uedge_bits
) {
112 vector
[start_elem
] = elem
[0];
113 } else if (elem_bits
> uedge_bits
) {
114 unsigned bits_to_write
= elem_bits
;
115 unsigned start_bit
= elem_bits
* index
;
117 for(; bits_to_write
> uedge_bits
; bits_to_write
-= uedge_bits
, i
++, start_bit
+= uedge_bits
) {
118 move_word(vector
, start_bit
, elem
[i
]);
120 move_lower_bits(vector
, start_bit
, elem
[i
], bits_to_write
);
122 /* only one element needs to be (partly) copied: */
123 move_lower_bits(vector
, elem_bits
* index
, elem
[0], elem_bits
);
127 static void load_vector (
130 const t_vmem_elem
*from
)
135 data
= (hive_uedge
*)from
;
138 unsigned size
= sizeof(short)*ISP_NWAY
;
139 VMEM_ARRAY(v
, 2*ISP_NWAY
); /* Need 2 vectors to work around vmem hss bug */
140 assert(ISP_BAMEM_BASE
[ID
] != (hrt_address
)-1);
141 #if !defined(HRT_MEMORY_ACCESS)
142 ia_css_device_load(ISP_BAMEM_BASE
[ID
] + (unsigned long)from
, &v
[0][0], size
);
144 hrt_master_port_load(ISP_BAMEM_BASE
[ID
] + (unsigned long)from
, &v
[0][0], size
);
146 data
= (hive_uedge
*)v
;
148 for (i
= 0; i
< ISP_NWAY
; i
++) {
150 hive_sim_wide_unpack(data
, &elem
, ISP_VEC_ELEMBITS
, i
);
153 hrt_sleep(); /* Spend at least 1 cycles per vector */
156 static void store_vector (
159 const t_vmem_elem
*from
)
163 hive_uedge
*data
= (hive_uedge
*)to
;
165 for (i
= 0; i
< ISP_NWAY
; i
++) {
166 hive_sim_wide_pack(data
, (hive_wide
)&from
[i
], ISP_VEC_ELEMBITS
, i
);
169 unsigned size
= sizeof(short)*ISP_NWAY
;
170 VMEM_ARRAY(v
, 2*ISP_NWAY
); /* Need 2 vectors to work around vmem hss bug */
171 //load_vector (&v[1][0], &to[ISP_NWAY]); /* Fetch the next vector, since it will be overwritten. */
172 hive_uedge
*data
= (hive_uedge
*)v
;
173 for (i
= 0; i
< ISP_NWAY
; i
++) {
174 hive_sim_wide_pack(data
, (hive_wide
)&from
[i
], ISP_VEC_ELEMBITS
, i
);
176 assert(ISP_BAMEM_BASE
[ID
] != (hrt_address
)-1);
177 #if !defined(HRT_MEMORY_ACCESS)
178 ia_css_device_store(ISP_BAMEM_BASE
[ID
] + (unsigned long)to
, &v
, size
);
180 //hrt_mem_store (ISP, VMEM, (unsigned)to, &v, siz); /* This will overwrite the next vector as well */
181 hrt_master_port_store(ISP_BAMEM_BASE
[ID
] + (unsigned long)to
, &v
, size
);
183 hrt_sleep(); /* Spend at least 1 cycles per vector */
189 const t_vmem_elem
*from
,
191 unsigned elems
) /* In t_vmem_elem */
194 const t_vmem_elem
*vp
= from
;
195 assert(ID
< N_ISP_ID
);
197 assert((unsigned long)from
% ISP_VEC_ALIGN
== 0);
199 assert(elems
% ISP_NWAY
== 0);
200 for (c
= 0; c
< elems
; c
+= ISP_NWAY
) {
201 load_vector(ID
, &to
[c
], vp
);
202 vp
= (t_vmem_elem
*)((char*)vp
+ ISP_VEC_ALIGN
);
209 const t_vmem_elem
*from
,
210 unsigned elems
) /* In t_vmem_elem */
213 t_vmem_elem
*vp
= to
;
214 assert(ID
< N_ISP_ID
);
216 assert((unsigned long)to
% ISP_VEC_ALIGN
== 0);
218 assert(elems
% ISP_NWAY
== 0);
219 for (c
= 0; c
< elems
; c
+= ISP_NWAY
) {
220 store_vector (ID
, vp
, &from
[c
]);
221 vp
= (t_vmem_elem
*)((char*)vp
+ ISP_VEC_ALIGN
);
225 void isp_vmem_2d_load (
227 const t_vmem_elem
*from
,
231 unsigned stride_to
, /* In t_vmem_elem */
232 unsigned stride_from
/* In t_vmem_elem */)
236 assert(ID
< N_ISP_ID
);
238 assert((unsigned long)from
% ISP_VEC_ALIGN
== 0);
240 assert(width
% ISP_NWAY
== 0);
241 assert(stride_from
% ISP_NWAY
== 0);
242 for (h
= 0; h
< height
; h
++) {
244 const t_vmem_elem
*vp
= from
;
245 for (c
= 0; c
< width
; c
+= ISP_NWAY
) {
246 load_vector(ID
, &to
[stride_to
*h
+ c
], vp
);
247 vp
= (t_vmem_elem
*)((char*)vp
+ ISP_VEC_ALIGN
);
249 from
= (const t_vmem_elem
*)((const char *)from
+ stride_from
/ISP_NWAY
*ISP_VEC_ALIGN
);
253 void isp_vmem_2d_store (
256 const t_vmem_elem
*from
,
259 unsigned stride_to
, /* In t_vmem_elem */
260 unsigned stride_from
/* In t_vmem_elem */)
264 assert(ID
< N_ISP_ID
);
266 assert((unsigned long)to
% ISP_VEC_ALIGN
== 0);
268 assert(width
% ISP_NWAY
== 0);
269 assert(stride_to
% ISP_NWAY
== 0);
270 for (h
= 0; h
< height
; h
++) {
272 t_vmem_elem
*vp
= to
;
273 for (c
= 0; c
< width
; c
+= ISP_NWAY
) {
274 store_vector (ID
, vp
, &from
[stride_from
*h
+ c
]);
275 vp
= (t_vmem_elem
*)((char*)vp
+ ISP_VEC_ALIGN
);
277 to
= (t_vmem_elem
*)((char *)to
+ stride_to
/ISP_NWAY
*ISP_VEC_ALIGN
);