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 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 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 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 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