Skip to content

Commit 9fd9c79

Browse files
Shixiang Zhengrkhuangtao
authored andcommitted
drm/rockchip: add a debug node to dump buf from application
dump path: /data/vop_buf debug nod: d/dri/0/ff900000.vop/vop_dump/dump echo dump > dump to dump one frame echo dumpon > dump to start vop keep dumping echo dumpoff > dump to stop keep dumping echo dumpn > dump n is the number of dump times if fd err -3 try rm -r /data/vopbuf echo dump1 > dump can fix it if fd err -28 save needed data try rm -r /data/vopbuf Change-Id: Id5fefa428db1b5669ceae418cd8bddfa52e52f61 Signed-off-by: Shixiang Zheng <shixiang.zheng@rock-chips.com>
1 parent 1c40af5 commit 9fd9c79

7 files changed

Lines changed: 355 additions & 11 deletions

File tree

drivers/gpu/drm/drm_debugfs.c

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@
3737
#include <drm/drmP.h>
3838
#include <drm/drm_edid.h>
3939
#include "drm_internal.h"
40+
#include <linux/ctype.h>
41+
#include <linux/syscalls.h>
4042

4143
#if defined(CONFIG_DEBUG_FS)
44+
#define DUMP_BUF_PATH "/data/vop_buf"
4245

