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
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)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
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)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
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)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 *
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)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 *
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)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 *
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)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
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)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
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)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);
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
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)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  			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
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)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
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)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
ia_css_isp_param_enable_pipeline(const struct ia_css_isp_param_host_segments * mem_params)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