mirror of
https://github.com/physwizz/a155-U-u1.git
synced 2025-09-26 19:04:54 +00:00
311 lines
7.3 KiB
C
311 lines
7.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2021 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/component.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
#include "mtk-mml-core.h"
|
|
#include "mtk-mml-driver.h"
|
|
|
|
#include "tile_driver.h"
|
|
|
|
#define TCC_CTRL 0x000
|
|
#define TCC_DEBUG 0x520
|
|
#define TCC_INTEN 0x524
|
|
#define TCC_INTST 0x528
|
|
#define TCC_ST 0x52C
|
|
#define TCC_CROP_X 0x530
|
|
#define TCC_CROP_Y 0x534
|
|
|
|
struct tcc_data {
|
|
};
|
|
|
|
static const struct tcc_data mt6893_tcc_data = {
|
|
};
|
|
|
|
struct mml_comp_tcc {
|
|
struct mml_comp comp;
|
|
const struct tcc_data *data;
|
|
};
|
|
|
|
/* meta data for each different frame config */
|
|
struct tcc_frame_data {
|
|
u8 out_idx;
|
|
};
|
|
|
|
#define tcc_frm_data(i) ((struct tcc_frame_data *)(i->data))
|
|
|
|
static s32 tcc_prepare(struct mml_comp *comp, struct mml_task *task,
|
|
struct mml_comp_config *ccfg)
|
|
{
|
|
struct tcc_frame_data *tcc_frm;
|
|
|
|
tcc_frm = kzalloc(sizeof(*tcc_frm), GFP_KERNEL);
|
|
ccfg->data = tcc_frm;
|
|
/* cache out index for easy use */
|
|
tcc_frm->out_idx = ccfg->node->out_idx;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static s32 tcc_tile_prepare(struct mml_comp *comp, struct mml_task *task,
|
|
struct mml_comp_config *ccfg,
|
|
struct tile_func_block *func,
|
|
union mml_tile_data *data)
|
|
{
|
|
struct tcc_frame_data *tcc_frm = tcc_frm_data(ccfg);
|
|
struct mml_frame_config *cfg = task->config;
|
|
struct mml_frame_dest *dest = &cfg->info.dest[tcc_frm->out_idx];
|
|
|
|
func->enable_flag = true;
|
|
|
|
if (dest->rotate == MML_ROT_90 ||
|
|
dest->rotate == MML_ROT_270) {
|
|
func->full_size_x_in = dest->data.height;
|
|
func->full_size_y_in = dest->data.width;
|
|
func->full_size_x_out = dest->data.height;
|
|
func->full_size_y_out = dest->data.width;
|
|
} else {
|
|
func->full_size_x_in = dest->data.width;
|
|
func->full_size_y_in = dest->data.height;
|
|
func->full_size_x_out = dest->data.width;
|
|
func->full_size_y_out = dest->data.height;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct mml_comp_tile_ops tcc_tile_ops = {
|
|
.prepare = tcc_tile_prepare,
|
|
};
|
|
|
|
static s32 tcc_init(struct mml_comp *comp, struct mml_task *task,
|
|
struct mml_comp_config *ccfg)
|
|
{
|
|
struct cmdq_pkt *pkt = task->pkts[ccfg->pipe];
|
|
const phys_addr_t base_pa = comp->base_pa;
|
|
|
|
cmdq_pkt_write(pkt, NULL, base_pa + TCC_CTRL, 1, 0x00000001);
|
|
return 0;
|
|
}
|
|
|
|
static s32 tcc_config_frame(struct mml_comp *comp, struct mml_task *task,
|
|
struct mml_comp_config *ccfg)
|
|
{
|
|
struct cmdq_pkt *pkt = task->pkts[ccfg->pipe];
|
|
const phys_addr_t base_pa = comp->base_pa;
|
|
|
|
/* relay mode */
|
|
cmdq_pkt_write(pkt, NULL, base_pa + TCC_CTRL, 1 << 29, 0x20000000);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static s32 tcc_config_tile(struct mml_comp *comp, struct mml_task *task,
|
|
struct mml_comp_config *ccfg, u32 idx)
|
|
{
|
|
struct mml_frame_config *cfg = task->config;
|
|
struct cmdq_pkt *pkt = task->pkts[ccfg->pipe];
|
|
const phys_addr_t base_pa = comp->base_pa;
|
|
|
|
struct mml_tile_engine *tile = config_get_tile(cfg, ccfg, idx);
|
|
|
|
u32 width = tile->in.xe - tile->in.xs + 1;
|
|
u32 height = tile->in.ye - tile->in.ys + 1;
|
|
|
|
cmdq_pkt_write(pkt, NULL, base_pa + TCC_CTRL,
|
|
((height & 0x3fff) << 15) + ((width & 0x3fff) << 1),
|
|
0x1ffffffe);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct mml_comp_config_ops tcc_cfg_ops = {
|
|
.prepare = tcc_prepare,
|
|
.init = tcc_init,
|
|
.frame = tcc_config_frame,
|
|
.tile = tcc_config_tile,
|
|
};
|
|
|
|
static void tcc_debug_dump(struct mml_comp *comp)
|
|
{
|
|
void __iomem *base = comp->base;
|
|
u32 value[7];
|
|
|
|
mml_err("tcc component %u dump:", comp->id);
|
|
|
|
value[0] = readl(base + TCC_CTRL);
|
|
value[1] = readl(base + TCC_DEBUG);
|
|
value[2] = readl(base + TCC_INTEN);
|
|
value[3] = readl(base + TCC_INTST);
|
|
value[4] = readl(base + TCC_ST);
|
|
value[5] = readl(base + TCC_CROP_X);
|
|
value[6] = readl(base + TCC_CROP_Y);
|
|
|
|
mml_err("TCC_CTRL %#010x TCC_DEBUG %#010x TCC_INTEN %#010x TCC_INTST %#010x",
|
|
value[0], value[1], value[2], value[3]);
|
|
mml_err("TCC_ST %#010x TCC_CROP_X %#010x TCC_CROP_Y %#010x",
|
|
value[4], value[5], value[6]);
|
|
}
|
|
|
|
static const struct mml_comp_debug_ops tcc_debug_ops = {
|
|
.dump = &tcc_debug_dump,
|
|
};
|
|
|
|
static int mml_bind(struct device *dev, struct device *master, void *data)
|
|
{
|
|
struct mml_comp_tcc *tcc = dev_get_drvdata(dev);
|
|
s32 ret;
|
|
|
|
ret = mml_register_comp(master, &tcc->comp);
|
|
if (ret)
|
|
dev_err(dev, "Failed to register mml component %s: %d\n",
|
|
dev->of_node->full_name, ret);
|
|
return ret;
|
|
}
|
|
|
|
static void mml_unbind(struct device *dev, struct device *master, void *data)
|
|
{
|
|
struct mml_comp_tcc *tcc = dev_get_drvdata(dev);
|
|
|
|
mml_unregister_comp(master, &tcc->comp);
|
|
}
|
|
|
|
static const struct component_ops mml_comp_ops = {
|
|
.bind = mml_bind,
|
|
.unbind = mml_unbind,
|
|
};
|
|
|
|
static struct mml_comp_tcc *dbg_probed_components[4];
|
|
static int dbg_probed_count;
|
|
|
|
static int probe(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
struct mml_comp_tcc *priv;
|
|
s32 ret;
|
|
|
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
|
if (!priv)
|
|
return -ENOMEM;
|
|
|
|
platform_set_drvdata(pdev, priv);
|
|
priv->data = of_device_get_match_data(dev);
|
|
|
|
ret = mml_comp_init(pdev, &priv->comp);
|
|
if (ret) {
|
|
dev_err(dev, "Failed to init mml component: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
/* assign ops */
|
|
priv->comp.tile_ops = &tcc_tile_ops;
|
|
priv->comp.config_ops = &tcc_cfg_ops;
|
|
priv->comp.debug_ops = &tcc_debug_ops;
|
|
|
|
if (unlikely(dbg_probed_count < 0))
|
|
return -EFAULT;
|
|
|
|
dbg_probed_components[dbg_probed_count++] = priv;
|
|
|
|
ret = component_add(dev, &mml_comp_ops);
|
|
if (ret)
|
|
dev_err(dev, "Failed to add component: %d\n", ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int remove(struct platform_device *pdev)
|
|
{
|
|
component_del(&pdev->dev, &mml_comp_ops);
|
|
return 0;
|
|
}
|
|
|
|
const struct of_device_id mml_tcc_driver_dt_match[] = {
|
|
{
|
|
.compatible = "mediatek,mt6893-mml_tcc",
|
|
.data = &mt6893_tcc_data
|
|
},
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, mml_tcc_driver_dt_match);
|
|
|
|
struct platform_driver mml_tcc_driver = {
|
|
.probe = probe,
|
|
.remove = remove,
|
|
.driver = {
|
|
.name = "mediatek-mml-tcc",
|
|
.owner = THIS_MODULE,
|
|
.of_match_table = mml_tcc_driver_dt_match,
|
|
},
|
|
};
|
|
|
|
//module_platform_driver(mml_tcc_driver);
|
|
|
|
static s32 ut_case;
|
|
static s32 ut_set(const char *val, const struct kernel_param *kp)
|
|
{
|
|
s32 result;
|
|
|
|
result = sscanf(val, "%d", &ut_case);
|
|
if (result != 1) {
|
|
mml_err("invalid input: %s, result(%d)", val, result);
|
|
return -EINVAL;
|
|
}
|
|
mml_log("%s: case_id=%d", __func__, ut_case);
|
|
|
|
switch (ut_case) {
|
|
case 0:
|
|
mml_log("use read to dump current pwm setting");
|
|
break;
|
|
default:
|
|
mml_err("invalid case_id: %d", ut_case);
|
|
break;
|
|
}
|
|
|
|
mml_log("%s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
static s32 ut_get(char *buf, const struct kernel_param *kp)
|
|
{
|
|
s32 length = 0;
|
|
u32 i;
|
|
|
|
switch (ut_case) {
|
|
case 0:
|
|
length += snprintf(buf + length, PAGE_SIZE - length,
|
|
"[%d] probed count: %d\n", ut_case, dbg_probed_count);
|
|
for(i = 0; i < dbg_probed_count; i++) {
|
|
length += snprintf(buf + length, PAGE_SIZE - length,
|
|
" - [%d] mml_comp_id: %d\n", i,
|
|
dbg_probed_components[i]->comp.id);
|
|
length += snprintf(buf + length, PAGE_SIZE - length,
|
|
" - mml_bound: %d\n",
|
|
dbg_probed_components[i]->comp.bound);
|
|
}
|
|
break;
|
|
default:
|
|
mml_err("not support read for case_id: %d", ut_case);
|
|
break;
|
|
}
|
|
buf[length] = '\0';
|
|
|
|
return length;
|
|
}
|
|
|
|
static struct kernel_param_ops up_param_ops = {
|
|
.set = ut_set,
|
|
.get = ut_get,
|
|
};
|
|
module_param_cb(tcc_ut_case, &up_param_ops, NULL, 0644);
|
|
MODULE_PARM_DESC(tcc_ut_case, "mml tcc UT test case");
|
|
|
|
MODULE_AUTHOR("Dennis-YC Hsieh <dennis-yc.hsieh@mediatek.com>");
|
|
MODULE_DESCRIPTION("MediaTek SoC display MML TCC driver");
|
|
MODULE_LICENSE("GPL v2");
|