diff options
author | Lael Jones <lajones@nvidia.com> | 2014-03-14 09:43:56 -0700 |
---|---|---|
committer | Bo Yan <byan@nvidia.com> | 2014-03-25 14:03:37 -0700 |
commit | ded1580ceca63d5923c83b42324bbc07c1ede5e1 (patch) | |
tree | 71207bf6aecf879781d24c60bf2b4632e15291fc /drivers/misc | |
parent | 7521a15df5f63c8b41b9f7e6896d751ea8e7a33f (diff) |
misc: mods: Add MODS debugfs interface
Add export of Tegra DC driver features
through the MODS debugfs interface
Signed-off-by: Lael Jones <lajones@nvidia.com>
Change-Id: Ibc3b3a031aca1339fd9b02db816a38b4c32d6730
Reviewed-on: http://git-master/r/382091
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-by: Dan Merget <dmerget@nvidia.com>
Reviewed-by: Chris Dragan <kdragan@nvidia.com>
Tested-by: Chris Dragan <kdragan@nvidia.com>
Reviewed-by: Bo Yan <byan@nvidia.com>
Tested-by: Bo Yan <byan@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/mods/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/mods/mods_debugfs.c | 345 | ||||
-rw-r--r-- | drivers/misc/mods/mods_internal.h | 12 | ||||
-rw-r--r-- | drivers/misc/mods/mods_krnl.c | 7 |
4 files changed, 365 insertions, 0 deletions
diff --git a/drivers/misc/mods/Makefile b/drivers/misc/mods/Makefile index 986d2d142f82..0880c2509e1f 100644 --- a/drivers/misc/mods/Makefile +++ b/drivers/misc/mods/Makefile @@ -5,3 +5,4 @@ mods-y += mods_irq.o mods-$(CONFIG_PCI) += mods_pci.o mods-$(CONFIG_ACPI) += mods_acpi.o mods-$(CONFIG_ARCH_TEGRA) += mods_clock.o +mods-$(CONFIG_DEBUG_FS) += mods_debugfs.o diff --git a/drivers/misc/mods/mods_debugfs.c b/drivers/misc/mods/mods_debugfs.c new file mode 100644 index 000000000000..942030224f41 --- /dev/null +++ b/drivers/misc/mods/mods_debugfs.c @@ -0,0 +1,345 @@ +/* + * mods_debugfs.c - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +#ifdef CONFIG_TEGRA_DC +#include <../drivers/video/tegra/dc/dc_config.h> +#endif + +static struct dentry *mods_debugfs_dir; + +#ifdef CONFIG_TEGRA_DC +static int mods_dc_color_formats_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + u32 i, j; + + for (i = 0; i < DC_N_WINDOWS; i++) { + struct tegra_dc_win *win; + u32 *fmt_masks; + win = tegra_dc_get_window(dc, i); + if (!win) + continue; + fmt_masks = tegra_dc_parse_feature(dc, i, GET_WIN_FORMATS); + if (!fmt_masks) + continue; + seq_printf(s, "window_%u:", i); + for (j = 0; j < ENTRY_SIZE; j++) + seq_printf(s, " 0x%08x", fmt_masks[j]); + seq_puts(s, "\n"); + } + return 0; +} + +static int mods_dc_color_formats_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_color_formats_show, inode->i_private); +} + +static const struct file_operations mods_dc_color_formats_fops = { + .open = mods_dc_color_formats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mods_dc_blend_gen_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + u32 i; + + for (i = 0; i < DC_N_WINDOWS; i++) { + struct tegra_dc_win *win; + u32 *blend_gen; + win = tegra_dc_get_window(dc, i); + if (!win) + continue; + blend_gen = tegra_dc_parse_feature(dc, i, HAS_GEN2_BLEND); + if (!blend_gen) + continue; + seq_printf(s, "window_%u: %u\n", i, + blend_gen[BLEND_GENERATION]); + } + return 0; +} + +static int mods_dc_blend_gen_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_blend_gen_show, inode->i_private); +} + +static const struct file_operations mods_dc_blend_gen_fops = { + .open = mods_dc_blend_gen_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mods_dc_layout_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + u32 i; + + seq_puts(s, " Pitch Tiled Block\n"); + for (i = 0; i < DC_N_WINDOWS; i++) { + struct tegra_dc_win *win; + u32 *layouts; + win = tegra_dc_get_window(dc, i); + if (!win) + continue; + layouts = tegra_dc_parse_feature(dc, i, HAS_TILED); + if (!layouts) + continue; + seq_printf(s, "window_%u: %5u %5u %5u\n", i, + layouts[PITCHED_LAYOUT], + layouts[TILED_LAYOUT], + layouts[BLOCK_LINEAR]); + } + return 0; +} + +static int mods_dc_layout_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_layout_show, inode->i_private); +} + +static const struct file_operations mods_dc_layout_fops = { + .open = mods_dc_layout_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mods_dc_invert_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + u32 i; + + seq_puts(s, " FlipH FlipV ScanColumn\n"); + for (i = 0; i < DC_N_WINDOWS; i++) { + struct tegra_dc_win *win; + u32 *invert_data; + win = tegra_dc_get_window(dc, i); + if (!win) + continue; + invert_data = tegra_dc_parse_feature(dc, i, GET_INVERT); + if (!invert_data) + continue; + seq_printf(s, "window_%u: %5u %5u %10u\n", i, + invert_data[H_INVERT], + invert_data[V_INVERT], + invert_data[SCAN_COLUMN]); + } + return 0; +} + +static int mods_dc_invert_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_invert_show, inode->i_private); +} + +static const struct file_operations mods_dc_invert_fops = { + .open = mods_dc_invert_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mods_dc_interlaced_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + u32 i; +#ifdef CONFIG_TEGRA_DC_INTERLACE + const unsigned head_interlaced = 1; +#else + const unsigned head_interlaced = 0; +#endif + + seq_printf(s, "head: %u\n", head_interlaced); + for (i = 0; i < DC_N_WINDOWS; i++) { + struct tegra_dc_win *win; + u32 *interlaced; + win = tegra_dc_get_window(dc, i); + if (!win) + continue; + interlaced = tegra_dc_parse_feature(dc, i, HAS_INTERLACE); + if (!interlaced) + continue; + seq_printf(s, "window_%u: %u\n", i, interlaced[0]); + } + return 0; +} + +static int mods_dc_interlaced_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_interlaced_show, inode->i_private); +} + +static const struct file_operations mods_dc_interlaced_fops = { + .open = mods_dc_interlaced_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mods_dc_window_mask_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + seq_printf(s, "0x%02lx\n", dc->valid_windows); + return 0; +} + +static int mods_dc_window_mask_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_window_mask_show, inode->i_private); +} + +static const struct file_operations mods_dc_window_mask_fops = { + .open = mods_dc_window_mask_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int mods_dc_scaling_show(struct seq_file *s, void *unused) +{ + struct tegra_dc *dc = s->private; + u32 i; + + seq_puts(s, " UpH UpV DownH DownV\n"); + for (i = 0; i < DC_N_WINDOWS; i++) { + struct tegra_dc_win *win; + u32 *scaling; + win = tegra_dc_get_window(dc, i); + if (!win) + continue; + scaling = tegra_dc_parse_feature(dc, i, HAS_SCALE); + if (!scaling) + continue; + seq_printf(s, "window_%u: %3u %3u %5u %5u\n", i, + scaling[H_SCALE_UP], + scaling[V_SCALE_UP], + scaling[H_FILTER_DOWN], + scaling[V_FILTER_DOWN]); + } + return 0; +} + +static int mods_dc_scaling_open(struct inode *inode, struct file *file) +{ + return single_open(file, mods_dc_scaling_show, inode->i_private); +} + +static const struct file_operations mods_dc_scaling_fops = { + .open = mods_dc_scaling_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +void mods_remove_debugfs(void) +{ + debugfs_remove_recursive(mods_debugfs_dir); + mods_debugfs_dir = NULL; +} + +int mods_create_debugfs(struct miscdevice *modsdev) +{ + struct dentry *retval; +#ifdef CONFIG_TEGRA_DC + unsigned dc_idx; +#endif + int err = 0; + + mods_debugfs_dir = debugfs_create_dir(dev_name(modsdev->this_device), + NULL); + if (IS_ERR(mods_debugfs_dir)) { + err = -EIO; + goto remove_out; + } + +#ifdef CONFIG_TEGRA_DC + for (dc_idx = 0; dc_idx < TEGRA_MAX_DC; dc_idx++) { + struct dentry *dc_debugfs_dir; + struct tegra_dc *dc = tegra_dc_get_dc(dc_idx); + if (!dc) + continue; + + dc_debugfs_dir = debugfs_create_dir(dev_name(&dc->ndev->dev), + mods_debugfs_dir); + if (IS_ERR(dc_debugfs_dir)) { + err = -EIO; + goto remove_out; + } + + retval = debugfs_create_file("window_mask", S_IRUGO, + dc_debugfs_dir, dc, &mods_dc_window_mask_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("color_formats", S_IRUGO, + dc_debugfs_dir, dc, &mods_dc_color_formats_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("blend_gen", S_IRUGO, + dc_debugfs_dir, dc, &mods_dc_blend_gen_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("layout", S_IRUGO, dc_debugfs_dir, + dc, &mods_dc_layout_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("invert", S_IRUGO, dc_debugfs_dir, + dc, &mods_dc_invert_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("interlaced", S_IRUGO, + dc_debugfs_dir, dc, &mods_dc_interlaced_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + retval = debugfs_create_file("scaling", S_IRUGO, dc_debugfs_dir, + dc, &mods_dc_scaling_fops); + if (IS_ERR(retval)) { + err = -EIO; + goto remove_out; + } + } +#endif + + return 0; +remove_out: + dev_err(modsdev->this_device, "could not create debugfs\n"); + mods_remove_debugfs(); + return err; +} + diff --git a/drivers/misc/mods/mods_internal.h b/drivers/misc/mods/mods_internal.h index 2e24db672b85..0b64717c767e 100644 --- a/drivers/misc/mods/mods_internal.h +++ b/drivers/misc/mods/mods_internal.h @@ -24,6 +24,7 @@ #include <linux/list.h> #include <linux/pci.h> #include <linux/slab.h> +#include <linux/miscdevice.h> #define NvU8 u8 #define NvU16 u16 @@ -443,4 +444,15 @@ int esc_mods_flush_cpu_cache_range(struct file *, struct MODS_FLUSH_CPU_CACHE_RANGE *); #endif +#ifdef CONFIG_DEBUG_FS +int mods_create_debugfs(struct miscdevice *modsdev); +void mods_remove_debugfs(void); +#else +static inline int mods_create_debugfs(struct miscdevice *modsdev) +{ + return 0; +} +static inline void mods_remove_debugfs(void) {} +#endif /* CONFIG_DEBUG_FS */ + #endif /* _MODS_INTERNAL_H_ */ diff --git a/drivers/misc/mods/mods_krnl.c b/drivers/misc/mods/mods_krnl.c index f1ac5c695cf9..b17a4f278d00 100644 --- a/drivers/misc/mods/mods_krnl.c +++ b/drivers/misc/mods/mods_krnl.c @@ -94,6 +94,10 @@ static int __init mods_init_module(void) mods_init_clock_api(); #endif + rc = mods_create_debugfs(&mods_dev); + if (rc < 0) + return rc; + mods_info_printk("driver loaded, version %x.%02x\n", (MODS_DRIVER_VERSION>>8), (MODS_DRIVER_VERSION&0xFF)); @@ -104,6 +108,9 @@ static int __init mods_init_module(void) static void __exit mods_exit_module(void) { LOG_ENT(); + + mods_remove_debugfs(); + mods_cleanup_irq(); misc_deregister(&mods_dev); |