From: Pawel O. <p.o...@sa...> - 2009-09-11 18:06:38
|
This patch adds debugfs information in s3c-fb directory in debugfs root. Reviewed-by: Marek Szyprowski <m.s...@sa...> Reviewed-by: Kyungmin Park <kyu...@sa...> Signed-off-by: Pawel Osciak <p.o...@sa...> --- drivers/video/Kconfig | 16 +++- drivers/video/s3c-fb.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+), 4 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3b54b39..922a1cb 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1917,10 +1917,18 @@ config FB_S3C Currently the support is only for the S3C6400 and S3C6410 SoCs. config FB_S3C_DEBUG_REGWRITE - bool "Debug register writes" - depends on FB_S3C - ---help--- - Show all register writes via printk(KERN_DEBUG) + bool "Debug register writes" + depends on FB_S3C + ---help--- + Show all register writes via printk(KERN_DEBUG) + +config FB_S3C_DEBUG_FS + bool "Enable debug information in DebugFS" + depends on FB_S3C && DEBUG_FS + default n + ---help--- + Enable this if you want debugging information in debugfs. + If unsure, say N. config FB_S3C2410 tristate "S3C2410 LCD framebuffer support" diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 226d225..6721f20 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -26,6 +26,12 @@ #include <plat/s3c-fb.h> +#ifdef CONFIG_FB_S3C_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#endif + + #include <mach/map.h> #include <mach/regs-fb.h> #include <plat/fb.h> @@ -62,6 +68,11 @@ struct s3c_fb; +#ifdef CONFIG_FB_S3C_DEBUG_FS +static void __devinit s3c_fb_debugfs_init(struct s3c_fb *sfb); +static void __devinit s3c_fb_debugfs_remove(void); +#endif + /** * struct s3c_fb_win - per window private data for each framebuffer. * @windata: The platform data supplied for the window configuration. @@ -1441,6 +1452,10 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sfb); +#ifdef CONFIG_FB_S3C_DEBUG_FS + s3c_fb_debugfs_init(sfb); +#endif + return 0; err_irq: @@ -1474,6 +1489,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) struct s3c_fb *sfb = platform_get_drvdata(pdev); int win; +#ifdef CONFIG_FB_S3C_DEBUG_FS + s3c_fb_debugfs_remove(); +#endif + for (win = 0; win < S3C_FB_MAX_WIN; win++) if (sfb->windows[win]) s3c_fb_release_win(sfb, sfb->windows[win]); @@ -1567,6 +1586,224 @@ static void __exit s3c_fb_cleanup(void) platform_driver_unregister(&s3c_fb_driver); } +/* DEBUGFS */ + +#ifdef CONFIG_FB_S3C_DEBUG_FS +static struct dentry *debugfs_dir; + +static void *dbg_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + int *win_no; + + if (v == SEQ_START_TOKEN) + return pos; + + win_no = (int *)pos; + *win_no += 1; + if (*win_no >= S3C_FB_MAX_WIN) + return NULL; + + return pos; +} + +static int dbg_blend_seq_show(struct seq_file *s, void *v) +{ + struct s3c_fb *sfb = s->private; + int *win_no = v; + u32 vidosdc, wincon; + + if (v == SEQ_START_TOKEN) { + seq_printf(s, "win| mode AEN0 AEN1\n"); + return 0; + } + + if (!s3c_fb_has_alpha(*win_no)) + return SEQ_SKIP; + + seq_printf(s, "%2d | ", *win_no); + + vidosdc = readl(sfb->regs + VIDOSD_C(*win_no)); + wincon = readl(sfb->regs + WINCONx(*win_no)); + if (wincon & WINCONx_BLD_PIX) { + seq_printf(s, " per pixel "); + if (wincon & WINCONx_ALPHA_SEL) + seq_printf(s, "value "); + else + seq_printf(s, "global "); + } else { + seq_printf(s, " global "); + if (wincon & WINCONx_ALPHA_SEL) + seq_printf(s, "val 1 "); + else + seq_printf(s, "val 0 "); + } + seq_printf(s, "%04x %04x\n", + (vidosdc & VIDOSD14C_ALPHA0_MASK) + >> VIDOSD14C_ALPHA0_B_SHIFT, + vidosdc & VIDOSD14C_ALPHA1_MASK); + + return 0; +} + +static int dbg_ckey_seq_show(struct seq_file *s, void *v) +{ + struct s3c_fb *sfb = s->private; + int *win_no = v; + u32 keycon0, keycon1; + + if (v == SEQ_START_TOKEN) { + seq_printf(s, "win| enabled direction value mask\n"); + return 0; + } + + if (!has_colorkey(*win_no)) + return SEQ_SKIP; + + seq_printf(s, "%2d | ", *win_no); + + keycon0 = readl(sfb->regs + WxKEYCON0(*win_no)); + keycon1 = readl(sfb->regs + WxKEYCON1(*win_no)); + + seq_printf(s, " %d ", keycon0 & WxKEYCON0_KEYEN_F); + if (keycon0 & WxKEYCON0_DIRCON) + seq_printf(s, " FG "); + else + seq_printf(s, " BG "); + + seq_printf(s, " %06x ", keycon1 & WxKEYCON1_COLVAL_MASK); + seq_printf(s, "%06x ", keycon0 & WxKEYCON0_COMPKEY_MASK); + seq_printf(s, "\n"); + + return 0; +} + +static inline void *single_start(struct seq_file *p, loff_t *pos) +{ + if (*pos == 0) + return SEQ_START_TOKEN; + + return NULL + (*pos == 0); +} + +static inline void single_stop(struct seq_file *p, void *v) +{ +} + +static const struct seq_operations dbg_blend_seq_ops = { + .start = single_start, + .next = dbg_seq_next, + .stop = single_stop, + .show = dbg_blend_seq_show, +}; + +static const struct seq_operations dbg_ckey_seq_ops = { + .start = single_start, + .next = dbg_seq_next, + .stop = single_stop, + .show = dbg_ckey_seq_show, +}; + +static int dbg_blend_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int ret; + + ret = seq_open(file, &dbg_blend_seq_ops); + if (ret) + return ret; + + seq = file->private_data; + seq->private = inode->i_private; + + return 0; +} + +static const struct file_operations dbg_blend_fops = { + .owner = THIS_MODULE, + .open = dbg_blend_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int dbg_ckey_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int ret; + + ret = seq_open(file, &dbg_ckey_seq_ops); + if (ret) + return ret; + + seq = file->private_data; + seq->private = inode->i_private; + + return 0; +} + +static const struct file_operations dbg_ckey_fops = { + .owner = THIS_MODULE, + .open = dbg_ckey_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int dbg_winen_show(struct seq_file *s, void *v) +{ + struct s3c_fb *sfb = s->private; + int win_no; + + for (win_no = 0; win_no < S3C_FB_MAX_WIN; ++win_no) { + if (sfb->enabled & (1 << win_no)) + seq_printf(s, "Win%d: enabled\n", win_no); + else + seq_printf(s, "Win%d: disabled\n", win_no); + } + + return 0; +} + +static int dbg_winen_open(struct inode *inode, struct file *file) +{ + return single_open(file, dbg_winen_show, inode->i_private); +} + +static const struct file_operations dbg_winen_fops = { + .owner = THIS_MODULE, + .open = dbg_winen_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __devinit s3c_fb_debugfs_init(struct s3c_fb *sfb) +{ + debugfs_dir = debugfs_create_dir("s3c-fb", NULL); + if (! debugfs_dir || IS_ERR(debugfs_dir)) { + dev_warn(sfb->dev, "Could not create debugfs directory\n"); + return; + } + + debugfs_create_file("windows_enabled", S_IRUGO, debugfs_dir, sfb, + &dbg_winen_fops); + + debugfs_create_file("blending", S_IRUGO, debugfs_dir, sfb, + &dbg_blend_fops); + + debugfs_create_file("color_key", S_IRUGO, debugfs_dir, sfb, + &dbg_ckey_fops); +} + +static void __devinit s3c_fb_debugfs_remove(void) +{ + if (debugfs_dir) + debugfs_remove_recursive(debugfs_dir); +} +#endif /* CONFIG_DEBUG_FS */ + +/* DEBUGFS END */ + module_init(s3c_fb_init); module_exit(s3c_fb_cleanup); -- 1.6.4.2.253.g0b1fac |