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