Linux-libre 4.15.7-gnu
[librecmc/linux-libre.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / runtime / queue / src / queue_access.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 "type_support.h"
32 #include "queue_access.h"
33 #include "ia_css_circbuf.h"
34 #include "sp.h"
35 #include "memory_access.h"
36 #include "assert_support.h"
37
38 int ia_css_queue_load(
39                 struct ia_css_queue *rdesc,
40                 ia_css_circbuf_desc_t *cb_desc,
41                 uint32_t ignore_desc_flags)
42 {
43         if (rdesc == NULL || cb_desc == NULL)
44                 return EINVAL;
45
46         if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
47                 assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX);
48
49                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG)) {
50                         cb_desc->size = sp_dmem_load_uint8(rdesc->proc_id,
51                                 rdesc->desc.remote.cb_desc_addr
52                                 + offsetof(ia_css_circbuf_desc_t, size));
53
54                         if (0 == cb_desc->size) {
55                                 /* Adding back the workaround which was removed
56                                    while refactoring queues. When reading size
57                                    through sp_dmem_load_*, sometimes we get back
58                                    the value as zero. This causes division by 0
59                                    exception as the size is used in a modular
60                                    division operation. */
61                                 return EDOM;
62                         }
63                 }
64
65                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG))
66                         cb_desc->start = sp_dmem_load_uint8(rdesc->proc_id,
67                                 rdesc->desc.remote.cb_desc_addr
68                                 + offsetof(ia_css_circbuf_desc_t, start));
69
70                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG))
71                         cb_desc->end = sp_dmem_load_uint8(rdesc->proc_id,
72                                 rdesc->desc.remote.cb_desc_addr
73                                 + offsetof(ia_css_circbuf_desc_t, end));
74
75                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG))
76                         cb_desc->step = sp_dmem_load_uint8(rdesc->proc_id,
77                                 rdesc->desc.remote.cb_desc_addr
78                                 + offsetof(ia_css_circbuf_desc_t, step));
79
80         } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
81                 /* doing DMA transfer of entire structure */
82                 mmgr_load(rdesc->desc.remote.cb_desc_addr,
83                         (void *)cb_desc,
84                         sizeof(ia_css_circbuf_desc_t));
85         } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
86                 /* Not supported yet */
87                 return ENOTSUP;
88         }
89
90         return 0;
91 }
92
93 int ia_css_queue_store(
94                 struct ia_css_queue *rdesc,
95                 ia_css_circbuf_desc_t *cb_desc,
96                 uint32_t ignore_desc_flags)
97 {
98         if (rdesc == NULL || cb_desc == NULL)
99                 return EINVAL;
100
101         if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
102                 assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX);
103
104                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG))
105                         sp_dmem_store_uint8(rdesc->proc_id,
106                                 rdesc->desc.remote.cb_desc_addr
107                                 + offsetof(ia_css_circbuf_desc_t, size),
108                                 cb_desc->size);
109
110                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG))
111                         sp_dmem_store_uint8(rdesc->proc_id,
112                                 rdesc->desc.remote.cb_desc_addr
113                                 + offsetof(ia_css_circbuf_desc_t, start),
114                                 cb_desc->start);
115
116                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG))
117                         sp_dmem_store_uint8(rdesc->proc_id,
118                                 rdesc->desc.remote.cb_desc_addr
119                                 + offsetof(ia_css_circbuf_desc_t, end),
120                                 cb_desc->end);
121
122                 if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG))
123                         sp_dmem_store_uint8(rdesc->proc_id,
124                                 rdesc->desc.remote.cb_desc_addr
125                                 + offsetof(ia_css_circbuf_desc_t, step),
126                                 cb_desc->step);
127         } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
128                 /* doing DMA transfer of entire structure */
129                 mmgr_store(rdesc->desc.remote.cb_desc_addr,
130                         (void *)cb_desc,
131                         sizeof(ia_css_circbuf_desc_t));
132         } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
133                 /* Not supported yet */
134                 return ENOTSUP;
135         }
136
137         return 0;
138 }
139
140 int ia_css_queue_item_load(
141                 struct ia_css_queue *rdesc,
142                 uint8_t position,
143                 ia_css_circbuf_elem_t *item)
144 {
145         if (rdesc == NULL || item == NULL)
146                 return EINVAL;
147
148         if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
149                 sp_dmem_load(rdesc->proc_id,
150                         rdesc->desc.remote.cb_elems_addr
151                         + position * sizeof(ia_css_circbuf_elem_t),
152                         item,
153                         sizeof(ia_css_circbuf_elem_t));
154         } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
155                 mmgr_load(rdesc->desc.remote.cb_elems_addr
156                         + position * sizeof(ia_css_circbuf_elem_t),
157                         (void *)item,
158                         sizeof(ia_css_circbuf_elem_t));
159         } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
160                 /* Not supported yet */
161                 return ENOTSUP;
162         }
163
164         return 0;
165 }
166
167 int ia_css_queue_item_store(
168                 struct ia_css_queue *rdesc,
169                 uint8_t position,
170                 ia_css_circbuf_elem_t *item)
171 {
172         if (rdesc == NULL || item == NULL)
173                 return EINVAL;
174
175         if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
176                 sp_dmem_store(rdesc->proc_id,
177                         rdesc->desc.remote.cb_elems_addr
178                         + position * sizeof(ia_css_circbuf_elem_t),
179                         item,
180                         sizeof(ia_css_circbuf_elem_t));
181         } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
182                 mmgr_store(rdesc->desc.remote.cb_elems_addr
183                         + position * sizeof(ia_css_circbuf_elem_t),
184                         (void *)item,
185                         sizeof(ia_css_circbuf_elem_t));
186         } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
187                 /* Not supported yet */
188                 return ENOTSUP;
189         }
190
191         return 0;
192 }