1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2010 - 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 "type_support.h"
19 #include "queue_access.h"
20 #include "ia_css_circbuf.h"
21 #include "sp.h"
22 #include "assert_support.h"
23
ia_css_queue_load(struct ia_css_queue * rdesc,ia_css_circbuf_desc_t * cb_desc,uint32_t ignore_desc_flags)24 int ia_css_queue_load(
25 struct ia_css_queue *rdesc,
26 ia_css_circbuf_desc_t *cb_desc,
27 uint32_t ignore_desc_flags)
28 {
29 if (!rdesc || !cb_desc)
30 return -EINVAL;
31
32 if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
33 assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX);
34
35 if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG)) {
36 cb_desc->size = sp_dmem_load_uint8(rdesc->proc_id,
37 rdesc->desc.remote.cb_desc_addr
38 + offsetof(ia_css_circbuf_desc_t, size));
39
40 if (cb_desc->size == 0) {
41 /* Adding back the workaround which was removed
42 while refactoring queues. When reading size
43 through sp_dmem_load_*, sometimes we get back
44 the value as zero. This causes division by 0
45 exception as the size is used in a modular
46 division operation. */
47 return -EDOM;
48 }
49 }
50
51 if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG))
52 cb_desc->start = sp_dmem_load_uint8(rdesc->proc_id,
53 rdesc->desc.remote.cb_desc_addr
54 + offsetof(ia_css_circbuf_desc_t, start));
55
56 if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG))
57 cb_desc->end = sp_dmem_load_uint8(rdesc->proc_id,
58 rdesc->desc.remote.cb_desc_addr
59 + offsetof(ia_css_circbuf_desc_t, end));
60
61 if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG))
62 cb_desc->step = sp_dmem_load_uint8(rdesc->proc_id,
63 rdesc->desc.remote.cb_desc_addr
64 + offsetof(ia_css_circbuf_desc_t, step));
65
66 } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
67 /* doing DMA transfer of entire structure */
68 hmm_load(rdesc->desc.remote.cb_desc_addr,
69 (void *)cb_desc,
70 sizeof(ia_css_circbuf_desc_t));
71 } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
72 /* Not supported yet */
73 return -ENOTSUPP;
74 }
75
76 return 0;
77 }
78
ia_css_queue_store(struct ia_css_queue * rdesc,ia_css_circbuf_desc_t * cb_desc,uint32_t ignore_desc_flags)79 int ia_css_queue_store(
80 struct ia_css_queue *rdesc,
81 ia_css_circbuf_desc_t *cb_desc,
82 uint32_t ignore_desc_flags)
83 {
84 if (!rdesc || !cb_desc)
85 return -EINVAL;
86
87 if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
88 assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX);
89
90 if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG))
91 sp_dmem_store_uint8(rdesc->proc_id,
92 rdesc->desc.remote.cb_desc_addr
93 + offsetof(ia_css_circbuf_desc_t, size),
94 cb_desc->size);
95
96 if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG))
97 sp_dmem_store_uint8(rdesc->proc_id,
98 rdesc->desc.remote.cb_desc_addr
99 + offsetof(ia_css_circbuf_desc_t, start),
100 cb_desc->start);
101
102 if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG))
103 sp_dmem_store_uint8(rdesc->proc_id,
104 rdesc->desc.remote.cb_desc_addr
105 + offsetof(ia_css_circbuf_desc_t, end),
106 cb_desc->end);
107
108 if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG))
109 sp_dmem_store_uint8(rdesc->proc_id,
110 rdesc->desc.remote.cb_desc_addr
111 + offsetof(ia_css_circbuf_desc_t, step),
112 cb_desc->step);
113 } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
114 /* doing DMA transfer of entire structure */
115 hmm_store(rdesc->desc.remote.cb_desc_addr,
116 (void *)cb_desc,
117 sizeof(ia_css_circbuf_desc_t));
118 } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
119 /* Not supported yet */
120 return -ENOTSUPP;
121 }
122
123 return 0;
124 }
125
ia_css_queue_item_load(struct ia_css_queue * rdesc,u8 position,ia_css_circbuf_elem_t * item)126 int ia_css_queue_item_load(
127 struct ia_css_queue *rdesc,
128 u8 position,
129 ia_css_circbuf_elem_t *item)
130 {
131 if (!rdesc || !item)
132 return -EINVAL;
133
134 if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
135 sp_dmem_load(rdesc->proc_id,
136 rdesc->desc.remote.cb_elems_addr
137 + position * sizeof(ia_css_circbuf_elem_t),
138 item,
139 sizeof(ia_css_circbuf_elem_t));
140 } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
141 hmm_load(rdesc->desc.remote.cb_elems_addr
142 + position * sizeof(ia_css_circbuf_elem_t),
143 (void *)item,
144 sizeof(ia_css_circbuf_elem_t));
145 } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
146 /* Not supported yet */
147 return -ENOTSUPP;
148 }
149
150 return 0;
151 }
152
ia_css_queue_item_store(struct ia_css_queue * rdesc,u8 position,ia_css_circbuf_elem_t * item)153 int ia_css_queue_item_store(
154 struct ia_css_queue *rdesc,
155 u8 position,
156 ia_css_circbuf_elem_t *item)
157 {
158 if (!rdesc || !item)
159 return -EINVAL;
160
161 if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
162 sp_dmem_store(rdesc->proc_id,
163 rdesc->desc.remote.cb_elems_addr
164 + position * sizeof(ia_css_circbuf_elem_t),
165 item,
166 sizeof(ia_css_circbuf_elem_t));
167 } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
168 hmm_store(rdesc->desc.remote.cb_elems_addr
169 + position * sizeof(ia_css_circbuf_elem_t),
170 (void *)item,
171 sizeof(ia_css_circbuf_elem_t));
172 } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
173 /* Not supported yet */
174 return -ENOTSUPP;
175 }
176
177 return 0;
178 }
179