summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c')
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c142
1 files changed, 115 insertions, 27 deletions
diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
index 94f4ed785..5209f531e 100644
--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
+++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c
@@ -21,14 +21,21 @@ static const struct of_device_id mdp_of_ids[] = {
{ .compatible = "mediatek,mt8183-mdp3-rdma",
.data = &mt8183_mdp_driver_data,
},
+ { .compatible = "mediatek,mt8195-mdp3-rdma",
+ .data = &mt8195_mdp_driver_data,
+ },
+ { .compatible = "mediatek,mt8195-mdp3-wrot",
+ .data = &mt8195_mdp_driver_data,
+ },
{},
};
MODULE_DEVICE_TABLE(of, mdp_of_ids);
static struct platform_device *__get_pdev_by_id(struct platform_device *pdev,
+ struct platform_device *from,
enum mdp_infra_id id)
{
- struct device_node *node;
+ struct device_node *node, *f = NULL;
struct platform_device *mdp_pdev = NULL;
const struct mtk_mdp_driver_data *mdp_data;
const char *compat;
@@ -46,9 +53,14 @@ static struct platform_device *__get_pdev_by_id(struct platform_device *pdev,
dev_err(&pdev->dev, "have no driver data to find node\n");
return NULL;
}
+
compat = mdp_data->mdp_probe_infra[id].compatible;
+ if (strlen(compat) == 0)
+ return NULL;
- node = of_find_compatible_node(NULL, NULL, compat);
+ if (from)
+ f = from->dev.of_node;
+ node = of_find_compatible_node(f, NULL, compat);
if (WARN_ON(!node)) {
dev_err(&pdev->dev, "find node from id %d failed\n", id);
return NULL;
@@ -130,6 +142,10 @@ void mdp_video_device_release(struct video_device *vdev)
struct mdp_dev *mdp = (struct mdp_dev *)video_get_drvdata(vdev);
int i;
+ for (i = 0; i < mdp->mdp_data->pp_used; i++)
+ if (mdp->cmdq_clt[i])
+ cmdq_mbox_destroy(mdp->cmdq_clt[i]);
+
scp_put(mdp->scp);
destroy_workqueue(mdp->job_wq);
@@ -140,19 +156,72 @@ void mdp_video_device_release(struct video_device *vdev)
vb2_dma_contig_clear_max_seg_size(&mdp->pdev->dev);
mdp_comp_destroy(mdp);
- for (i = 0; i < MDP_PIPE_MAX; i++)
- mtk_mutex_put(mdp->mdp_mutex[i]);
+ for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
+ enum mdp_mm_subsys_id idx;
+ struct mtk_mutex *m;
+ u32 m_id;
+
+ idx = mdp->mdp_data->pipe_info[i].sub_id;
+ m_id = mdp->mdp_data->pipe_info[i].mutex_id;
+ m = mdp->mm_subsys[idx].mdp_mutex[m_id];
+ if (!IS_ERR_OR_NULL(m))
+ mtk_mutex_put(m);
+ }
mdp_vpu_shared_mem_free(&mdp->vpu);
v4l2_m2m_release(mdp->m2m_dev);
kfree(mdp);
}
+static int mdp_mm_subsys_deploy(struct mdp_dev *mdp, enum mdp_infra_id id)
+{
+ struct platform_device *mm_pdev = NULL;
+ struct device **dev;
+ int i;
+
+ if (!mdp)
+ return -EINVAL;
+
+ for (i = 0; i < MDP_MM_SUBSYS_MAX; i++) {
+ const char *compat;
+ enum mdp_infra_id sub_id = id + i;
+
+ switch (id) {
+ case MDP_INFRA_MMSYS:
+ dev = &mdp->mm_subsys[i].mmsys;
+ break;
+ case MDP_INFRA_MUTEX:
+ dev = &mdp->mm_subsys[i].mutex;
+ break;
+ default:
+ dev_err(&mdp->pdev->dev, "Unknown infra id %d", id);
+ return -EINVAL;
+ }
+
+ /*
+ * Not every chip has multiple multimedia subsystems, so
+ * the config may be null.
+ */
+ compat = mdp->mdp_data->mdp_probe_infra[sub_id].compatible;
+ if (strlen(compat) == 0)
+ continue;
+
+ mm_pdev = __get_pdev_by_id(mdp->pdev, mm_pdev, sub_id);
+ if (WARN_ON(!mm_pdev))
+ return -ENODEV;
+
+ *dev = &mm_pdev->dev;
+ }
+
+ return 0;
+}
+
static int mdp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mdp_dev *mdp;
struct platform_device *mm_pdev;
+ struct resource *res;
int ret, i, mutex_id;
mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
@@ -164,25 +233,34 @@ static int mdp_probe(struct platform_device *pdev)
mdp->pdev = pdev;
mdp->mdp_data = of_device_get_match_data(&pdev->dev);
- mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_MMSYS);
- if (!mm_pdev) {
- ret = -ENODEV;
- goto err_destroy_device;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res->start != mdp->mdp_data->mdp_con_res) {
+ platform_set_drvdata(pdev, mdp);
+ goto success_return;
}
- mdp->mdp_mmsys = &mm_pdev->dev;
- mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_MUTEX);
- if (WARN_ON(!mm_pdev)) {
- ret = -ENODEV;
+ ret = mdp_mm_subsys_deploy(mdp, MDP_INFRA_MMSYS);
+ if (ret)
goto err_destroy_device;
- }
+
+ ret = mdp_mm_subsys_deploy(mdp, MDP_INFRA_MUTEX);
+ if (ret)
+ goto err_destroy_device;
+
for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
+ enum mdp_mm_subsys_id idx;
+ struct mtk_mutex **m;
+
+ idx = mdp->mdp_data->pipe_info[i].sub_id;
mutex_id = mdp->mdp_data->pipe_info[i].mutex_id;
- if (!IS_ERR_OR_NULL(mdp->mdp_mutex[mutex_id]))
+ m = &mdp->mm_subsys[idx].mdp_mutex[mutex_id];
+
+ if (!IS_ERR_OR_NULL(*m))
continue;
- mdp->mdp_mutex[mutex_id] = mtk_mutex_get(&mm_pdev->dev);
- if (IS_ERR(mdp->mdp_mutex[mutex_id])) {
- ret = PTR_ERR(mdp->mdp_mutex[mutex_id]);
+
+ *m = mtk_mutex_get(mdp->mm_subsys[idx].mutex);
+ if (IS_ERR(*m)) {
+ ret = PTR_ERR(*m);
goto err_free_mutex;
}
}
@@ -210,7 +288,7 @@ static int mdp_probe(struct platform_device *pdev)
mdp->scp = scp_get(pdev);
if (!mdp->scp) {
- mm_pdev = __get_pdev_by_id(pdev, MDP_INFRA_SCP);
+ mm_pdev = __get_pdev_by_id(pdev, NULL, MDP_INFRA_SCP);
if (WARN_ON(!mm_pdev)) {
dev_err(&pdev->dev, "Could not get scp device\n");
ret = -ENODEV;
@@ -225,10 +303,12 @@ static int mdp_probe(struct platform_device *pdev)
mutex_init(&mdp->vpu_lock);
mutex_init(&mdp->m2m_lock);
- mdp->cmdq_clt = cmdq_mbox_create(dev, 0);
- if (IS_ERR(mdp->cmdq_clt)) {
- ret = PTR_ERR(mdp->cmdq_clt);
- goto err_put_scp;
+ for (i = 0; i < mdp->mdp_data->pp_used; i++) {
+ mdp->cmdq_clt[i] = cmdq_mbox_create(dev, i);
+ if (IS_ERR(mdp->cmdq_clt[i])) {
+ ret = PTR_ERR(mdp->cmdq_clt[i]);
+ goto err_mbox_destroy;
+ }
}
init_waitqueue_head(&mdp->callback_wq);
@@ -250,14 +330,15 @@ static int mdp_probe(struct platform_device *pdev)
goto err_unregister_device;
}
+success_return:
dev_dbg(dev, "mdp-%d registered successfully\n", pdev->id);
return 0;
err_unregister_device:
v4l2_device_unregister(&mdp->v4l2_dev);
err_mbox_destroy:
- cmdq_mbox_destroy(mdp->cmdq_clt);
-err_put_scp:
+ while (--i >= 0)
+ cmdq_mbox_destroy(mdp->cmdq_clt[i]);
scp_put(mdp->scp);
err_destroy_clock_wq:
destroy_workqueue(mdp->clock_wq);
@@ -266,9 +347,16 @@ err_destroy_job_wq:
err_deinit_comp:
mdp_comp_destroy(mdp);
err_free_mutex:
- for (i = 0; i < mdp->mdp_data->pipe_info_len; i++)
- if (!IS_ERR_OR_NULL(mdp->mdp_mutex[i]))
- mtk_mutex_put(mdp->mdp_mutex[i]);
+ for (i = 0; i < mdp->mdp_data->pipe_info_len; i++) {
+ enum mdp_mm_subsys_id idx;
+ struct mtk_mutex *m;
+
+ idx = mdp->mdp_data->pipe_info[i].sub_id;
+ mutex_id = mdp->mdp_data->pipe_info[i].mutex_id;
+ m = mdp->mm_subsys[idx].mdp_mutex[mutex_id];
+ if (!IS_ERR_OR_NULL(m))
+ mtk_mutex_put(m);
+ }
err_destroy_device:
kfree(mdp);
err_return: