From: "james qian wang (Arm Technology China)" <james.qian.wang@xxxxxxx> Add a debugfs node "register" and entry function dump_register to dev/pipeline/component to register dump, then user can read "/sys/kernel/debug/komeda/register" to get the register values via these chip function. Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@xxxxxxx> --- .../arm/display/komeda/d71/d71_component.c | 205 ++++++++++++++++++ .../gpu/drm/arm/display/komeda/komeda_dev.c | 52 +++++ .../gpu/drm/arm/display/komeda/komeda_dev.h | 5 + .../drm/arm/display/komeda/komeda_pipeline.c | 20 ++ .../drm/arm/display/komeda/komeda_pipeline.h | 3 + 5 files changed, 285 insertions(+) diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c index 095779964518..eb8f16e089e7 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c @@ -69,6 +69,42 @@ static u32 get_valid_inputs(struct block_header *blk) return valid_inputs; } +static void get_values_from_reg(void __iomem *reg, u32 offset, + u32 count, u32 *val) +{ + u32 i, addr; + + for (i = 0; i < count; i++) { + addr = offset + (i << 2); + /* 0xA4 is WO register */ + if (addr != 0xA4) + val[i] = malidp_read32(reg, addr); + else + val[i] = 0xDEADDEAD; + } +} + +static void dump_block_header(struct seq_file *sf, void __iomem *reg) +{ + struct block_header hdr; + u32 i, n_input, n_output; + + d71_read_block_header(reg, &hdr); + seq_printf(sf, "BLOCK_INFO:\t\t0x%X\n", hdr.block_info); + seq_printf(sf, "PIPELINE_INFO:\t\t0x%X\n", hdr.pipeline_info); + + n_output = PIPELINE_INFO_N_OUTPUTS(hdr.pipeline_info); + n_input = PIPELINE_INFO_N_VALID_INPUTS(hdr.pipeline_info); + + for (i = 0; i < n_input; i++) + seq_printf(sf, "VALID_INPUT_ID%u:\t0x%X\n", + i, hdr.input_ids[i]); + + for (i = 0; i < n_output; i++) + seq_printf(sf, "OUTPUT_ID%u:\t\t0x%X\n", + i, hdr.output_ids[i]); +} + static u32 to_rot_ctrl(u32 rot) { u32 lr_ctrl = 0; @@ -141,9 +177,76 @@ static void d71_layer_update(struct komeda_component *c, malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl); } +static void d71_layer_dump(struct komeda_component *c, struct seq_file *sf) +{ + u32 v[15], i; + bool rich, rgb2rgb; + char *prefix; + + get_values_from_reg(c->reg, LAYER_INFO, 1, &v[14]); + if (v[14] & 0x1) { + rich = true; + prefix = "LR_"; + } else { + rich = false; + prefix = "LS_"; + } + + rgb2rgb = !!(v[14] & L_INFO_CM); + + dump_block_header(sf, c->reg); + + seq_printf(sf, "%sLAYER_INFO:\t\t0x%X\n", prefix, v[14]); + + get_values_from_reg(c->reg, 0xD0, 1, v); + seq_printf(sf, "%sCONTROL:\t\t0x%X\n", prefix, v[0]); + if (rich) { + get_values_from_reg(c->reg, 0xD4, 1, v); + seq_printf(sf, "LR_RICH_CONTROL:\t0x%X\n", v[0]); + } + get_values_from_reg(c->reg, 0xD8, 4, v); + seq_printf(sf, "%sFORMAT:\t\t0x%X\n", prefix, v[0]); + seq_printf(sf, "%sIT_COEFFTAB:\t\t0x%X\n", prefix, v[1]); + seq_printf(sf, "%sIN_SIZE:\t\t0x%X\n", prefix, v[2]); + seq_printf(sf, "%sPALPHA:\t\t0x%X\n", prefix, v[3]); + + get_values_from_reg(c->reg, 0x100, 3, v); + seq_printf(sf, "%sP0_PTR_LOW:\t\t0x%X\n", prefix, v[0]); + seq_printf(sf, "%sP0_PTR_HIGH:\t\t0x%X\n", prefix, v[1]); + seq_printf(sf, "%sP0_STRIDE:\t\t0x%X\n", prefix, v[2]); + + get_values_from_reg(c->reg, 0x110, 2, v); + seq_printf(sf, "%sP1_PTR_LOW:\t\t0x%X\n", prefix, v[0]); + seq_printf(sf, "%sP1_PTR_HIGH:\t\t0x%X\n", prefix, v[1]); + if (rich) { + get_values_from_reg(c->reg, 0x118, 1, v); + seq_printf(sf, "LR_P1_STRIDE:\t\t0x%X\n", v[0]); + + get_values_from_reg(c->reg, 0x120, 2, v); + seq_printf(sf, "LR_P2_PTR_LOW:\t\t0x%X\n", v[0]); + seq_printf(sf, "LR_P2_PTR_HIGH:\t\t0x%X\n", v[1]); + + get_values_from_reg(c->reg, 0x130, 12, v); + for (i = 0; i < 12; i++) + seq_printf(sf, "LR_YUV_RGB_COEFF%u:\t0x%X\n", i, v[i]); + } + + if (rgb2rgb) { + get_values_from_reg(c->reg, LAYER_RGB_RGB_COEFF0, 12, v); + for (i = 0; i < 12; i++) + seq_printf(sf, "LS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]); + } + + get_values_from_reg(c->reg, 0x160, 3, v); + seq_printf(sf, "%sAD_CONTROL:\t\t0x%X\n", prefix, v[0]); + seq_printf(sf, "%sAD_H_CROP:\t\t0x%X\n", prefix, v[1]); + seq_printf(sf, "%sAD_V_CROP:\t\t0x%X\n", prefix, v[2]); +} + struct komeda_component_funcs d71_layer_funcs = { .update = d71_layer_update, .disable = d71_layer_disable, + .dump_register = d71_layer_dump, }; static int d71_layer_init(struct d71_dev *d71, @@ -250,9 +353,46 @@ static void d71_compiz_update(struct komeda_component *c, malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); } +static void d71_compiz_dump(struct komeda_component *c, struct seq_file *sf) +{ + u32 v[8], i; + + dump_block_header(sf, c->reg); + + get_values_from_reg(c->reg, 0x80, 5, v); + for (i = 0; i < 5; i++) + seq_printf(sf, "CU_INPUT_ID%u:\t\t0x%X\n", i, v[i]); + + get_values_from_reg(c->reg, 0xA0, 5, v); + seq_printf(sf, "CU_IRQ_RAW_STATUS:\t0x%X\n", v[0]); + seq_printf(sf, "CU_IRQ_CLEAR:\t\t0x%X\n", v[1]); + seq_printf(sf, "CU_IRQ_MASK:\t\t0x%X\n", v[2]); + seq_printf(sf, "CU_IRQ_STATUS:\t\t0x%X\n", v[3]); + seq_printf(sf, "CU_STATUS:\t\t0x%X\n", v[4]); + + get_values_from_reg(c->reg, 0xD0, 2, v); + seq_printf(sf, "CU_CONTROL:\t\t0x%X\n", v[0]); + seq_printf(sf, "CU_SIZE:\t\t0x%X\n", v[1]); + + get_values_from_reg(c->reg, 0xDC, 1, v); + seq_printf(sf, "CU_BG_COLOR:\t\t0x%X\n", v[0]); + + for (i = 0, v[4] = 0xE0; i < 5; i++, v[4] += 0x10) { + get_values_from_reg(c->reg, v[4], 3, v); + seq_printf(sf, "CU_INPUT%u_SIZE:\t\t0x%X\n", i, v[0]); + seq_printf(sf, "CU_INPUT%u_OFFSET:\t0x%X\n", i, v[1]); + seq_printf(sf, "CU_INPUT%u_CONTROL:\t0x%X\n", i, v[2]); + } + + get_values_from_reg(c->reg, 0x130, 2, v); + seq_printf(sf, "CU_USER_LOW:\t\t0x%X\n", v[0]); + seq_printf(sf, "CU_USER_HIGH:\t\t0x%X\n", v[1]); +} + struct komeda_component_funcs d71_compiz_funcs = { .update = d71_compiz_update, .disable = d71_component_disable, + .dump_register = d71_compiz_dump, }; static int d71_compiz_init(struct d71_dev *d71, @@ -298,9 +438,37 @@ static void d71_improc_update(struct komeda_component *c, malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize)); } +static void d71_improc_dump(struct komeda_component *c, struct seq_file *sf) +{ + u32 v[12], i; + + dump_block_header(sf, c->reg); + + get_values_from_reg(c->reg, 0x80, 2, v); + seq_printf(sf, "IPS_INPUT_ID0:\t\t0x%X\n", v[0]); + seq_printf(sf, "IPS_INPUT_ID1:\t\t0x%X\n", v[1]); + + get_values_from_reg(c->reg, 0xC0, 1, v); + seq_printf(sf, "IPS_INFO:\t\t0x%X\n", v[0]); + + get_values_from_reg(c->reg, 0xD0, 3, v); + seq_printf(sf, "IPS_CONTROL:\t\t0x%X\n", v[0]); + seq_printf(sf, "IPS_SIZE:\t\t0x%X\n", v[1]); + seq_printf(sf, "IPS_DEPTH:\t\t0x%X\n", v[2]); + + get_values_from_reg(c->reg, 0x130, 12, v); + for (i = 0; i < 12; i++) + seq_printf(sf, "IPS_RGB_RGB_COEFF%u:\t0x%X\n", i, v[i]); + + get_values_from_reg(c->reg, 0x170, 12, v); + for (i = 0; i < 12; i++) + seq_printf(sf, "IPS_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]); +} + struct komeda_component_funcs d71_improc_funcs = { .update = d71_improc_update, .disable = d71_component_disable, + .dump_register = d71_improc_dump, }; static int d71_improc_init(struct d71_dev *d71, @@ -373,9 +541,46 @@ static void d71_timing_ctrlr_update(struct komeda_component *c, malidp_write32(reg, BLK_CONTROL, value); } +void d71_timing_ctrlr_dump(struct komeda_component *c, struct seq_file *sf) +{ + u32 v[8], i; + + dump_block_header(sf, c->reg); + + get_values_from_reg(c->reg, 0xC0, 1, v); + seq_printf(sf, "BS_INFO:\t\t0x%X\n", v[0]); + + get_values_from_reg(c->reg, 0xD0, 8, v); + seq_printf(sf, "BS_CONTROL:\t\t0x%X\n", v[0]); + seq_printf(sf, "BS_PROG_LINE:\t\t0x%X\n", v[1]); + seq_printf(sf, "BS_PREFETCH_LINE:\t0x%X\n", v[2]); + seq_printf(sf, "BS_BG_COLOR:\t\t0x%X\n", v[3]); + seq_printf(sf, "BS_ACTIVESIZE:\t\t0x%X\n", v[4]); + seq_printf(sf, "BS_HINTERVALS:\t\t0x%X\n", v[5]); + seq_printf(sf, "BS_VINTERVALS:\t\t0x%X\n", v[6]); + seq_printf(sf, "BS_SYNC:\t\t0x%X\n", v[7]); + + get_values_from_reg(c->reg, 0x100, 3, v); + seq_printf(sf, "BS_DRIFT_TO:\t\t0x%X\n", v[0]); + seq_printf(sf, "BS_FRAME_TO:\t\t0x%X\n", v[1]); + seq_printf(sf, "BS_TE_TO:\t\t0x%X\n", v[2]); + + get_values_from_reg(c->reg, 0x110, 3, v); + for (i = 0; i < 3; i++) + seq_printf(sf, "BS_T%u_INTERVAL:\t\t0x%X\n", i, v[i]); + + get_values_from_reg(c->reg, 0x120, 5, v); + for (i = 0; i < 2; i++) { + seq_printf(sf, "BS_CRC%u_LOW:\t\t0x%X\n", i, v[i << 1]); + seq_printf(sf, "BS_CRC%u_HIGH:\t\t0x%X\n", i, v[(i << 1) + 1]); + } + seq_printf(sf, "BS_USER:\t\t0x%X\n", v[4]); +} + struct komeda_component_funcs d71_timing_ctrlr_funcs = { .update = d71_timing_ctrlr_update, .disable = d71_timing_ctrlr_disable, + .dump_register = d71_timing_ctrlr_dump, }; static int d71_timing_ctrlr_init(struct d71_dev *d71, diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c index 01ae869b659b..a012b3bbf53b 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c @@ -7,8 +7,52 @@ #include <linux/platform_device.h> #include <linux/of_device.h> #include <linux/of_graph.h> +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#endif #include "komeda_dev.h" +static int komeda_register_show(struct seq_file *sf, void *x) +{ + struct komeda_dev *mdev = sf->private; + int i; + + if (mdev->funcs->dump_register) + mdev->funcs->dump_register(mdev, sf); + + for (i = 0; i < mdev->n_pipelines; i++) + komeda_pipeline_dump_register(mdev->pipelines[i], sf); + + return 0; +} + +static int komeda_register_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, komeda_register_show, inode->i_private); +} + +static const struct file_operations komeda_register_fops = { + .owner = THIS_MODULE, + .open = komeda_register_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void komeda_debugfs_init(struct komeda_dev *mdev) +{ + if (!debugfs_initialized()) + return; + + mdev->debugfs_root = debugfs_create_dir("komeda", NULL); + if (IS_ERR_OR_NULL(mdev->debugfs_root)) + return; + + debugfs_create_file("register", 0444, mdev->debugfs_root, + mdev, &komeda_register_fops); +} + static int komeda_parse_pipe_dt(struct komeda_dev *mdev, struct device_node *np) { struct komeda_pipeline *pipe; @@ -155,6 +199,10 @@ struct komeda_dev *komeda_dev_create(struct device *dev) goto err_cleanup; } +#ifdef CONFIG_DEBUG_FS + komeda_debugfs_init(mdev); +#endif + return mdev; err_cleanup: @@ -168,6 +216,10 @@ void komeda_dev_destroy(struct komeda_dev *mdev) struct komeda_dev_funcs *funcs = mdev->funcs; int i; +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(mdev->debugfs_root); +#endif + for (i = 0; i < mdev->n_pipelines; i++) { komeda_pipeline_destroy(mdev, mdev->pipelines[i]); mdev->pipelines[i] = NULL; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index 681fe022bd22..8eae2620ce77 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h @@ -103,6 +103,9 @@ struct komeda_dev_funcs { int (*enable_irq)(struct komeda_dev *mdev); /** @disable_irq: disable irq */ int (*disable_irq)(struct komeda_dev *mdev); + + /** @dump_register: Optional, dump registers to seq_file */ + void (*dump_register)(struct komeda_dev *mdev, struct seq_file *seq); }; /** @@ -139,6 +142,8 @@ struct komeda_dev { * destroyed by &komeda_dev_funcs.cleanup() */ void *chip_data; + + struct dentry *debugfs_root; }; static inline bool diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c index c2e469164244..06da94f509e4 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c @@ -273,3 +273,23 @@ int komeda_assemble_pipelines(struct komeda_dev *mdev) return 0; } + +void komeda_pipeline_dump_register(struct komeda_pipeline *pipe, + struct seq_file *sf) +{ + struct komeda_component *c; + u32 id; + + seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id); + + if (pipe->funcs && pipe->funcs->dump_register) + pipe->funcs->dump_register(pipe, sf); + + dp_for_each_set_bit(id, pipe->avail_comps) { + c = komeda_pipeline_get_component(pipe, id); + + seq_printf(sf, "\n------%s------\n", c->name); + if (c->funcs->dump_register) + c->funcs->dump_register(c, sf); + } +} diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h index f9b7f517a484..c30a790d0712 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h @@ -367,6 +367,9 @@ int komeda_assemble_pipelines(struct komeda_dev *mdev); struct komeda_component * komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id); +void komeda_pipeline_dump_register(struct komeda_pipeline *pipe, + struct seq_file *sf); + /* component APIs */ struct komeda_component * komeda_component_add(struct komeda_pipeline *pipe, -- 2.17.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel