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

742 lines
20 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_drm_ddp_comp.h>
#include "mtk-mml-color.h"
#include "mtk-mml-core.h"
#include "mtk-mml-driver.h"
#include "mtk-mml-dle-adaptor.h"
#include "mtk-mml-pq-core.h"
#include "tile_driver.h"
#include "mtk-mml-tile.h"
#include "tile_mdp_func.h"
#undef pr_fmt
#define pr_fmt(fmt) "[mml_pq_tdshp]" fmt
#define TDSHP_00 0x000
#define TDSHP_01 0x004
#define TDSHP_02 0x008
#define TDSHP_03 0x00c
#define TDSHP_05 0x014
#define TDSHP_06 0x018
#define TDSHP_07 0x01c
#define TDSHP_08 0x020
#define TDSHP_09 0x024
#define PBC_00 0x040
#define PBC_01 0x044
#define PBC_02 0x048
#define PBC_03 0x04c
#define PBC_04 0x050
#define PBC_05 0x054
#define PBC_06 0x058
#define PBC_07 0x05c
#define PBC_08 0x060
#define HIST_CFG_00 0x064
#define HIST_CFG_01 0x068
#define LUMA_HIST_00 0x06c
#define LUMA_HIST_01 0x070
#define LUMA_HIST_02 0x074
#define LUMA_HIST_03 0x078
#define LUMA_HIST_04 0x07c
#define LUMA_HIST_05 0x080
#define LUMA_HIST_06 0x084
#define LUMA_HIST_07 0x08c
#define LUMA_HIST_08 0x090
#define LUMA_HIST_09 0x094
#define LUMA_HIST_10 0x098
#define LUMA_HIST_11 0x09c
#define LUMA_HIST_12 0x0a0
#define LUMA_HIST_13 0x0a4
#define LUMA_HIST_14 0x0a8
#define LUMA_HIST_15 0x0ac
#define LUMA_HIST_16 0x0b0
#define LUMA_SUM 0x0b4
#define Y_FTN_1_0_MAIN 0x0bc
#define Y_FTN_3_2_MAIN 0x0c0
#define Y_FTN_5_4_MAIN 0x0c4
#define Y_FTN_7_6_MAIN 0x0c8
#define Y_FTN_9_8_MAIN 0x0cc
#define Y_FTN_11_10_MAIN 0x0d0
#define Y_FTN_13_12_MAIN 0x0d4
#define Y_FTN_15_14_MAIN 0x0d8
#define Y_FTN_17_16_MAIN 0x0dc
#define C_BOOST_MAIN 0x0e0
#define C_BOOST_MAIN_2 0x0e4
#define TDSHP_ATPG 0x0fc
#define TDSHP_CTRL 0x100
#define TDSHP_INTEN 0x104
#define TDSHP_INTSTA 0x108
#define TDSHP_STATUS 0x10c
#define TDSHP_CFG 0x110
#define TDSHP_INPUT_COUNT 0x114
#define TDSHP_CHKSUM 0x118
#define TDSHP_OUTPUT_COUNT 0x11c
#define TDSHP_INPUT_SIZE 0x120
#define TDSHP_OUTPUT_OFFSET 0x124
#define TDSHP_OUTPUT_SIZE 0x128
#define TDSHP_BLANK_WIDTH 0x12c
#define TDSHP_DUMMY_REG 0x14c
#define LUMA_HIST_INIT_00 0x200
#define LUMA_HIST_INIT_01 0x204
#define LUMA_HIST_INIT_02 0x208
#define LUMA_HIST_INIT_03 0x20c
#define LUMA_HIST_INIT_04 0x210
#define LUMA_HIST_INIT_05 0x214
#define LUMA_HIST_INIT_06 0x218
#define LUMA_HIST_INIT_07 0x21c
#define LUMA_HIST_INIT_08 0x220
#define LUMA_HIST_INIT_09 0x224
#define LUMA_HIST_INIT_10 0x228
#define LUMA_HIST_INIT_11 0x22c
#define LUMA_HIST_INIT_12 0x230
#define LUMA_HIST_INIT_13 0x234
#define LUMA_HIST_INIT_14 0x238
#define LUMA_HIST_INIT_15 0x23c
#define LUMA_HIST_INIT_16 0x240
#define LUMA_SUM_INIT 0x244
#define DC_DBG_CFG_MAIN 0x250
#define DC_TWO_D_W1 0x25c
#define DC_TWO_D_W1_RESULT_INIT 0x260
#define DC_TWO_D_W1_RESULT 0x264
#define EDF_GAIN_00 0x300
#define EDF_GAIN_01 0x304
#define EDF_GAIN_02 0x308
#define EDF_GAIN_03 0x30c
#define EDF_GAIN_05 0x314
#define TDSHP_10 0x320
#define TDSHP_11 0x324
#define TDSHP_12 0x328
#define TDSHP_13 0x32c
#define PAT1_GEN_SET 0x330
#define PAT1_GEN_FRM_SIZE 0x334
#define PAT1_GEN_COLOR0 0x338
#define PAT1_GEN_COLOR1 0x33c
#define PAT1_GEN_COLOR2 0x340
#define PAT1_GEN_POS 0x344
#define PAT1_GEN_TILE_POS 0x354
#define PAT1_GEN_TILE_OV 0x358
#define PAT2_GEN_SET 0x360
#define PAT2_GEN_COLOR0 0x368
#define PAT2_GEN_COLOR1 0x36c
#define PAT2_GEN_POS 0x374
#define PAT2_GEN_CURSOR_RB0 0x378
#define PAT2_GEN_CURSOR_RB1 0x37c
#define PAT2_GEN_TILE_POS 0x384
#define PAT2_GEN_TILE_OV 0x388
#define BITPLUS_00 0x38c
#define BITPLUS_01 0x390
#define BITPLUS_02 0x394
#define CONTOUR_HIST_INIT_00 0x398
#define CONTOUR_HIST_INIT_01 0x39c
#define CONTOUR_HIST_INIT_02 0x3a0
#define CONTOUR_HIST_INIT_03 0x3a4
#define CONTOUR_HIST_INIT_04 0x3a8
#define CONTOUR_HIST_INIT_05 0x3ac
#define CONTOUR_HIST_INIT_06 0x3b0
#define CONTOUR_HIST_INIT_07 0x3b4
#define CONTOUR_HIST_INIT_08 0x3b8
#define CONTOUR_HIST_INIT_09 0x3bc
#define CONTOUR_HIST_INIT_10 0x3c0
#define CONTOUR_HIST_INIT_11 0x3c4
#define CONTOUR_HIST_INIT_12 0x3c8
#define CONTOUR_HIST_INIT_13 0x3cc
#define CONTOUR_HIST_INIT_14 0x3d0
#define CONTOUR_HIST_INIT_15 0x3d4
#define CONTOUR_HIST_INIT_16 0x3d8
#define CONTOUR_HIST_00 0x3dc
#define CONTOUR_HIST_01 0x3e0
#define CONTOUR_HIST_02 0x3e4
#define CONTOUR_HIST_03 0x3e8
#define CONTOUR_HIST_04 0x3ec
#define CONTOUR_HIST_05 0x3f0
#define CONTOUR_HIST_06 0x3f4
#define CONTOUR_HIST_07 0x3f8
#define CONTOUR_HIST_08 0x3fc
#define CONTOUR_HIST_09 0x400
#define CONTOUR_HIST_10 0x404
#define CONTOUR_HIST_11 0x408
#define CONTOUR_HIST_12 0x40c
#define CONTOUR_HIST_13 0x410
#define CONTOUR_HIST_14 0x414
#define CONTOUR_HIST_15 0x418
#define CONTOUR_HIST_16 0x41c
#define DC_SKIN_RANGE0 0x420
#define DC_SKIN_RANGE1 0x424
#define DC_SKIN_RANGE2 0x428
#define DC_SKIN_RANGE3 0x42c
#define DC_SKIN_RANGE4 0x430
#define DC_SKIN_RANGE5 0x434
#define POST_YLEV_00 0x480
#define POST_YLEV_01 0x484
#define POST_YLEV_02 0x488
#define POST_YLEV_03 0x48c
#define POST_YLEV_04 0x490
#define TDSHP_SHADOW_CTRL 0x67c
#define TDSHP_WAIT_TIMEOUT_MS (50)
#define DS_REG_NUM (36)
struct tdshp_data {
u32 tile_width;
/* u32 min_hfg_width; 9: HFG min + TDSHP crop */
};
static const struct tdshp_data mt6893_tdshp_data = {
.tile_width = 528
};
static const struct tdshp_data mt6983_tdshp_data = {
.tile_width = 1628,
};
static const struct tdshp_data mt6879_tdshp_data = {
.tile_width = 1344,
};
static const struct tdshp_data mt6895_tdshp_data = {
.tile_width = 1926,
};
struct mml_comp_tdshp {
struct mtk_ddp_comp ddp_comp;
struct mml_comp comp;
const struct tdshp_data *data;
bool ddp_bound;
};
/* meta data for each different frame config */
struct tdshp_frame_data {
u16 labels[DS_REG_NUM];
bool config_success;
};
#define tdshp_frm_data(i) ((struct tdshp_frame_data *)(i->data))
static inline struct mml_comp_tdshp *comp_to_tdshp(struct mml_comp *comp)
{
return container_of(comp, struct mml_comp_tdshp, comp);
}
static s32 tdshp_prepare(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
struct tdshp_frame_data *tdshp_frm = NULL;
tdshp_frm = kzalloc(sizeof(*tdshp_frm), GFP_KERNEL);
ccfg->data = tdshp_frm;
return 0;
}
static s32 tdshp_buf_prepare(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
struct mml_frame_config *cfg = task->config;
struct mml_frame_dest *dest = &cfg->info.dest[ccfg->node->out_idx];
s32 ret = 0;
if (!dest->pq_config.en_sharp && !dest->pq_config.en_dc)
return ret;
mml_pq_trace_ex_begin("%s", __func__);
ret = mml_pq_set_comp_config(task);
mml_pq_trace_ex_end();
return ret;
}
static s32 tdshp_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 mml_frame_config *cfg = task->config;
struct mml_frame_dest *dest = &cfg->info.dest[ccfg->node->out_idx];
struct mml_comp_tdshp *tdshp = comp_to_tdshp(comp);
data->tdshp.max_width = tdshp->data->tile_width;
/* TDSHP support crop capability, if no HFG. */
func->type = TILE_TYPE_CROP_EN;
func->init_func = tile_tdshp_init;
func->for_func = tile_crop_for;
func->data = data;
func->enable_flag = dest->pq_config.en_sharp ||
cfg->info.mode == MML_MODE_DDP_ADDON;
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 tdshp_tile_ops = {
.prepare = tdshp_tile_prepare,
};
static u32 tdshp_get_label_count(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
struct mml_frame_config *cfg = task->config;
const struct mml_frame_dest *dest = &cfg->info.dest[ccfg->node->out_idx];
mml_pq_msg("%s pipe_id[%d] engine_id[%d] en_sharp[%d]", __func__,
ccfg->pipe, comp->id, dest->pq_config.en_sharp);
if (!dest->pq_config.en_sharp)
return 0;
return DS_REG_NUM;
}
static void tdshp_init(struct cmdq_pkt *pkt, const phys_addr_t base_pa)
{
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_CTRL, 0x1, 0x00000001);
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_CFG, 0x2, 0x00000002);
/* Enable shadow */
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_SHADOW_CTRL, 0x2, U32_MAX);
}
static void tdshp_relay(struct cmdq_pkt *pkt, const phys_addr_t base_pa,
u32 relay)
{
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_CFG, relay, 0x00000001);
}
static s32 tdshp_config_init(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
tdshp_init(task->pkts[ccfg->pipe], comp->base_pa);
return 0;
}
static struct mml_pq_comp_config_result *get_tdshp_comp_config_result(
struct mml_task *task)
{
return task->pq_task->comp_config.result;
}
static s32 tdshp_config_frame(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
struct mml_frame_config *cfg = task->config;
struct cmdq_pkt *pkt = task->pkts[ccfg->pipe];
struct tdshp_frame_data *tdshp_frm = tdshp_frm_data(ccfg);
struct mml_frame_data *src = &cfg->info.src;
const struct mml_frame_dest *dest = &cfg->info.dest[ccfg->node->out_idx];
struct mml_task_reuse *reuse = &task->reuse[ccfg->pipe];
struct mml_pipe_cache *cache = &cfg->cache[ccfg->pipe];
const phys_addr_t base_pa = comp->base_pa;
struct mml_pq_comp_config_result *result;
s32 ret;
if (MML_FMT_10BIT(src->format) || MML_FMT_10BIT(dest->data.format))
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_CTRL, 0, 0x00000004);
else
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_CTRL, 0x4, 0x00000004);
if (!dest->pq_config.en_sharp && !dest->pq_config.en_dc) {
/* relay mode */
if (cfg->info.mode == MML_MODE_DDP_ADDON) {
/* enable to crop */
tdshp_relay(pkt, base_pa, 0x0);
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_00, 0, 1 << 31);
} else {
tdshp_relay(pkt, base_pa, 0x1);
}
return 0;
}
tdshp_relay(pkt, base_pa, 0x0);
ret = mml_pq_get_comp_config_result(task, TDSHP_WAIT_TIMEOUT_MS);
if (!ret) {
result = get_tdshp_comp_config_result(task);
if (result) {
s32 i;
struct mml_pq_reg *regs = result->ds_regs;
/* TODO: use different regs */
mml_pq_msg("%s:config ds regs, count: %d", __func__, result->ds_reg_cnt);
tdshp_frm->config_success = true;
for (i = 0; i < result->ds_reg_cnt; i++) {
mml_write(pkt, base_pa + regs[i].offset, regs[i].value,
regs[i].mask, reuse, cache,
&tdshp_frm->labels[i]);
mml_pq_msg("[ds][config][%x] = %#x mask(%#x)",
regs[i].offset, regs[i].value, regs[i].mask);
}
} else {
mml_pq_err("%s: not get result from user lib", __func__);
}
} else {
mml_pq_comp_config_clear(task);
tdshp_frm->config_success = false;
mml_pq_err("get ds param timeout: %d in %dms",
ret, TDSHP_WAIT_TIMEOUT_MS);
}
return ret;
}
static s32 tdshp_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 tdshp_input_w;
u32 tdshp_input_h;
u32 tdshp_output_w;
u32 tdshp_output_h;
u32 tdshp_crop_x_offset;
u32 tdshp_crop_y_offset;
u32 tdshp_hist_left;
u32 tdshp_hist_top;
mml_pq_msg("%s idx[%d] engine_id[%d]", __func__, idx, comp->id);
tdshp_input_w = tile->in.xe - tile->in.xs + 1;
tdshp_input_h = tile->in.ye - tile->in.ys + 1;
tdshp_output_w = tile->out.xe - tile->out.xs + 1;
tdshp_output_h = tile->out.ye - tile->out.ys + 1;
tdshp_crop_x_offset = tile->out.xs - tile->in.xs;
tdshp_crop_y_offset = tile->out.ys - tile->in.ys;
/* TODO: need official implementation */
tdshp_hist_left = 0xffff;
tdshp_hist_top = 0xffff;
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_INPUT_SIZE,
(tdshp_input_w << 16) + tdshp_input_h, U32_MAX);
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_OUTPUT_OFFSET,
(tdshp_crop_x_offset << 16) + tdshp_crop_y_offset, U32_MAX);
cmdq_pkt_write(pkt, NULL, base_pa + TDSHP_OUTPUT_SIZE,
(tdshp_output_w << 16) + tdshp_output_h, U32_MAX);
cmdq_pkt_write(pkt, NULL, base_pa + HIST_CFG_00,
((tile->out.xe - tile->in.xs) << 16) +
(tdshp_hist_left - tile->in.xs), U32_MAX);
cmdq_pkt_write(pkt, NULL, base_pa + HIST_CFG_01,
((tile->out.ye - tile->in.ys) << 16) +
(tdshp_hist_top - tile->in.ys), U32_MAX);
return 0;
}
static s32 tdshp_config_post(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
struct mml_frame_dest *dest = &task->config->info.dest[ccfg->node->out_idx];
if (dest->pq_config.en_sharp || dest->pq_config.en_dc)
mml_pq_put_comp_config_result(task);
return 0;
}
static s32 tdshp_reconfig_frame(struct mml_comp *comp, struct mml_task *task,
struct mml_comp_config *ccfg)
{
struct mml_frame_config *cfg = task->config;
struct tdshp_frame_data *tdshp_frm = tdshp_frm_data(ccfg);
const struct mml_frame_dest *dest = &cfg->info.dest[ccfg->node->out_idx];
struct mml_task_reuse *reuse = &task->reuse[ccfg->pipe];
struct mml_pq_comp_config_result *result = NULL;
s32 ret = 0;
if (!dest->pq_config.en_sharp && !dest->pq_config.en_dc)
return ret;
ret = mml_pq_get_comp_config_result(task, TDSHP_WAIT_TIMEOUT_MS);
if (!ret) {
result = get_tdshp_comp_config_result(task);
if (result && tdshp_frm->config_success) {
s32 i;
struct mml_pq_reg *regs = result->ds_regs;
//TODO: use different regs
mml_pq_msg("%s:config ds regs, count: %d", __func__, result->ds_reg_cnt);
for (i = 0; i < result->ds_reg_cnt; i++) {
mml_update(reuse, tdshp_frm->labels[i], regs[i].value);
mml_pq_msg("[ds][config][%x] = %#x mask(%#x)",
regs[i].offset, regs[i].value, regs[i].mask);
}
} else {
mml_pq_err("%s: not get result from user lib", __func__);
}
} else {
mml_pq_err("get ds param timeout: %d in %dms",
ret, TDSHP_WAIT_TIMEOUT_MS);
}
return ret;
}
static const struct mml_comp_config_ops tdshp_cfg_ops = {
.prepare = tdshp_prepare,
.buf_prepare = tdshp_buf_prepare,
.get_label_count = tdshp_get_label_count,
.init = tdshp_config_init,
.frame = tdshp_config_frame,
.tile = tdshp_config_tile,
.post = tdshp_config_post,
.reframe = tdshp_reconfig_frame,
};
static void tdshp_debug_dump(struct mml_comp *comp)
{
void __iomem *base = comp->base;
u32 value[11];
u32 shadow_ctrl;
mml_err("tdshp component %u dump:", comp->id);
/* Enable shadow read working */
shadow_ctrl = readl(base + TDSHP_SHADOW_CTRL);
shadow_ctrl |= 0x4;
writel(shadow_ctrl, base + TDSHP_SHADOW_CTRL);
value[0] = readl(base + TDSHP_CTRL);
value[1] = readl(base + TDSHP_INTEN);
value[2] = readl(base + TDSHP_INTSTA);
value[3] = readl(base + TDSHP_STATUS);
value[4] = readl(base + TDSHP_CFG);
value[5] = readl(base + TDSHP_INPUT_COUNT);
value[6] = readl(base + TDSHP_OUTPUT_COUNT);
value[7] = readl(base + TDSHP_INPUT_SIZE);
value[8] = readl(base + TDSHP_OUTPUT_OFFSET);
value[9] = readl(base + TDSHP_OUTPUT_SIZE);
value[10] = readl(base + TDSHP_BLANK_WIDTH);
mml_err("TDSHP_CTRL %#010x TDSHP_INTEN %#010x TDSHP_INTSTA %#010x TDSHP_STATUS %#010x",
value[0], value[1], value[2], value[3]);
mml_err("TDSHP_CFG %#010x TDSHP_INPUT_COUNT %#010x TDSHP_OUTPUT_COUNT %#010x",
value[4], value[5], value[6]);
mml_err("TDSHP_INPUT_SIZE %#010x TDSHP_OUTPUT_OFFSET %#010x TDSHP_OUTPUT_SIZE %#010x",
value[7], value[8], value[9]);
mml_err("TDSHP_BLANK_WIDTH %#010x", value[10]);
}
static const struct mml_comp_debug_ops tdshp_debug_ops = {
.dump = &tdshp_debug_dump,
};
static int mml_bind(struct device *dev, struct device *master, void *data)
{
struct mml_comp_tdshp *tdshp = dev_get_drvdata(dev);
struct drm_device *drm_dev = data;
s32 ret;
if (!drm_dev) {
ret = mml_register_comp(master, &tdshp->comp);
if (ret)
dev_err(dev, "Failed to register mml component %s: %d\n",
dev->of_node->full_name, ret);
} else {
ret = mml_ddp_comp_register(drm_dev, &tdshp->ddp_comp);
if (ret)
dev_err(dev, "Failed to register ddp component %s: %d\n",
dev->of_node->full_name, ret);
else
tdshp->ddp_bound = true;
}
return ret;
}
static void mml_unbind(struct device *dev, struct device *master, void *data)
{
struct mml_comp_tdshp *tdshp = dev_get_drvdata(dev);
struct drm_device *drm_dev = data;
if (!drm_dev) {
mml_unregister_comp(master, &tdshp->comp);
} else {
mml_ddp_comp_unregister(drm_dev, &tdshp->ddp_comp);
tdshp->ddp_bound = false;
}
}
static const struct component_ops mml_comp_ops = {
.bind = mml_bind,
.unbind = mml_unbind,
};
static const struct mtk_ddp_comp_funcs ddp_comp_funcs = {
};
static struct mml_comp_tdshp *dbg_probed_components[4];
static int dbg_probed_count;
static int probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mml_comp_tdshp *priv;
s32 ret;
bool add_ddp = true;
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 = &tdshp_tile_ops;
priv->comp.config_ops = &tdshp_cfg_ops;
priv->comp.debug_ops = &tdshp_debug_ops;
ret = mml_ddp_comp_init(dev, &priv->ddp_comp, &priv->comp,
&ddp_comp_funcs);
if (ret) {
mml_log("failed to init ddp component: %d", ret);
add_ddp = false;
}
if (unlikely(dbg_probed_count < 0))
return -EFAULT;
dbg_probed_components[dbg_probed_count++] = priv;
ret = component_add(dev, &mml_comp_ops);
if (add_ddp)
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);
component_del(&pdev->dev, &mml_comp_ops);
return 0;
}
const struct of_device_id mml_tdshp_driver_dt_match[] = {
{
.compatible = "mediatek,mt6983-mml_tdshp",
.data = &mt6983_tdshp_data,
},
{
.compatible = "mediatek,mt6893-mml_tdshp",
.data = &mt6893_tdshp_data
},
{
.compatible = "mediatek,mt6879-mml_tdshp",
.data = &mt6879_tdshp_data
},
{
.compatible = "mediatek,mt6895-mml_tdshp",
.data = &mt6895_tdshp_data
},
{},
};
MODULE_DEVICE_TABLE(of, mml_tdshp_driver_dt_match);
struct platform_driver mml_tdshp_driver = {
.probe = probe,
.remove = remove,
.driver = {
.name = "mediatek-mml-tdshp",
.owner = THIS_MODULE,
.of_match_table = mml_tdshp_driver_dt_match,
},
};
//module_platform_driver(mml_tdshp_driver);
static s32 dbg_case;
static s32 dbg_set(const char *val, const struct kernel_param *kp)
{
s32 result;
result = kstrtos32(val, 0, &dbg_case);
mml_log("%s: debug_case=%d", __func__, dbg_case);
switch (dbg_case) {
case 0:
mml_log("use read to dump component status");
break;
default:
mml_err("invalid debug_case: %d", dbg_case);
break;
}
return result;
}
static s32 dbg_get(char *buf, const struct kernel_param *kp)
{
s32 length = 0;
u32 i;
switch (dbg_case) {
case 0:
length += snprintf(buf + length, PAGE_SIZE - length,
"[%d] probed count: %d\n", dbg_case, dbg_probed_count);
for (i = 0; i < dbg_probed_count; i++) {
struct mml_comp *comp = &dbg_probed_components[i]->comp;
length += snprintf(buf + length, PAGE_SIZE - length,
" - [%d] mml comp_id: %d.%d @%llx name: %s bound: %d\n", i,
comp->id, comp->sub_idx, comp->base_pa,
comp->name ? comp->name : "(null)", comp->bound);
length += snprintf(buf + length, PAGE_SIZE - length,
" - larb_port: %d @%llx pw: %d clk: %d\n",
comp->larb_port, comp->larb_base,
comp->pw_cnt, comp->clk_cnt);
length += snprintf(buf + length, PAGE_SIZE - length,
" - ddp comp_id: %d bound: %d\n",
dbg_probed_components[i]->ddp_comp.id,
dbg_probed_components[i]->ddp_bound);
}
break;
default:
mml_err("not support read for debug_case: %d", dbg_case);
break;
}
buf[length] = '\0';
return length;
}
static const struct kernel_param_ops dbg_param_ops = {
.set = dbg_set,
.get = dbg_get,
};
module_param_cb(tdshp_debug, &dbg_param_ops, NULL, 0644);
MODULE_PARM_DESC(tdshp_debug, "mml tdshp debug case");
MODULE_AUTHOR("Dennis-YC Hsieh <dennis-yc.hsieh@mediatek.com>");
MODULE_DESCRIPTION("MediaTek SoC display MML TDSHP driver");
MODULE_LICENSE("GPL v2");