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