4346
/***************************************************
4447
* Initialization, etc.
@@ -71,7 +74,219 @@ static const struct file_operations drm_debugfs_fops = {
7174
.release = single_release,
7275
};
7376

77+
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
78+
static char *get_format_str(uint32_t format)
79+
{
80+
switch (format) {
81+
case DRM_FORMAT_XRGB8888:
82+
case DRM_FORMAT_ARGB8888:
83+
case DRM_FORMAT_XBGR8888:
84+
case DRM_FORMAT_ABGR8888:
85+
return "ARGB8888";
86+
case DRM_FORMAT_RGB888:
87+
case DRM_FORMAT_BGR888:
88+
return "BGR888";
89+
case DRM_FORMAT_RGB565:
90+
case DRM_FORMAT_BGR565:
91+
return "RGB565";
92+
case DRM_FORMAT_NV12:
93+
case DRM_FORMAT_NV12_10:
94+
return "YUV420NV12";
95+
case DRM_FORMAT_NV16:
96+
case DRM_FORMAT_NV16_10:
97+
return "YUV422NV16";
98+
case DRM_FORMAT_NV24:
99+
case DRM_FORMAT_NV24_10:
100+
return "YUV444NV24";
101+
default:
102+
DRM_ERROR("unsupport format[%08x]\n", format);
103+
return "UNF";
104+
}
105+
}
106+
107+
int vop_plane_dump(struct vop_dump_info *dump_info, int frame_count)
108+
{
109+
int flags;
110+
int bits = 32;
111+
int fd;
112+
const char *ptr;
113+
char file_name[100];
114+
int width;
115+
void *kvaddr;
116+
mm_segment_t old_fs;
117+
u32 format = dump_info->pixel_format;
118+
119+
switch (format) {
120+
case DRM_FORMAT_XRGB8888:
121+
case DRM_FORMAT_ARGB8888:
122+
case DRM_FORMAT_XBGR8888:
123+
case DRM_FORMAT_ABGR8888:
124+
bits = 32;
125+
break;
126+
case DRM_FORMAT_RGB888:
127+
case DRM_FORMAT_BGR888:
128+
case DRM_FORMAT_NV24:
129+
case DRM_FORMAT_NV24_10:
130+
bits = 24;
131+
break;
132+
case DRM_FORMAT_RGB565:
133+
case DRM_FORMAT_BGR565:
134+
case DRM_FORMAT_NV16:
135+
case DRM_FORMAT_NV16_10:
136+
bits = 16;
137+
break;
138+
case DRM_FORMAT_NV12:
139+
case DRM_FORMAT_NV12_10:
140+
bits = 12;
141+
break;
142+
default:
143+
DRM_ERROR("unsupport format[%08x]\n", format);
144+
return -1;
145+
}
146+
147+
if (dump_info->yuv_format) {
148+
width = dump_info->pitches;
149+
flags = O_RDWR | O_CREAT | O_APPEND;
150+
snprintf(file_name, 100, "%s/video%d_%d_%s.%s", DUMP_BUF_PATH,
151+
width, dump_info->height, get_format_str(format),
152+
"bin");
153+
} else {
154+
width = dump_info->pitches >> 2;
155+
flags = O_RDWR | O_CREAT;
156+
snprintf(file_name, 100, "%s/win%d_area%d_%dx%d_%s%s%d.%s",
157+
DUMP_BUF_PATH, dump_info->win_id,
158+
dump_info->area_id, width, dump_info->height,
159+
get_format_str(format), dump_info->AFBC_flag ?
160+
"_AFBC_" : "_", frame_count, "bin");
161+
}
162+
kvaddr = vmap(dump_info->pages, dump_info->num_pages, VM_MAP,
163+
pgprot_writecombine(PAGE_KERNEL));
164+
if (!kvaddr)
165+
DRM_ERROR("failed to vmap() buffer\n");
166+
else
167+
kvaddr += dump_info->offset;
168+
old_fs = get_fs();
169+
set_fs(KERNEL_DS);
170+
sys_mkdir(DUMP_BUF_PATH, 0700);
171+
ptr = file_name;
172+
fd = sys_open(ptr, flags, 0644);
173+
if (fd >= 0) {
174+
sys_write(fd, kvaddr, width * dump_info->height * bits >> 3);
175+
DRM_INFO("dump file name is:%s\n", file_name);
176+
sys_close(fd);
177+
} else {
178+
DRM_INFO("writ fail fd err fd is %d\n", fd);
179+
}
180+
set_fs(old_fs);
181+
vunmap(kvaddr);
182+
return 0;
183+
}
184+
185+
static int vop_dump_show(struct seq_file *m, void *data)
186+
{
187+
seq_puts(m, " echo dump > dump to dump one frame\n");
188+
seq_puts(m, " echo dumpon > dump to start vop keep dumping\n");
189+
seq_puts(m, " echo dumpoff > dump to stop keep dumping\n");
190+
seq_puts(m, " echo dumpn > dump n is the number of dump times\n");
191+
seq_puts(m, " dump path is /data/vop_buf\n");
192+
seq_puts(m, " if fd err = -3 try rm -r /data/vopbuf echo dump1 > dump can fix it\n");
193+
seq_puts(m, " if fd err = -28 save needed data try rm -r /data/vopbuf\n");
194+
return 0;
195+
}
196+
197+
static int vop_dump_open(struct inode *inode, struct file *file)
198+
{
199+
struct drm_crtc *crtc = inode->i_private;
200+
201+
return single_open(file, vop_dump_show, crtc);
202+
}
203+
204+
static int temp_pow(int sum, int n)
205+
{
206+
int i;
207+
int temp = sum;
74208

209+
if (n < 1)
210+
return 1;
211+
for (i = 1; i < n ; i++)
212+
sum *= temp;
213+
return sum;
214+
}
215+
216+
static ssize_t vop_dump_write(struct file *file, const char __user *ubuf,
217+
size_t len, loff_t *offp)
218+
{
219+
struct seq_file *m = file->private_data;
220+
struct drm_crtc *crtc = m->private;
221+
char buf[14];
222+
int dump_times = 0;
223+
struct vop_dump_list *pos, *n;
224+
int i = 0;
225+
226+
if (len > sizeof(buf) - 1)
227+
return -EINVAL;
228+
if (copy_from_user(buf, ubuf, len))
229+
return -EFAULT;
230+
buf[len - 1] = '\0';
231+
if (strncmp(buf, "dumpon", 6) == 0) {
232+
crtc->vop_dump_status = DUMP_KEEP;
233+
DRM_INFO("keep dumping\n");
234+
} else if (strncmp(buf, "dumpoff", 7) == 0) {
235+
crtc->vop_dump_status = DUMP_DISABLE;
236+
DRM_INFO("close keep dumping\n");
237+
} else if (strncmp(buf, "dump", 4) == 0) {
238+
if (isdigit(buf[4])) {
239+
for (i = 4; i < strlen(buf); i++) {
240+
dump_times += temp_pow(10, (strlen(buf)
241+
- i - 1))
242+
* (buf[i] - '0');
243+
}
244+
crtc->vop_dump_times = dump_times;
245+
} else {
246+
drm_modeset_lock_all(crtc->dev);
247+
list_for_each_entry_safe(pos, n,
248+
&crtc->vop_dump_list_head,
249+
entry) {
250+
vop_plane_dump(&pos->dump_info,
251+
crtc->frame_count);
252+
}
253+
drm_modeset_unlock_all(crtc->dev);
254+
crtc->frame_count++;
255+
}
256+
} else {
257+
return -EINVAL;
258+
}
259+
return len;
260+
}
261+
262+
static const struct file_operations drm_vopdump_fops = {
263+
.owner = THIS_MODULE,
264+
.open = vop_dump_open,
265+
.read = seq_read,
266+
.llseek = seq_lseek,
267+
.release = single_release,
268+
.write = vop_dump_write,
269+
};
270+
271+
int drm_debugfs_vop_add(struct drm_crtc *crtc, struct dentry *root)
272+
{
273+
struct dentry *vop_dump_root;
274+
struct dentry *ent;
275+
276+
vop_dump_root = debugfs_create_dir("vop_dump", root);
277+
crtc->vop_dump_status = DUMP_DISABLE;
278+
crtc->vop_dump_list_init_flag = false;
279+
crtc->vop_dump_times = 0;
280+
crtc->frame_count = 0;
281+
ent = debugfs_create_file("dump", 0644, vop_dump_root,
282+
crtc, &drm_vopdump_fops);
283+
if (!ent) {
284+
DRM_ERROR("create vop_plane_dump err\n");
285+
debugfs_remove_recursive(vop_dump_root);
286+
}
287+
return 0;
288+
}
289+
#endif
75290
/**
76291
* Initialize a given set of debugfs files for a device
77292
*

drivers/gpu/drm/rockchip/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ config DRM_ROCKCHIP
1616
2D or 3D acceleration; acceleration is performed by other
1717
IP found on the SoC.
1818

19+
config ROCKCHIP_DRM_DEBUG
20+
tristate "Rockchip DRM debug"
21+
depends on DRM_ROCKCHIP
22+
help
23+
This option add a debug nod to dump buf from application.
24+
dump path: /data/vop_buf
25+
debug nod: d/dri/0/ff900000.vop/vop_dump/dump
26+
echo dump > dump to dump one frame
27+
echo dumpon > dump to start vop keep dumping
28+
echo dumpoff > dump to stop keep dumping
29+
echo dumpn > dump n is the number of dump times
30+
if fd err -3 try rm -r /data/vopbuf echo dump1 > dump can fix it
31+
if fd err -28 save needed data try rm -r /data/vopbuf
32+
1933
config ROCKCHIP_CDN_DP
2034
tristate "Rockchip cdn DP"
2135
depends on DRM_ROCKCHIP

drivers/gpu/drm/rockchip/rockchip_drm_fb.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,6 @@
2727
#include "rockchip_drm_gem.h"
2828
#include "rockchip_drm_backlight.h"
2929

30-
#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
31-
32-
struct rockchip_drm_fb {
33-
struct drm_framebuffer fb;
34-
dma_addr_t dma_addr[ROCKCHIP_MAX_FB_BUFFER];
35-
void *kvaddr[ROCKCHIP_MAX_FB_BUFFER];
36-
struct drm_gem_object *obj[ROCKCHIP_MAX_FB_BUFFER];
37-
struct rockchip_logo *logo;
38-
};
39-
4030
bool rockchip_fb_is_logo(struct drm_framebuffer *fb)
4131
{
4232
struct rockchip_drm_fb *rk_fb = to_rockchip_fb(fb);

drivers/gpu/drm/rockchip/rockchip_drm_fb.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,13 @@ rockchip_dmcfreq_vop_bandwidth_update(struct devfreq *devfreq,
5353
}
5454
#endif
5555

56+
#define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
57+
58+
struct rockchip_drm_fb {
59+
struct drm_framebuffer fb;
60+
dma_addr_t dma_addr[ROCKCHIP_MAX_FB_BUFFER];
61+
void *kvaddr[ROCKCHIP_MAX_FB_BUFFER];
62+
struct drm_gem_object *obj[ROCKCHIP_MAX_FB_BUFFER];
63+
struct rockchip_logo *logo;
64+
};
5665
#endif /* _ROCKCHIP_DRM_FB_H */

