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