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-cfg.h"
10 #include "mtk-mdp3-cmdq.h"
11 #include "mtk-mdp3-comp.h"
12 #include "mtk-mdp3-core.h"
13 #include "mtk-mdp3-m2m.h"
14 #include "mtk-img-ipi.h"
15
16 #define MDP_PATH_MAX_COMPS IMG_MAX_COMPONENTS
17
18 struct mdp_path {
19 struct mdp_dev *mdp_dev;
20 struct mdp_comp_ctx comps[MDP_PATH_MAX_COMPS];
21 u32 num_comps;
22 const struct img_config *config;
23 const struct img_ipi_frameparam *param;
24 const struct v4l2_rect *composes[IMG_MAX_HW_OUTPUTS];
25 struct v4l2_rect bounds[IMG_MAX_HW_OUTPUTS];
26 };
27
28 #define has_op(ctx, op) \
29 ((ctx)->comp->ops && (ctx)->comp->ops->op)
30 #define call_op(ctx, op, ...) \
31 (has_op(ctx, op) ? (ctx)->comp->ops->op(ctx, ##__VA_ARGS__) : 0)
32
is_output_disabled(int p_id,const struct img_compparam * param,u32 count)33 static bool is_output_disabled(int p_id, const struct img_compparam *param, u32 count)
34 {
35 u32 num = 0;
36 bool dis_output = false;
37 bool dis_tile = false;
38
39 if (CFG_CHECK(MT8183, p_id)) {
40 num = CFG_COMP(MT8183, param, num_subfrms);
41 dis_output = CFG_COMP(MT8183, param, frame.output_disable);
42 dis_tile = CFG_COMP(MT8183, param, frame.output_disable);
43 } else if (CFG_CHECK(MT8195, p_id)) {
44 num = CFG_COMP(MT8195, param, num_subfrms);
45 dis_output = CFG_COMP(MT8195, param, frame.output_disable);
46 dis_tile = CFG_COMP(MT8195, param, frame.output_disable);
47 }
48
49 return (count < num) ? (dis_output || dis_tile) : true;
50 }
51
__get_mutex(const struct mdp_dev * mdp_dev,const struct mdp_pipe_info * p)52 static struct mtk_mutex *__get_mutex(const struct mdp_dev *mdp_dev,
53 const struct mdp_pipe_info *p)
54 {
55 return mdp_dev->mm_subsys[p->sub_id].mdp_mutex[p->mutex_id];
56 }
57
__get_pp_num(enum mdp_stream_type type)58 static u8 __get_pp_num(enum mdp_stream_type type)
59 {
60 switch (type) {
61 case MDP_STREAM_TYPE_DUAL_BITBLT:
62 return MDP_PP_USED_2;
63 default:
64 return MDP_PP_USED_1;
65 }
66 }
67
__get_pipe(const struct mdp_dev * mdp_dev,enum mtk_mdp_comp_id id)68 static enum mdp_pipe_id __get_pipe(const struct mdp_dev *mdp_dev,
69 enum mtk_mdp_comp_id id)
70 {
71 enum mdp_pipe_id pipe_id;
72
73 switch (id) {
74 case MDP_COMP_RDMA0:
75 pipe_id = MDP_PIPE_RDMA0;
76 break;
77 case MDP_COMP_ISP_IMGI:
78 pipe_id = MDP_PIPE_IMGI;
79 break;
80 case MDP_COMP_WPEI:
81 pipe_id = MDP_PIPE_WPEI;
82 break;
83 case MDP_COMP_WPEI2:
84 pipe_id = MDP_PIPE_WPEI2;
85 break;
86 case MDP_COMP_RDMA1:
87 pipe_id = MDP_PIPE_RDMA1;
88 break;
89 case MDP_COMP_RDMA2:
90 pipe_id = MDP_PIPE_RDMA2;
91 break;
92 case MDP_COMP_RDMA3:
93 pipe_id = MDP_PIPE_RDMA3;
94 break;
95 default:
96 /* Avoid exceptions when operating MUTEX */
97 pipe_id = MDP_PIPE_RDMA0;
98 dev_err(&mdp_dev->pdev->dev, "Unknown pipeline id %d", id);
99 break;
100 }
101
102 return pipe_id;
103 }
104
__get_config_offset(struct mdp_dev * mdp,struct mdp_cmdq_param * param,u8 pp_idx)105 static struct img_config *__get_config_offset(struct mdp_dev *mdp,
106 struct mdp_cmdq_param *param,
107 u8 pp_idx)
108 {
109 const int p_id = mdp->mdp_data->mdp_plat_id;
110 struct device *dev = &mdp->pdev->dev;
111 void *cfg_c, *cfg_n;
112 long bound = mdp->vpu.config_size;
113
114 if (pp_idx >= mdp->mdp_data->pp_used)
115 goto err_param;
116
117 if (CFG_CHECK(MT8183, p_id))
118 cfg_c = CFG_OFST(MT8183, param->config, pp_idx);
119 else if (CFG_CHECK(MT8195, p_id))
120 cfg_c = CFG_OFST(MT8195, param->config, pp_idx);
121 else
122 goto err_param;
123
124 if (CFG_CHECK(MT8183, p_id))
125 cfg_n = CFG_OFST(MT8183, param->config, pp_idx + 1);
126 else if (CFG_CHECK(MT8195, p_id))
127 cfg_n = CFG_OFST(MT8195, param->config, pp_idx + 1);
128 else
129 goto err_param;
130
131 if ((long)cfg_n - (long)mdp->vpu.config > bound) {
132 dev_err(dev, "config offset %ld OOB %ld\n", (long)cfg_n, bound);
133 cfg_c = ERR_PTR(-EFAULT);
134 }
135
136 return (struct img_config *)cfg_c;
137
138 err_param:
139 cfg_c = ERR_PTR(-EINVAL);
140 return (struct img_config *)cfg_c;
141 }
142
mdp_path_subfrm_require(const struct mdp_path * path,struct mdp_cmdq_cmd * cmd,struct mdp_pipe_info * p,u32 count)143 static int mdp_path_subfrm_require(const struct mdp_path *path,
144 struct mdp_cmdq_cmd *cmd,
145 struct mdp_pipe_info *p, u32 count)
146 {
147 const int p_id = path->mdp_dev->mdp_data->mdp_plat_id;
148 const struct mdp_comp_ctx *ctx;
149 const struct mtk_mdp_driver_data *data = path->mdp_dev->mdp_data;
150 struct mtk_mutex *mutex;
151 int id, index;
152 u32 num_comp = 0;
153
154 if (CFG_CHECK(MT8183, p_id))
155 num_comp = CFG_GET(MT8183, path->config, num_components);
156 else if (CFG_CHECK(MT8195, p_id))
157 num_comp = CFG_GET(MT8195, path->config, num_components);
158
159 /* Decide which mutex to use based on the current pipeline */
160 index = __get_pipe(path->mdp_dev, path->comps[0].comp->public_id);
161 memcpy(p, &data->pipe_info[index], sizeof(struct mdp_pipe_info));
162 mutex = __get_mutex(path->mdp_dev, p);
163
164 /* Set mutex mod */
165 for (index = 0; index < num_comp; index++) {
166 s32 inner_id = MDP_COMP_NONE;
167 const u32 *mutex_idx;
168 const struct mdp_comp_blend *b;
169
170 if (CFG_CHECK(MT8183, p_id))
171 inner_id = CFG_GET(MT8183, path->config, components[index].type);
172 else if (CFG_CHECK(MT8195, p_id))
173 inner_id = CFG_GET(MT8195, path->config, components[index].type);
174
175 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
176 continue;
177
178 ctx = &path->comps[index];
179 if (is_output_disabled(p_id, ctx->param, count))
180 continue;
181
182 mutex_idx = data->mdp_mutex_table_idx;
183 id = ctx->comp->public_id;
184 mtk_mutex_write_mod(mutex, mutex_idx[id], false);
185
186 b = &data->comp_data[id].blend;
187 if (b && b->aid_mod)
188 mtk_mutex_write_mod(mutex, mutex_idx[b->b_id], false);
189 }
190
191 mtk_mutex_write_sof(mutex, MUTEX_SOF_IDX_SINGLE_MODE);
192
193 return 0;
194 }
195
mdp_path_subfrm_run(const struct mdp_path * path,struct mdp_cmdq_cmd * cmd,struct mdp_pipe_info * p,u32 count)196 static int mdp_path_subfrm_run(const struct mdp_path *path,
197 struct mdp_cmdq_cmd *cmd,
198 struct mdp_pipe_info *p, u32 count)
199 {
200 const int p_id = path->mdp_dev->mdp_data->mdp_plat_id;
201 const struct mdp_comp_ctx *ctx;
202 struct device *dev = &path->mdp_dev->pdev->dev;
203 struct mtk_mutex *mutex;
204 int index;
205 u32 num_comp = 0;
206 s32 event;
207 s32 inner_id = MDP_COMP_NONE;
208
209 if (-1 == p->mutex_id) {
210 dev_err(dev, "Incorrect mutex id");
211 return -EINVAL;
212 }
213
214 if (CFG_CHECK(MT8183, p_id))
215 num_comp = CFG_GET(MT8183, path->config, num_components);
216 else if (CFG_CHECK(MT8195, p_id))
217 num_comp = CFG_GET(MT8195, path->config, num_components);
218
219 /* Wait WROT SRAM shared to DISP RDMA */
220 /* Clear SOF event for each engine */
221 for (index = 0; index < num_comp; index++) {
222 if (CFG_CHECK(MT8183, p_id))
223 inner_id = CFG_GET(MT8183, path->config, components[index].type);
224 else if (CFG_CHECK(MT8195, p_id))
225 inner_id = CFG_GET(MT8195, path->config, components[index].type);
226
227 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
228 continue;
229 ctx = &path->comps[index];
230 if (is_output_disabled(p_id, ctx->param, count))
231 continue;
232 event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF];
233 if (event != MDP_GCE_NO_EVENT)
234 MM_REG_CLEAR(cmd, event);
235 }
236
237 /* Enable the mutex */
238 mutex = __get_mutex(path->mdp_dev, p);
239 mtk_mutex_enable_by_cmdq(mutex, (void *)&cmd->pkt);
240
241 /* Wait SOF events and clear mutex modules (optional) */
242 for (index = 0; index < num_comp; index++) {
243 if (CFG_CHECK(MT8183, p_id))
244 inner_id = CFG_GET(MT8183, path->config, components[index].type);
245 else if (CFG_CHECK(MT8195, p_id))
246 inner_id = CFG_GET(MT8195, path->config, components[index].type);
247
248 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
249 continue;
250 ctx = &path->comps[index];
251 if (is_output_disabled(p_id, ctx->param, count))
252 continue;
253 event = ctx->comp->gce_event[MDP_GCE_EVENT_SOF];
254 if (event != MDP_GCE_NO_EVENT)
255 MM_REG_WAIT(cmd, event);
256 }
257
258 return 0;
259 }
260
mdp_path_ctx_init(struct mdp_dev * mdp,struct mdp_path * path)261 static int mdp_path_ctx_init(struct mdp_dev *mdp, struct mdp_path *path)
262 {
263 const int p_id = mdp->mdp_data->mdp_plat_id;
264 void *param = NULL;
265 int index, ret;
266 u32 num_comp = 0;
267
268 if (CFG_CHECK(MT8183, p_id))
269 num_comp = CFG_GET(MT8183, path->config, num_components);
270 else if (CFG_CHECK(MT8195, p_id))
271 num_comp = CFG_GET(MT8195, path->config, num_components);
272
273 if (num_comp < 1)
274 return -EINVAL;
275
276 for (index = 0; index < num_comp; index++) {
277 s32 inner_id = MDP_COMP_NONE;
278
279 if (CFG_CHECK(MT8183, p_id))
280 inner_id = CFG_GET(MT8183, path->config, components[index].type);
281 else if (CFG_CHECK(MT8195, p_id))
282 inner_id = CFG_GET(MT8195, path->config, components[index].type);
283
284 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
285 continue;
286 if (CFG_CHECK(MT8183, p_id))
287 param = (void *)CFG_ADDR(MT8183, path->config, components[index]);
288 else if (CFG_CHECK(MT8195, p_id))
289 param = (void *)CFG_ADDR(MT8195, path->config, components[index]);
290 ret = mdp_comp_ctx_config(mdp, &path->comps[index],
291 param, path->param);
292 if (ret)
293 return ret;
294 }
295
296 return 0;
297 }
298
mdp_path_config_subfrm(struct mdp_cmdq_cmd * cmd,struct mdp_path * path,u32 count)299 static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
300 struct mdp_path *path, u32 count)
301 {
302 const int p_id = path->mdp_dev->mdp_data->mdp_plat_id;
303 const struct img_mmsys_ctrl *ctrl = NULL;
304 const struct img_mux *set;
305 struct mdp_comp_ctx *ctx;
306 struct mdp_pipe_info pipe;
307 int index, ret;
308 u32 num_comp = 0;
309 s32 inner_id = MDP_COMP_NONE;
310
311 if (CFG_CHECK(MT8183, p_id))
312 num_comp = CFG_GET(MT8183, path->config, num_components);
313 else if (CFG_CHECK(MT8195, p_id))
314 num_comp = CFG_GET(MT8195, path->config, num_components);
315
316 if (CFG_CHECK(MT8183, p_id))
317 ctrl = CFG_ADDR(MT8183, path->config, ctrls[count]);
318 else if (CFG_CHECK(MT8195, p_id))
319 ctrl = CFG_ADDR(MT8195, path->config, ctrls[count]);
320
321 /* Acquire components */
322 ret = mdp_path_subfrm_require(path, cmd, &pipe, count);
323 if (ret)
324 return ret;
325 /* Enable mux settings */
326 for (index = 0; index < ctrl->num_sets; index++) {
327 set = &ctrl->sets[index];
328 cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg,
329 set->value, 0xFFFFFFFF);
330 }
331 /* Config sub-frame information */
332 for (index = (num_comp - 1); index >= 0; index--) {
333 if (CFG_CHECK(MT8183, p_id))
334 inner_id = CFG_GET(MT8183, path->config, components[index].type);
335 else if (CFG_CHECK(MT8195, p_id))
336 inner_id = CFG_GET(MT8195, path->config, components[index].type);
337
338 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
339 continue;
340 ctx = &path->comps[index];
341 if (is_output_disabled(p_id, ctx->param, count))
342 continue;
343 ret = call_op(ctx, config_subfrm, cmd, count);
344 if (ret)
345 return ret;
346 }
347 /* Run components */
348 ret = mdp_path_subfrm_run(path, cmd, &pipe, count);
349 if (ret)
350 return ret;
351 /* Wait components done */
352 for (index = 0; index < num_comp; index++) {
353 if (CFG_CHECK(MT8183, p_id))
354 inner_id = CFG_GET(MT8183, path->config, components[index].type);
355 else if (CFG_CHECK(MT8195, p_id))
356 inner_id = CFG_GET(MT8195, path->config, components[index].type);
357
358 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
359 continue;
360 ctx = &path->comps[index];
361 if (is_output_disabled(p_id, ctx->param, count))
362 continue;
363 ret = call_op(ctx, wait_comp_event, cmd);
364 if (ret)
365 return ret;
366 }
367 /* Advance to the next sub-frame */
368 for (index = 0; index < num_comp; index++) {
369 if (CFG_CHECK(MT8183, p_id))
370 inner_id = CFG_GET(MT8183, path->config, components[index].type);
371 else if (CFG_CHECK(MT8195, p_id))
372 inner_id = CFG_GET(MT8195, path->config, components[index].type);
373
374 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
375 continue;
376 ctx = &path->comps[index];
377 ret = call_op(ctx, advance_subfrm, cmd, count);
378 if (ret)
379 return ret;
380 }
381 /* Disable mux settings */
382 for (index = 0; index < ctrl->num_sets; index++) {
383 set = &ctrl->sets[index];
384 cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg,
385 0, 0xFFFFFFFF);
386 }
387
388 return 0;
389 }
390
mdp_path_config(struct mdp_dev * mdp,struct mdp_cmdq_cmd * cmd,struct mdp_path * path)391 static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmdq_cmd *cmd,
392 struct mdp_path *path)
393 {
394 const int p_id = mdp->mdp_data->mdp_plat_id;
395 struct mdp_comp_ctx *ctx;
396 int index, count, ret;
397 u32 num_comp = 0;
398 u32 num_sub = 0;
399 s32 inner_id = MDP_COMP_NONE;
400
401 if (CFG_CHECK(MT8183, p_id))
402 num_comp = CFG_GET(MT8183, path->config, num_components);
403 else if (CFG_CHECK(MT8195, p_id))
404 num_comp = CFG_GET(MT8195, path->config, num_components);
405
406 if (CFG_CHECK(MT8183, p_id))
407 num_sub = CFG_GET(MT8183, path->config, num_subfrms);
408 else if (CFG_CHECK(MT8195, p_id))
409 num_sub = CFG_GET(MT8195, path->config, num_subfrms);
410
411 /* Config path frame */
412 /* Reset components */
413 for (index = 0; index < num_comp; index++) {
414 if (CFG_CHECK(MT8183, p_id))
415 inner_id = CFG_GET(MT8183, path->config, components[index].type);
416 else if (CFG_CHECK(MT8195, p_id))
417 inner_id = CFG_GET(MT8195, path->config, components[index].type);
418
419 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
420 continue;
421 ctx = &path->comps[index];
422 ret = call_op(ctx, init_comp, cmd);
423 if (ret)
424 return ret;
425 }
426 /* Config frame mode */
427 for (index = 0; index < num_comp; index++) {
428 const struct v4l2_rect *compose;
429 u32 out = 0;
430
431 ctx = &path->comps[index];
432 if (CFG_CHECK(MT8183, p_id))
433 inner_id = CFG_GET(MT8183, path->config, components[index].type);
434 else if (CFG_CHECK(MT8195, p_id))
435 inner_id = CFG_GET(MT8195, path->config, components[index].type);
436
437 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
438 continue;
439
440 if (CFG_CHECK(MT8183, p_id))
441 out = CFG_COMP(MT8183, ctx->param, outputs[0]);
442 else if (CFG_CHECK(MT8195, p_id))
443 out = CFG_COMP(MT8195, ctx->param, outputs[0]);
444
445 compose = path->composes[out];
446 ret = call_op(ctx, config_frame, cmd, compose);
447 if (ret)
448 return ret;
449 }
450
451 /* Config path sub-frames */
452 for (count = 0; count < num_sub; count++) {
453 ret = mdp_path_config_subfrm(cmd, path, count);
454 if (ret)
455 return ret;
456 }
457 /* Post processing information */
458 for (index = 0; index < num_comp; index++) {
459 if (CFG_CHECK(MT8183, p_id))
460 inner_id = CFG_GET(MT8183, path->config, components[index].type);
461 else if (CFG_CHECK(MT8195, p_id))
462 inner_id = CFG_GET(MT8195, path->config, components[index].type);
463
464 if (mdp_cfg_comp_is_dummy(path->mdp_dev, inner_id))
465 continue;
466 ctx = &path->comps[index];
467 ret = call_op(ctx, post_process, cmd);
468 if (ret)
469 return ret;
470 }
471 return 0;
472 }
473
mdp_cmdq_pkt_create(struct cmdq_client * client,struct cmdq_pkt * pkt,size_t size)474 static int mdp_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
475 size_t size)
476 {
477 struct device *dev;
478 dma_addr_t dma_addr;
479
480 pkt->va_base = kzalloc(size, GFP_KERNEL);
481 if (!pkt->va_base)
482 return -ENOMEM;
483
484 pkt->buf_size = size;
485 pkt->cl = (void *)client;
486
487 dev = client->chan->mbox->dev;
488 dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
489 DMA_TO_DEVICE);
490 if (dma_mapping_error(dev, dma_addr)) {
491 dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
492 kfree(pkt->va_base);
493 return -ENOMEM;
494 }
495
496 pkt->pa_base = dma_addr;
497
498 return 0;
499 }
500
mdp_cmdq_pkt_destroy(struct cmdq_pkt * pkt)501 static void mdp_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
502 {
503 struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
504
505 dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
506 DMA_TO_DEVICE);
507 kfree(pkt->va_base);
508 pkt->va_base = NULL;
509 }
510
mdp_auto_release_work(struct work_struct * work)511 static void mdp_auto_release_work(struct work_struct *work)
512 {
513 struct mdp_cmdq_cmd *cmd;
514 struct mdp_dev *mdp;
515 struct mtk_mutex *mutex;
516 enum mdp_pipe_id pipe_id;
517
518 cmd = container_of(work, struct mdp_cmdq_cmd, auto_release_work);
519 mdp = cmd->mdp;
520
521 pipe_id = __get_pipe(mdp, cmd->comps[0].public_id);
522 mutex = __get_mutex(mdp, &mdp->mdp_data->pipe_info[pipe_id]);
523 mtk_mutex_unprepare(mutex);
524 mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
525 cmd->num_comps);
526
527 if (refcount_dec_and_test(&mdp->job_count)) {
528 if (cmd->mdp_ctx)
529 mdp_m2m_job_finish(cmd->mdp_ctx);
530
531 if (cmd->user_cmdq_cb) {
532 struct cmdq_cb_data user_cb_data;
533
534 user_cb_data.sta = cmd->data->sta;
535 user_cb_data.pkt = cmd->data->pkt;
536 cmd->user_cmdq_cb(user_cb_data);
537 }
538 wake_up(&mdp->callback_wq);
539 }
540
541 mdp_cmdq_pkt_destroy(&cmd->pkt);
542 kfree(cmd->comps);
543 cmd->comps = NULL;
544 kfree(cmd);
545 cmd = NULL;
546 }
547
mdp_handle_cmdq_callback(struct mbox_client * cl,void * mssg)548 static void mdp_handle_cmdq_callback(struct mbox_client *cl, void *mssg)
549 {
550 struct mdp_cmdq_cmd *cmd;
551 struct cmdq_cb_data *data;
552 struct mdp_dev *mdp;
553 struct device *dev;
554 enum mdp_pipe_id pipe_id;
555
556 if (!mssg) {
557 pr_info("%s:no callback data\n", __func__);
558 return;
559 }
560
561 data = (struct cmdq_cb_data *)mssg;
562 cmd = container_of(data->pkt, struct mdp_cmdq_cmd, pkt);
563 cmd->data = data;
564 mdp = cmd->mdp;
565 dev = &mdp->pdev->dev;
566
567 INIT_WORK(&cmd->auto_release_work, mdp_auto_release_work);
568 if (!queue_work(mdp->clock_wq, &cmd->auto_release_work)) {
569 struct mtk_mutex *mutex;
570
571 dev_err(dev, "%s:queue_work fail!\n", __func__);
572 pipe_id = __get_pipe(mdp, cmd->comps[0].public_id);
573 mutex = __get_mutex(mdp, &mdp->mdp_data->pipe_info[pipe_id]);
574 mtk_mutex_unprepare(mutex);
575 mdp_comp_clocks_off(&mdp->pdev->dev, cmd->comps,
576 cmd->num_comps);
577
578 if (refcount_dec_and_test(&mdp->job_count))
579 wake_up(&mdp->callback_wq);
580
581 mdp_cmdq_pkt_destroy(&cmd->pkt);
582 kfree(cmd->comps);
583 cmd->comps = NULL;
584 kfree(cmd);
585 cmd = NULL;
586 }
587 }
588
mdp_cmdq_prepare(struct mdp_dev * mdp,struct mdp_cmdq_param * param,u8 pp_idx)589 static struct mdp_cmdq_cmd *mdp_cmdq_prepare(struct mdp_dev *mdp,
590 struct mdp_cmdq_param *param,
591 u8 pp_idx)
592 {
593 struct mdp_path *path = NULL;
594 struct mdp_cmdq_cmd *cmd = NULL;
595 struct mdp_comp *comps = NULL;
596 struct device *dev = &mdp->pdev->dev;
597 const int p_id = mdp->mdp_data->mdp_plat_id;
598 struct img_config *config;
599 struct mtk_mutex *mutex = NULL;
600 enum mdp_pipe_id pipe_id;
601 int i, ret = -ECANCELED;
602 u32 num_comp;
603
604 config = __get_config_offset(mdp, param, pp_idx);
605 if (IS_ERR(config)) {
606 ret = PTR_ERR(config);
607 goto err_uninit;
608 }
609
610 if (CFG_CHECK(MT8183, p_id))
611 num_comp = CFG_GET(MT8183, config, num_components);
612 else if (CFG_CHECK(MT8195, p_id))
613 num_comp = CFG_GET(MT8195, config, num_components);
614 else
615 goto err_uninit;
616
617 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
618 if (!cmd) {
619 ret = -ENOMEM;
620 goto err_uninit;
621 }
622
623 ret = mdp_cmdq_pkt_create(mdp->cmdq_clt[pp_idx], &cmd->pkt, SZ_16K);
624 if (ret)
625 goto err_free_cmd;
626
627 if (CFG_CHECK(MT8183, p_id)) {
628 num_comp = CFG_GET(MT8183, param->config, num_components);
629 } else if (CFG_CHECK(MT8195, p_id)) {
630 num_comp = CFG_GET(MT8195, param->config, num_components);
631 } else {
632 ret = -EINVAL;
633 goto err_destroy_pkt;
634 }
635 comps = kcalloc(num_comp, sizeof(*comps), GFP_KERNEL);
636 if (!comps) {
637 ret = -ENOMEM;
638 goto err_destroy_pkt;
639 }
640
641 path = kzalloc(sizeof(*path), GFP_KERNEL);
642 if (!path) {
643 ret = -ENOMEM;
644 goto err_free_comps;
645 }
646
647 path->mdp_dev = mdp;
648 path->config = config;
649 path->param = param->param;
650 for (i = 0; i < param->param->num_outputs; i++) {
651 path->bounds[i].left = 0;
652 path->bounds[i].top = 0;
653 path->bounds[i].width =
654 param->param->outputs[i].buffer.format.width;
655 path->bounds[i].height =
656 param->param->outputs[i].buffer.format.height;
657 path->composes[i] = param->composes[i] ?
658 param->composes[i] : &path->bounds[i];
659 }
660 ret = mdp_path_ctx_init(mdp, path);
661 if (ret) {
662 dev_err(dev, "mdp_path_ctx_init error %d\n", pp_idx);
663 goto err_free_path;
664 }
665
666 pipe_id = __get_pipe(mdp, path->comps[0].comp->public_id);
667 mutex = __get_mutex(mdp, &mdp->mdp_data->pipe_info[pipe_id]);
668 ret = mtk_mutex_prepare(mutex);
669 if (ret) {
670 dev_err(dev, "Fail to enable mutex %d clk\n", pp_idx);
671 goto err_free_path;
672 }
673
674 ret = mdp_path_config(mdp, cmd, path);
675 if (ret) {
676 dev_err(dev, "mdp_path_config error %d\n", pp_idx);
677 goto err_free_path;
678 }
679 cmdq_pkt_finalize(&cmd->pkt);
680
681 for (i = 0; i < num_comp; i++) {
682 s32 inner_id = MDP_COMP_NONE;
683
684 if (CFG_CHECK(MT8183, p_id))
685 inner_id = CFG_GET(MT8183, path->config, components[i].type);
686 else if (CFG_CHECK(MT8195, p_id))
687 inner_id = CFG_GET(MT8195, path->config, components[i].type);
688
689 if (mdp_cfg_comp_is_dummy(mdp, inner_id))
690 continue;
691 memcpy(&comps[i], path->comps[i].comp,
692 sizeof(struct mdp_comp));
693 }
694
695 mdp->cmdq_clt[pp_idx]->client.rx_callback = mdp_handle_cmdq_callback;
696 cmd->mdp = mdp;
697 cmd->user_cmdq_cb = param->cmdq_cb;
698 cmd->user_cb_data = param->cb_data;
699 cmd->comps = comps;
700 cmd->num_comps = num_comp;
701 cmd->mdp_ctx = param->mdp_ctx;
702
703 kfree(path);
704 return cmd;
705
706 err_free_path:
707 if (mutex)
708 mtk_mutex_unprepare(mutex);
709 kfree(path);
710 err_free_comps:
711 kfree(comps);
712 err_destroy_pkt:
713 mdp_cmdq_pkt_destroy(&cmd->pkt);
714 err_free_cmd:
715 kfree(cmd);
716 err_uninit:
717 return ERR_PTR(ret);
718 }
719
mdp_cmdq_send(struct mdp_dev * mdp,struct mdp_cmdq_param * param)720 int mdp_cmdq_send(struct mdp_dev *mdp, struct mdp_cmdq_param *param)
721 {
722 struct mdp_cmdq_cmd *cmd[MDP_PP_MAX] = {NULL};
723 struct device *dev = &mdp->pdev->dev;
724 int i, ret;
725 u8 pp_used = __get_pp_num(param->param->type);
726
727 refcount_set(&mdp->job_count, pp_used);
728 if (atomic_read(&mdp->suspended)) {
729 refcount_set(&mdp->job_count, 0);
730 return -ECANCELED;
731 }
732
733 for (i = 0; i < pp_used; i++) {
734 cmd[i] = mdp_cmdq_prepare(mdp, param, i);
735 if (IS_ERR_OR_NULL(cmd[i])) {
736 ret = PTR_ERR(cmd[i]);
737 goto err_cancel_job;
738 }
739 }
740
741 for (i = 0; i < pp_used; i++) {
742 ret = mdp_comp_clocks_on(&mdp->pdev->dev, cmd[i]->comps, cmd[i]->num_comps);
743 if (ret)
744 goto err_clock_off;
745 }
746
747 for (i = 0; i < pp_used; i++) {
748 dma_sync_single_for_device(mdp->cmdq_clt[i]->chan->mbox->dev,
749 cmd[i]->pkt.pa_base, cmd[i]->pkt.cmd_buf_size,
750 DMA_TO_DEVICE);
751
752 ret = mbox_send_message(mdp->cmdq_clt[i]->chan, &cmd[i]->pkt);
753 if (ret < 0) {
754 dev_err(dev, "mbox send message fail %d!\n", ret);
755 i = pp_used;
756 goto err_clock_off;
757 }
758 mbox_client_txdone(mdp->cmdq_clt[i]->chan, 0);
759 }
760 return 0;
761
762 err_clock_off:
763 while (--i >= 0)
764 mdp_comp_clocks_off(&mdp->pdev->dev, cmd[i]->comps,
765 cmd[i]->num_comps);
766 err_cancel_job:
767 refcount_set(&mdp->job_count, 0);
768
769 return ret;
770 }
771 EXPORT_SYMBOL_GPL(mdp_cmdq_send);
772