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
17struct 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
32static 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
47static 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
98static 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
145static 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
170static 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
236static 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
290static 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
317static 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
327static 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
351static 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
399int 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
505err_clock_off:
506	mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
507			    cmd->num_comps);
508err_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);
512err_free_comps:
513	kfree(comps);
514err_destroy_pkt:
515	mdp_cmdq_pkt_destroy(&cmd->pkt);
516err_free_cmd:
517	kfree(cmd);
518err_cancel_job:
519	atomic_dec(&mdp->job_count);
520
521	return ret;
522}
523EXPORT_SYMBOL_GPL(mdp_cmdq_send);
524