1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-09-26 19:04:54 +00:00
Files
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

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");