772 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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_COMPONENTS17 18struct 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 33static 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 52static 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 58static 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 68static 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 105static 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 else122 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 else129 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 138err_param:139 cfg_c = ERR_PTR(-EINVAL);140 return (struct img_config *)cfg_c;141}142 143static 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 196static 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 261static 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 299static 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 391static 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 474static 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 501static 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 511static 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 548static 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 589static 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 else615 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 706err_free_path:707 if (mutex)708 mtk_mutex_unprepare(mutex);709 kfree(path);710err_free_comps:711 kfree(comps);712err_destroy_pkt:713 mdp_cmdq_pkt_destroy(&cmd->pkt);714err_free_cmd:715 kfree(cmd);716err_uninit:717 return ERR_PTR(ret);718}719 720int 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 762err_clock_off:763 while (--i >= 0)764 mdp_comp_clocks_off(&mdp->pdev->dev, cmd[i]->comps,765 cmd[i]->num_comps);766err_cancel_job:767 refcount_set(&mdp->job_count, 0);768 769 return ret;770}771EXPORT_SYMBOL_GPL(mdp_cmdq_send);772