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
23void
24ia_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
34void
35ia_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
45void
46ia_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 */
57const struct ia_css_host_data *
58ia_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
66const struct ia_css_data *
67ia_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
75const struct ia_css_isp_data *
76ia_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
84void
85ia_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
105int
106ia_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;
144cleanup:
145	ia_css_isp_param_destroy_isp_parameters(mem_params, css_params);
146	return err;
147}
148
149void
150ia_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
167void
168ia_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
183int
184ia_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
205void
206ia_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