diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.c b/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.c index 456d82d884ad..8d71df1d4cbf 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.c @@ -284,3 +284,70 @@ int rockchip_drm_debugfs_add_color_bar(struct drm_crtc *crtc, struct dentry *roo return 0; } + +static int rockchip_drm_debugfs_regs_write_show(struct seq_file *s, void *data) +{ + seq_puts(s, " Write VOP regs:\n"); + seq_puts(s, " echo address val > /sys/kernel/debug/dri/0/video_portx/regs_write\n\n"); + seq_puts(s, " video_portx is depend on hardware config, you can get this info from the cmd:\n"); + seq_puts(s, " cat /sys/kernel/debug/dri/0/summary\n\n"); + seq_puts(s, " Example:\n"); + seq_puts(s, " echo 0x27d00000 0x1 > /sys/kernel/debug/dri/0/video_portx/regs_write\n\n"); + + return 0; +} + +static int rockchip_drm_debugfs_regs_write_open(struct inode *inode, struct file *file) +{ + struct drm_crtc *crtc = inode->i_private; + + return single_open(file, rockchip_drm_debugfs_regs_write_show, crtc); +} + +static ssize_t rockchip_drm_debugfs_regs_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *s = file->private_data; + struct drm_crtc *crtc = s->private; + struct rockchip_drm_private *priv = crtc->dev->dev_private; + int ret = 0, pipe = drm_crtc_index(crtc); + unsigned long address = 0; + u32 val = 0; + char kbuf[32]; + + len = min_t(size_t, len, (sizeof(kbuf) - 1)); + if (copy_from_user(kbuf, ubuf, len)) + return -EINVAL; + + kbuf[len] = 0; + if (sscanf(kbuf, "%lx %x", &address, &val) == -1) + return -EFAULT; + + if (priv->crtc_funcs[pipe]->regs_write) + ret = priv->crtc_funcs[pipe]->regs_write(crtc, address, val); + if (ret) + return ret; + + return len; +} + +static const struct file_operations rockchip_drm_debugfs_regs_write_ops = { + .owner = THIS_MODULE, + .open = rockchip_drm_debugfs_regs_write_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = rockchip_drm_debugfs_regs_write, +}; + +int rockchip_drm_debugfs_add_regs_write(struct drm_crtc *crtc, struct dentry *root) +{ + struct dentry *ent; + + ent = debugfs_create_file("regs_write", 0644, root, crtc, + &rockchip_drm_debugfs_regs_write_ops); + if (!ent) + DRM_ERROR("Failed to add regs_write for debugfs\n"); + + return 0; +} diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.h b/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.h index 6e63da0a188c..2f8ec1677245 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_debugfs.h @@ -36,6 +36,7 @@ rockchip_drm_crtc_dump_plane_buffer(struct drm_crtc *crtc) } #endif int rockchip_drm_debugfs_add_color_bar(struct drm_crtc *crtc, struct dentry *root); +int rockchip_drm_debugfs_add_regs_write(struct drm_crtc *crtc, struct dentry *root); #else static inline int rockchip_drm_add_dump_buffer(struct drm_crtc *crtc, struct dentry *root) @@ -54,6 +55,12 @@ rockchip_drm_debugfs_add_color_bar(struct drm_crtc *crtc, struct dentry *root) { return 0; } + +static inline int +rockchip_drm_debugfs_add_regs_write(struct drm_crtc *crtc, struct dentry *root) +{ + return 0; +} #endif #endif diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 42e194b24574..b65781c36f96 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -491,6 +491,7 @@ struct rockchip_crtc_funcs { int (*debugfs_dump)(struct drm_crtc *crtc, struct seq_file *s); void (*regs_dump)(struct drm_crtc *crtc, struct seq_file *s); void (*active_regs_dump)(struct drm_crtc *crtc, struct seq_file *s); + int (*regs_write)(struct drm_crtc *crtc, phys_addr_t address, u32 val); enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc, const struct drm_display_mode *mode, int output_type);