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