1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2022 MediaTek Inc.
4  * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
5  */
6 
7 #include <linux/mailbox_controller.h>
8 #include <linux/platform_device.h>
9 #include "mtk-mdp3-cmdq.h"
10 #include "mtk-mdp3-comp.h"
11 #include "mtk-mdp3-core.h"
12 #include "mtk-mdp3-m2m.h"
13 
14 #define MDP_PATH_MAX_COMPS	IMG_MAX_COMPONENTS
15 
16 struct mdp_path {
17 	struct mdp_dev		*mdp_dev;
18 	struct mdp_comp_ctx	comps[MDP_PATH_MAX_COMPS];
19 	u32			num_comps;
20 	const struct img_config	*config;
21 	const struct img_ipi_frameparam *param;
22 	const struct v4l2_rect	*composes[IMG_MAX_HW_OUTPUTS];
23 	struct v4l2_rect	bounds[IMG_MAX_HW_OUTPUTS];
24 };
25 
26 #define has_op(ctx, op) \
27 	((ctx)->comp->ops && (ctx)->comp->ops->op)
28  #define call_op(ctx, op, ...) \
29 	(has_op(ctx, op) ? (ctx)->comp->ops->op(ctx, ##__VA_ARGS__) : 0)
30 
31 static bool is_output_disabled(const struct img_compparam *param, u32 count)
32 {
33 	return (count < param->num_subfrms) ?
34 		(param->frame.output_disable ||
35 		param->subfrms[count].tile_disable) :
36 		true;
37 }
38 
39 static int mdp_path_subfrm_require(const struct mdp_path *path,
40 				   struct mdp_cmdq_cmd *cmd,
41 				   s32 *mutex_id, u32 count)
42 {
43 	const struct img_config *config = path->config;
44 	const struct mdp_comp_ctx *ctx;
45 	const struct mtk_mdp_driver_data *data = path->mdp_dev->mdp_data;
46 	struct device *dev = &path->mdp_dev->pdev->dev;
47 	struct mtk_mutex **mutex = path->mdp_dev->mdp_mutex;
48 	int id, index;
49 
50 	/* Decide which mutex to use based on the current pipeline */
51 	switch (path->comps[0].comp->id) {
52 	case MDP_COMP_RDMA0:
53 		*mutex_id = MDP_PIPE_RDMA0;
54 		break;
55 	case MDP_COMP_ISP_IMGI:
56 		*mutex_id = MDP_PIPE_IMGI;
57 		break;
58 	case MDP_COMP_WPEI:
59 		*mutex_id = MDP_PIPE_WPEI;
60 		break;
61 	case MDP_COMP_WPEI2:
62 		*mutex_id = MDP_PIPE_WPEI2;
63 		break;
64 	default:
65 		dev_err(dev, "Unknown pipeline and no mutex is assigned");
66 		return -EINVAL;
67 	}
68 
69 	/* Set mutex mod */
70 	for (index = 0; index < config->num_components; index++) {
71 		ctx = &path->comps[index];
72 		if (is_output_disabled(ctx->param, count))
73 			continue;
74 		id = ctx->comp->id;
75 		mtk_mutex_write_mod(mutex[*mutex_id],
76 				    data->mdp_mutex_table_idx[id], false);
77 	}
78 
79 	mtk_mutex_write_sof(mutex[*mutex_id],
80 			    MUTEX_SOF_IDX_SINGLE_MODE);
81 
82 	return 0;
83 }
84 
85 static int mdp_path_subfrm_run(const struct mdp_path *path,
86 			       struct mdp_cmdq_cmd *cmd,
87 			       s32 *mutex_id, u32 count)
88 {
89 	const struct img_config *config = path->config;
90 	const struct mdp_comp_ctx *ctx;
91 	struct device *dev = &path->mdp_dev->pdev->dev;
92 	struct mtk_mutex **mutex = path->mdp_dev->mdp_mutex;
93 	int index;
94 	s32 event;
95 
96 	if (-1 == *mutex_id) {
97 		dev_err(dev, "Incorrect mutex id");
98 		return -EINVAL;
99 	}
100 
101 	/* Wait WROT SRAM shared to DISP RDMA */
102 	/* Clear SOF event for each engine */
103 	for (index = 0; index < config->num_components; index++) {
104 		ctx = &path->comps[index];
105 		if (is_output_disabled(ctx->param, count))
106 			continue;
107 		event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF];
108 		if (event != MDP_GCE_NO_EVENT)
109 			MM_REG_CLEAR(cmd, event);
110 	}
111 
112 	/* Enable the mutex */
113 	mtk_mutex_enable_by_cmdq(mutex[*mutex_id], (void *)&cmd->pkt);
114 
115 	/* Wait SOF events and clear mutex modules (optional) */
116 	for (index = 0; index < config->num_components; index++) {
117 		ctx = &path->comps[index];
118 		if (is_output_disabled(ctx->param, count))
119 			continue;
120 		event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF];
121 		if (event != MDP_GCE_NO_EVENT)
122 			MM_REG_WAIT(cmd, event);
123 	}
124 
125 	return 0;
126 }
127 
128 static int mdp_path_ctx_init(struct mdp_dev *mdp, struct mdp_path *path)
129 {
130 	const struct img_config *config = path->config;
131 	int index, ret;
132 
133 	if (config->num_components < 1)
134 		return -EINVAL;
135 
136 	for (index = 0; index < config->num_components; index++) {
137 		ret = mdp_comp_ctx_config(mdp, &path->comps[index],
138 					  &config->components[index],
139 					  path->param);
140 		if (ret)
141 			return ret;
142 	}
143 
144 	return 0;
145 }
146 
147 static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
148 				  struct mdp_path *path, u32 count)
149 {
150 	const struct img_config *config = path->config;
151 	const struct img_mmsys_ctrl *ctrl = &config->ctrls[count];
152 	const struct img_mux *set;
153 	struct mdp_comp_ctx *ctx;
154 	s32 mutex_id;
155 	int index, ret;
156 
157 	/* Acquire components */
158 	ret = mdp_path_subfrm_require(path, cmd, &mutex_id, count);
159 	if (ret)
160 		return ret;
161 	/* Enable mux settings */
162 	for (index = 0; index < ctrl->num_sets; index++) {
163 		set = &ctrl->sets[index];
164 		cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg,
165 				    set->value, 0xFFFFFFFF);
166 	}
167 	/* Config sub-frame information */
168 	for (index = (config->num_components - 1); index >= 0; index--) {
169 		ctx = &path->comps[index];
170 		if (is_output_disabled(ctx->param, count))
171 			continue;
172 		ret = call_op(ctx, config_subfrm, cmd, count);
173 		if (ret)
174 			return ret;
175 	}
176 	/* Run components */
177 	ret = mdp_path_subfrm_run(path, cmd, &mutex_id, count);
178 	if (ret)
179 		return ret;
180 	/* Wait components done */
181 	for (index = 0; index < config->num_components; index++) {
182 		ctx = &path->comps[index];
183 		if (is_output_disabled(ctx->param, count))
184 			continue;
185 		ret = call_op(ctx, wait_comp_event, cmd);
186 		if (ret)
187 			return ret;
188 	}
189 	/* Advance to the next sub-frame */
190 	for (index = 0; index < config->num_components; index++) {
191 		ctx = &path->comps[index];
192 		ret = call_op(ctx, advance_subfrm, cmd, count);
193 		if (ret)
194 			return ret;
195 	}
196 	/* Disable mux settings */
197 	for (index = 0; index < ctrl->num_sets; index++) {
198 		set = &ctrl->sets[index];
199 		cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg,
200 				    0, 0xFFFFFFFF);
201 	}
202 
203 	return 0;
204 }
205 
206 static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmdq_cmd *cmd,
207 			   struct mdp_path *path)
208 {
209 	const struct img_config *config = path->config;
210 	struct mdp_comp_ctx *ctx;
211 	int index, count, ret;
212 
213 	/* Config path frame */
214 	/* Reset components */
215 	for (index = 0; index < config->num_components; index++) {
216 		ctx = &path->comps[index];
217 		ret = call_op(ctx, init_comp, cmd);
218 		if (ret)
219 			return ret;
220 	}
221 	/* Config frame mode */
222 	for (index = 0; index < config->num_components; index++) {
223 		const struct v4l2_rect *compose =
224 			path->composes[ctx->param->outputs[0]];
225 
226 		ctx = &path->comps[index];
227 		ret = call_op(ctx, config_frame, cmd, compose);
228 		if (ret)
229 			return ret;
230 	}
231 
232 	/* Config path sub-frames */
233 	for (count = 0; count < config->num_subfrms; count++) {
234 		ret = mdp_path_config_subfrm(cmd, path, count);
235 		if (ret)
236 			return ret;
237 	}
238 	/* Post processing information */
239 	for (index = 0; index < config->num_components; index++) {
240 		ctx = &path->comps[index];
241 		ret = call_op(ctx, post_process, cmd);
242 		if (ret)
243 			return ret;
244 	}
245 	return 0;
246 }
247 
248 static int mdp_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
249 			       size_t size)
250 {
251 	struct device *dev;
252 	dma_addr_t dma_addr;
253 
254 	pkt->va_base = kzalloc(size, GFP_KERNEL);
255 	if (!pkt->va_base) {
256 		kfree(pkt);
257 		return -ENOMEM;
258 	}
259 	pkt->buf_size = size;
260 	pkt->cl = (void *)client;
261 
262 	dev = client->chan->mbox->dev;
263 	dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
264 				  DMA_TO_DEVICE);
265 	if (dma_mapping_error(dev, dma_addr)) {
266 		dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
267 		kfree(pkt->va_base);
268 		return -ENOMEM;
269 	}
270 
271 	pkt->pa_base = dma_addr;
272 
273 	return 0;
274 }
275 
276 static void mdp_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
277 {
278 	struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
279 
280 	dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
281 			 DMA_TO_DEVICE);
282 	kfree(pkt->va_base);
283 	pkt->va_base = NULL;
284 }
285 
286 static void mdp_auto_release_work(struct work_struct *work)
287 {
288 	struct mdp_cmdq_cmd *cmd;
289 	struct mdp_dev *mdp;
290 
291 	cmd = container_of(work, struct mdp_cmdq_cmd, auto_release_work);
292 	mdp = cmd->mdp;
293 
294 	mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
295 	mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
296 			    cmd->num_comps);
297 
298 	atomic_dec(&mdp->job_count);
299 	wake_up(&mdp->callback_wq);
300 
301 	mdp_cmdq_pkt_destroy(&cmd->pkt);
302 	kfree(cmd->comps);
303 	cmd->comps = NULL;
304 	kfree(cmd);
305 	cmd = NULL;
306 }
307 
308 static void mdp_handle_cmdq_callback(struct mbox_client *cl, void *mssg)
309 {
310 	struct mdp_cmdq_cmd *cmd;
311 	struct cmdq_cb_data *data;
312 	struct mdp_dev *mdp;
313 	struct device *dev;
314 
315 	if (!mssg) {
316 		pr_info("%s:no callback data\n", __func__);
317 		return;
318 	}
319 
320 	data = (struct cmdq_cb_data *)mssg;
321 	cmd = container_of(data->pkt, struct mdp_cmdq_cmd, pkt);
322 	mdp = cmd->mdp;
323 	dev = &mdp->pdev->dev;
324 
325 	if (cmd->mdp_ctx)
326 		mdp_m2m_job_finish(cmd->mdp_ctx);
327 
328 	if (cmd->user_cmdq_cb) {
329 		struct cmdq_cb_data user_cb_data;
330 
331 		user_cb_data.sta = data->sta;
332 		user_cb_data.pkt = data->pkt;
333 		cmd->user_cmdq_cb(user_cb_data);
334 	}
335 
336 	INIT_WORK(&cmd->auto_release_work, mdp_auto_release_work);
337 	if (!queue_work(mdp->clock_wq, &cmd->auto_release_work)) {
338 		dev_err(dev, "%s:queue_work fail!\n", __func__);
339 		mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
340 		mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
341 				    cmd->num_comps);
342 
343 		atomic_dec(&mdp->job_count);
344 		wake_up(&mdp->callback_wq);
345 
346 		mdp_cmdq_pkt_destroy(&cmd->pkt);
347 		kfree(cmd->comps);
348 		cmd->comps = NULL;
349 		kfree(cmd);
350 		cmd = NULL;
351 	}
352 }
353 
354 int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
355 {
356 	struct mdp_path *path = NULL;
357 	struct mdp_cmdq_cmd *cmd = NULL;
358 	struct mdp_comp *comps = NULL;
359 	struct device *dev = &mdp->pdev->dev;
360 	int i, ret;
361 
362 	atomic_inc(&mdp->job_count);
363 	if (atomic_read(&mdp->suspended)) {
364 		atomic_dec(&mdp->job_count);
365 		return -ECANCELED;
366 	}
367 
368 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
369 	if (!cmd) {
370 		ret = -ENOMEM;
371 		goto err_cmdq_data;
372 	}
373 
374 	if (mdp_cmdq_pkt_create(mdp->cmdq_clt, &cmd->pkt, SZ_16K)) {
375 		ret = -ENOMEM;
376 		goto err_cmdq_data;
377 	}
378 
379 	comps = kcalloc(param->config->num_components, sizeof(*comps),
380 			GFP_KERNEL);
381 	if (!comps) {
382 		ret = -ENOMEM;
383 		goto err_cmdq_data;
384 	}
385 
386 	path = kzalloc(sizeof(*path), GFP_KERNEL);
387 	if (!path) {
388 		ret = -ENOMEM;
389 		goto err_cmdq_data;
390 	}
391 
392 	path->mdp_dev = mdp;
393 	path->config = param->config;
394 	path->param = param->param;
395 	for (i = 0; i < param->param->num_outputs; i++) {
396 		path->bounds[i].left = 0;
397 		path->bounds[i].top = 0;
398 		path->bounds[i].width =
399 			param->param->outputs[i].buffer.format.width;
400 		path->bounds[i].height =
401 			param->param->outputs[i].buffer.format.height;
402 		path->composes[i] = param->composes[i] ?
403 			param->composes[i] : &path->bounds[i];
404 	}
405 
406 	ret = mdp_path_ctx_init(mdp, path);
407 	if (ret) {
408 		dev_err(dev, "mdp_path_ctx_init error\n");
409 		goto err_cmdq_data;
410 	}
411 
412 	mtk_mutex_prepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
413 
414 	ret = mdp_path_config(mdp, cmd, path);
415 	if (ret) {
416 		dev_err(dev, "mdp_path_config error\n");
417 		goto err_cmdq_data;
418 	}
419 	cmdq_pkt_finalize(&cmd->pkt);
420 
421 	for (i = 0; i < param->config->num_components; i++)
422 		memcpy(&comps[i], path->comps[i].comp,
423 		       sizeof(struct mdp_comp));
424 
425 	mdp->cmdq_clt->client.rx_callback = mdp_handle_cmdq_callback;
426 	cmd->mdp = mdp;
427 	cmd->user_cmdq_cb = param->cmdq_cb;
428 	cmd->user_cb_data = param->cb_data;
429 	cmd->comps = comps;
430 	cmd->num_comps = param->config->num_components;
431 	cmd->mdp_ctx = param->mdp_ctx;
432 
433 	ret = mdp_comp_clocks_on(&mdp->pdev->dev, cmd->comps, cmd->num_comps);
434 	if (ret) {
435 		dev_err(dev, "comp %d failed to enable clock!\n", ret);
436 		goto err_clock_off;
437 	}
438 
439 	dma_sync_single_for_device(mdp->cmdq_clt->chan->mbox->dev,
440 				   cmd->pkt.pa_base, cmd->pkt.cmd_buf_size,
441 				   DMA_TO_DEVICE);
442 	ret = mbox_send_message(mdp->cmdq_clt->chan, &cmd->pkt);
443 	if (ret < 0) {
444 		dev_err(dev, "mbox send message fail %d!\n", ret);
445 		goto err_clock_off;
446 	}
447 	mbox_client_txdone(mdp->cmdq_clt->chan, 0);
448 
449 	kfree(path);
450 	return 0;
451 
452 err_clock_off:
453 	mtk_mutex_unprepare(mdp->mdp_mutex[MDP_PIPE_RDMA0]);
454 	mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
455 			    cmd->num_comps);
456 err_cmdq_data:
457 	kfree(path);
458 	atomic_dec(&mdp->job_count);
459 	wake_up(&mdp->callback_wq);
460 	if (cmd && cmd->pkt.buf_size > 0)
461 		mdp_cmdq_pkt_destroy(&cmd->pkt);
462 	kfree(comps);
463 	kfree(cmd);
464 	return ret;
465 }
466 EXPORT_SYMBOL_GPL(mdp_cmdq_send);
467