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
24int 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
79int 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
126int 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
153int 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