drivers/gpu/drm/rockchip/rockchip_drm_vop.c

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ struct vop_plane_state {
178178
bool enable;
179179
int global_alpha;
180180
int blend_mode;
181+
unsigned long offset;
181182
};
182183

183184
struct vop_win {
@@ -1531,6 +1532,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
15311532
}
15321533

15331534
offset = (src->x1 >> 16) * drm_format_plane_bpp(fb->pixel_format, 0) / 8;
1535+
vop_plane_state->offset = offset + fb->offsets[0];
15341536
if (state->rotation & BIT(DRM_REFLECT_Y) ||
15351537
(rockchip_fb_is_logo(fb) && vop_plane_state->logo_ymirror))
15361538
offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
@@ -1626,6 +1628,29 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
16261628
uint32_t val;
16271629
bool rb_swap, global_alpha_en;
16281630

1631+
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
1632+
bool AFBC_flag = false;
1633+
struct vop_dump_list *planlist;
1634+
unsigned long num_pages;
1635+
struct page **pages;
1636+
struct rockchip_drm_fb *rk_fb;
1637+
struct drm_gem_object *obj;
1638+
struct rockchip_gem_object *rk_obj;
1639+
1640+
num_pages = 0;
1641+
pages = NULL;
1642+
rk_fb = to_rockchip_fb(fb);
1643+
obj = rk_fb->obj[0];
1644+
rk_obj = to_rockchip_obj(obj);
1645+
if (rk_obj) {
1646+
num_pages = rk_obj->num_pages;
1647+
pages = rk_obj->pages;
1648+
}
1649+
if (fb->modifier[0] == DRM_FORMAT_MOD_ARM_AFBC)
1650+
AFBC_flag = true;
1651+
else
1652+
AFBC_flag = false;
1653+
#endif
16291654
/*
16301655
* can't update plane when vop is disabled.
16311656
*/
@@ -1728,6 +1753,32 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
17281753
* actual_w, actual_h)
17291754
*/
17301755
vop->is_iommu_needed = true;
1756+
1757+
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
1758+
planlist = kmalloc(sizeof(*planlist), GFP_KERNEL);
1759+
if (planlist) {
1760+
planlist->dump_info.AFBC_flag = AFBC_flag;
1761+
planlist->dump_info.area_id = win->area_id;
1762+
planlist->dump_info.win_id = win->win_id;
1763+
planlist->dump_info.yuv_format =
1764+
is_yuv_support(fb->pixel_format);
1765+
planlist->dump_info.num_pages = num_pages;
1766+
planlist->dump_info.pages = pages;
1767+
planlist->dump_info.offset = vop_plane_state->offset;
1768+
planlist->dump_info.pitches = fb->pitches[0];
1769+
planlist->dump_info.height = actual_h;
1770+
planlist->dump_info.pixel_format = fb->pixel_format;
1771+
list_add_tail(&planlist->entry, &crtc->vop_dump_list_head);
1772+
} else {
1773+
DRM_ERROR("can't alloc a node of planlist %p\n", planlist);
1774+
return;
1775+
}
1776+
if (crtc->vop_dump_status == DUMP_KEEP ||
1777+
crtc->vop_dump_times > 0) {
1778+
vop_plane_dump(&planlist->dump_info, crtc->frame_count);
1779+
crtc->vop_dump_times--;
1780+
}
1781+
#endif
17311782
}
17321783

