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 "ia_css_pipeline.h"
19 #include "ia_css_isp_param.h"
20 
21 /* Set functions for parameter memory descriptors */
22 
23 void
24 ia_css_isp_param_set_mem_init(
25     struct ia_css_isp_param_host_segments *mem_init,
26     enum ia_css_param_class pclass,
27     enum ia_css_isp_memories mem,
28     char *address, size_t size)
29 {
30 	mem_init->params[pclass][mem].address = address;
31 	mem_init->params[pclass][mem].size = (uint32_t)size;
32 }
33 
34 void
35 ia_css_isp_param_set_css_mem_init(
36     struct ia_css_isp_param_css_segments *mem_init,
37     enum ia_css_param_class pclass,
38     enum ia_css_isp_memories mem,
39     ia_css_ptr address, size_t size)
40 {
41 	mem_init->params[pclass][mem].address = address;
42 	mem_init->params[pclass][mem].size = (uint32_t)size;
43 }
44 
45 void
46 ia_css_isp_param_set_isp_mem_init(
47     struct ia_css_isp_param_isp_segments *mem_init,
48     enum ia_css_param_class pclass,
49     enum ia_css_isp_memories mem,
50     u32 address, size_t size)
51 {
52 	mem_init->params[pclass][mem].address = address;
53 	mem_init->params[pclass][mem].size = (uint32_t)size;
54 }
55 
56 /* Get functions for parameter memory descriptors */
57 const struct ia_css_host_data *
58 ia_css_isp_param_get_mem_init(
59     const struct ia_css_isp_param_host_segments *mem_init,
60     enum ia_css_param_class pclass,
61     enum ia_css_isp_memories mem)
62 {
63 	return &mem_init->params[pclass][mem];
64 }
65 
66 const struct ia_css_data *
67 ia_css_isp_param_get_css_mem_init(
68     const struct ia_css_isp_param_css_segments *mem_init,
69     enum ia_css_param_class pclass,
70     enum ia_css_isp_memories mem)
71 {
72 	return &mem_init->params[pclass][mem];
73 }
74 
75 const struct ia_css_isp_data *
76 ia_css_isp_param_get_isp_mem_init(
77     const struct ia_css_isp_param_isp_segments *mem_init,
78     enum ia_css_param_class pclass,
79     enum ia_css_isp_memories mem)
80 {
81 	return &mem_init->params[pclass][mem];
82 }
83 
84 void
85 ia_css_init_memory_interface(
86     struct ia_css_isp_param_css_segments *isp_mem_if,
87     const struct ia_css_isp_param_host_segments *mem_params,
88     const struct ia_css_isp_param_css_segments *css_params)
89 {
90 	unsigned int pclass, mem;
91 
92 	for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) {
93 		memset(isp_mem_if->params[pclass], 0, sizeof(isp_mem_if->params[pclass]));
94 		for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++) {
95 			if (!mem_params->params[pclass][mem].address)
96 				continue;
97 			isp_mem_if->params[pclass][mem].size = mem_params->params[pclass][mem].size;
98 			if (pclass != IA_CSS_PARAM_CLASS_PARAM)
99 				isp_mem_if->params[pclass][mem].address =
100 				    css_params->params[pclass][mem].address;
101 		}
102 	}
103 }
104 
105 int
106 ia_css_isp_param_allocate_isp_parameters(
107     struct ia_css_isp_param_host_segments *mem_params,
108     struct ia_css_isp_param_css_segments *css_params,
109     const struct ia_css_isp_param_isp_segments *mem_initializers) {
110 	int err = 0;
111 	unsigned int mem, pclass;
112 
113 	pclass = IA_CSS_PARAM_CLASS_PARAM;
114 	for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++)
115 	{
116 		for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) {
117 			u32 size = 0;
118 
119 			if (mem_initializers)
120 				size = mem_initializers->params[pclass][mem].size;
121 			mem_params->params[pclass][mem].size = size;
122 			mem_params->params[pclass][mem].address = NULL;
123 			css_params->params[pclass][mem].size = size;
124 			css_params->params[pclass][mem].address = 0x0;
125 			if (size) {
126 				mem_params->params[pclass][mem].address = kvcalloc(1,
127 										   size,
128 										   GFP_KERNEL);
129 				if (!mem_params->params[pclass][mem].address) {
130 					err = -ENOMEM;
131 					goto cleanup;
132 				}
133 				if (pclass != IA_CSS_PARAM_CLASS_PARAM) {
134 					css_params->params[pclass][mem].address = hmm_alloc(size, HMM_BO_PRIVATE, 0, NULL, 0);
135 					if (!css_params->params[pclass][mem].address) {
136 						err = -ENOMEM;
137 						goto cleanup;
138 					}
139 				}
140 			}
141 		}
142 	}
143 	return err;
144 cleanup:
145 	ia_css_isp_param_destroy_isp_parameters(mem_params, css_params);
146 	return err;
147 }
148 
149 void
150 ia_css_isp_param_destroy_isp_parameters(
151     struct ia_css_isp_param_host_segments *mem_params,
152     struct ia_css_isp_param_css_segments *css_params)
153 {
154 	unsigned int mem, pclass;
155 
156 	for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++) {
157 		for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) {
158 			if (mem_params->params[pclass][mem].address)
159 				kvfree(mem_params->params[pclass][mem].address);
160 			if (css_params->params[pclass][mem].address)
161 				hmm_free(css_params->params[pclass][mem].address);
162 			mem_params->params[pclass][mem].address = NULL;
163 			css_params->params[pclass][mem].address = 0x0;
164 		}
165 	}
166 }
167 
168 void
169 ia_css_isp_param_load_fw_params(
170     const char *fw,
171     union ia_css_all_memory_offsets *mem_offsets,
172     const struct ia_css_isp_param_memory_offsets *memory_offsets,
173     bool init)
174 {
175 	unsigned int pclass;
176 
177 	for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) {
178 		mem_offsets->array[pclass].ptr = NULL;
179 		if (init)
180 			mem_offsets->array[pclass].ptr = (void *)(fw + memory_offsets->offsets[pclass]);
181 	}
182 }
183 
184 int
185 ia_css_isp_param_copy_isp_mem_if_to_ddr(
186     struct ia_css_isp_param_css_segments *ddr,
187     const struct ia_css_isp_param_host_segments *host,
188     enum ia_css_param_class pclass) {
189 	unsigned int mem;
190 
191 	for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++)
192 	{
193 		size_t       size	  = host->params[pclass][mem].size;
194 		ia_css_ptr ddr_mem_ptr  = ddr->params[pclass][mem].address;
195 		char	    *host_mem_ptr = host->params[pclass][mem].address;
196 
197 		if (size != ddr->params[pclass][mem].size)
198 			return -EINVAL;
199 		if (!size)
200 			continue;
201 		hmm_store(ddr_mem_ptr, host_mem_ptr, size);
202 	}
203 	return 0;
204 }
205 
206 void
207 ia_css_isp_param_enable_pipeline(
208     const struct ia_css_isp_param_host_segments *mem_params)
209 {
210 	/* By protocol b0 of the mandatory uint32_t first field of the
211 	   input parameter is a disable bit*/
212 	short dmem_offset = 0;
213 
214 	if (mem_params->params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM0].size == 0)
215 		return;
216 
217 	*(uint32_t *)
218 	&mem_params->params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM0].address[dmem_offset]
219 	    = 0x0;
220 }
221