17331784
static const struct drm_plane_helper_funcs plane_helper_funcs = {
@@ -2145,7 +2196,9 @@ static int vop_crtc_debugfs_init(struct drm_minor *minor, struct drm_crtc *crtc)
21452196
ret = -ENOMEM;
21462197
goto remove;
21472198
}
2148-
2199+
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2200+
drm_debugfs_vop_add(crtc, vop->debugfs);
2201+
#endif
21492202
for (i = 0; i < ARRAY_SIZE(vop_debugfs_files); i++)
21502203
vop->debugfs_files[i].data = vop;
21512204

@@ -2830,6 +2883,23 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc,
28302883
int dsp_layer_sel = 0;
28312884
int i, j, cnt = 0, ret = 0;
28322885

2886+
#if defined(CONFIG_ROCKCHIP_DRM_DEBUG)
2887+
struct vop_dump_list *pos, *n;
2888+
2889+
if (!crtc->vop_dump_list_init_flag) {
2890+
INIT_LIST_HEAD(&crtc->vop_dump_list_head);
2891+
crtc->vop_dump_list_init_flag = true;
2892+
}
2893+
list_for_each_entry_safe(pos, n, &crtc->vop_dump_list_head, entry) {
2894+
list_del(&pos->entry);
2895+
kfree(pos);
2896+
}
2897+
if (crtc->vop_dump_status == DUMP_KEEP ||
2898+
crtc->vop_dump_times > 0) {
2899+
crtc->frame_count++;
2900+
}
2901+
#endif
2902+
28332903
ret = vop_afbdc_atomic_check(crtc, crtc_state);
28342904
if (ret)
28352905
return ret;

0 commit comments

Comments
 (0)