aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-01-31 04:02:15 -0500
committerThierry Reding <treding@nvidia.com>2014-06-05 17:09:17 -0400
commita82752e19954cb741a7a582482e5c05c50d7acd3 (patch)
treef32dd92bc20b9060c8d6a4254c4068c94502ae09
parentf925390efccb24016a4fafe77721770021ed754a (diff)
drm/tegra: sor - Add CRC debugfs support
The SOR allows the computation of a 32 bit CRC of the content that it transmits. This functionality is exposed via debugfs and is useful to verify proper operation of the SOR. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/sor.c121
-rw-r--r--drivers/gpu/drm/tegra/sor.h4
2 files changed, 125 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 49ef5729f435..b2151ea679f0 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -7,6 +7,7 @@
7 */ 7 */
8 8
9#include <linux/clk.h> 9#include <linux/clk.h>
10#include <linux/debugfs.h>
10#include <linux/io.h> 11#include <linux/io.h>
11#include <linux/platform_device.h> 12#include <linux/platform_device.h>
12#include <linux/reset.h> 13#include <linux/reset.h>
@@ -34,6 +35,8 @@ struct tegra_sor {
34 struct tegra_dpaux *dpaux; 35 struct tegra_dpaux *dpaux;
35 36
36 bool enabled; 37 bool enabled;
38
39 struct dentry *debugfs;
37}; 40};
38 41
39static inline struct tegra_sor * 42static inline struct tegra_sor *
@@ -914,6 +917,110 @@ static const struct tegra_output_ops sor_ops = {
914 .detect = tegra_output_sor_detect, 917 .detect = tegra_output_sor_detect,
915}; 918};
916 919
920static int tegra_sor_crc_open(struct inode *inode, struct file *file)
921{
922 file->private_data = inode->i_private;
923
924 return 0;
925}
926
927static int tegra_sor_crc_release(struct inode *inode, struct file *file)
928{
929 return 0;
930}
931
932static int tegra_sor_crc_wait(struct tegra_sor *sor, unsigned long timeout)
933{
934 u32 value;
935
936 timeout = jiffies + msecs_to_jiffies(timeout);
937
938 while (time_before(jiffies, timeout)) {
939 value = tegra_sor_readl(sor, SOR_CRC_A);
940 if (value & SOR_CRC_A_VALID)
941 return 0;
942
943 usleep_range(100, 200);
944 }
945
946 return -ETIMEDOUT;
947}
948
949static ssize_t tegra_sor_crc_read(struct file *file, char __user *buffer,
950 size_t size, loff_t *ppos)
951{
952 struct tegra_sor *sor = file->private_data;
953 char buf[10];
954 ssize_t num;
955 u32 value;
956 int err;
957
958 value = tegra_sor_readl(sor, SOR_STATE_1);
959 value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
960 tegra_sor_writel(sor, value, SOR_STATE_1);
961
962 value = tegra_sor_readl(sor, SOR_CRC_CNTRL);
963 value |= SOR_CRC_CNTRL_ENABLE;
964 tegra_sor_writel(sor, value, SOR_CRC_CNTRL);
965
966 value = tegra_sor_readl(sor, SOR_TEST);
967 value &= ~SOR_TEST_CRC_POST_SERIALIZE;
968 tegra_sor_writel(sor, value, SOR_TEST);
969
970 err = tegra_sor_crc_wait(sor, 100);
971 if (err < 0)
972 return err;
973
974 tegra_sor_writel(sor, SOR_CRC_A_RESET, SOR_CRC_A);
975 value = tegra_sor_readl(sor, SOR_CRC_B);
976
977 num = scnprintf(buf, sizeof(buf), "%08x\n", value);
978
979 return simple_read_from_buffer(buffer, size, ppos, buf, num);
980}
981
982static const struct file_operations tegra_sor_crc_fops = {
983 .owner = THIS_MODULE,
984 .open = tegra_sor_crc_open,
985 .read = tegra_sor_crc_read,
986 .release = tegra_sor_crc_release,
987};
988
989static int tegra_sor_debugfs_init(struct tegra_sor *sor, struct dentry *root)
990{
991 struct dentry *entry;
992 int err = 0;
993
994 sor->debugfs = debugfs_create_dir("sor", root);
995 if (!sor->debugfs)
996 return -ENOMEM;
997
998 entry = debugfs_create_file("crc", 0644, sor->debugfs, sor,
999 &tegra_sor_crc_fops);
1000 if (!entry) {
1001 dev_err(sor->dev,
1002 "cannot create /sys/kernel/debug/dri/%s/sor/crc\n",
1003 root->d_name.name);
1004 err = -ENOMEM;
1005 goto remove;
1006 }
1007
1008 return err;
1009
1010remove:
1011 debugfs_remove(sor->debugfs);
1012 sor->debugfs = NULL;
1013 return err;
1014}
1015
1016static int tegra_sor_debugfs_exit(struct tegra_sor *sor)
1017{
1018 debugfs_remove(sor->debugfs);
1019 sor->debugfs = NULL;
1020
1021 return 0;
1022}
1023
917static int tegra_sor_init(struct host1x_client *client) 1024static int tegra_sor_init(struct host1x_client *client)
918{ 1025{
919 struct tegra_drm *tegra = dev_get_drvdata(client->parent); 1026 struct tegra_drm *tegra = dev_get_drvdata(client->parent);
@@ -934,6 +1041,14 @@ static int tegra_sor_init(struct host1x_client *client)
934 return err; 1041 return err;
935 } 1042 }
936 1043
1044 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1045 struct dentry *root = tegra->drm->primary->debugfs_root;
1046
1047 err = tegra_sor_debugfs_init(sor, root);
1048 if (err < 0)
1049 dev_err(sor->dev, "debugfs setup failed: %d\n", err);
1050 }
1051
937 if (sor->dpaux) { 1052 if (sor->dpaux) {
938 err = tegra_dpaux_attach(sor->dpaux, &sor->output); 1053 err = tegra_dpaux_attach(sor->dpaux, &sor->output);
939 if (err < 0) { 1054 if (err < 0) {
@@ -964,6 +1079,12 @@ static int tegra_sor_exit(struct host1x_client *client)
964 } 1079 }
965 } 1080 }
966 1081
1082 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1083 err = tegra_sor_debugfs_exit(sor);
1084 if (err < 0)
1085 dev_err(sor->dev, "debugfs cleanup failed: %d\n", err);
1086 }
1087
967 err = tegra_output_exit(&sor->output); 1088 err = tegra_output_exit(&sor->output);
968 if (err < 0) { 1089 if (err < 0) {
969 dev_err(sor->dev, "output cleanup failed: %d\n", err); 1090 dev_err(sor->dev, "output cleanup failed: %d\n", err);
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h
index f4156d54cd05..a5f8853fedb5 100644
--- a/drivers/gpu/drm/tegra/sor.h
+++ b/drivers/gpu/drm/tegra/sor.h
@@ -47,6 +47,7 @@
47#define SOR_HEAD_STATE_4(x) (0x0d + (x)) 47#define SOR_HEAD_STATE_4(x) (0x0d + (x))
48#define SOR_HEAD_STATE_5(x) (0x0f + (x)) 48#define SOR_HEAD_STATE_5(x) (0x0f + (x))
49#define SOR_CRC_CNTRL 0x11 49#define SOR_CRC_CNTRL 0x11
50#define SOR_CRC_CNTRL_ENABLE (1 << 0)
50#define SOR_DP_DEBUG_MVID 0x12 51#define SOR_DP_DEBUG_MVID 0x12
51 52
52#define SOR_CLK_CNTRL 0x13 53#define SOR_CLK_CNTRL 0x13
@@ -69,6 +70,7 @@
69#define SOR_PWR_NORMAL_STATE_PU (1 << 0) 70#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
70 71
71#define SOR_TEST 0x16 72#define SOR_TEST 0x16
73#define SOR_TEST_CRC_POST_SERIALIZE (1 << 23)
72#define SOR_TEST_ATTACHED (1 << 10) 74#define SOR_TEST_ATTACHED (1 << 10)
73#define SOR_TEST_HEAD_MODE_MASK (3 << 8) 75#define SOR_TEST_HEAD_MODE_MASK (3 << 8)
74#define SOR_TEST_HEAD_MODE_AWAKE (2 << 8) 76#define SOR_TEST_HEAD_MODE_AWAKE (2 << 8)
@@ -115,6 +117,8 @@
115 117
116#define SOR_LVDS 0x1c 118#define SOR_LVDS 0x1c
117#define SOR_CRC_A 0x1d 119#define SOR_CRC_A 0x1d
120#define SOR_CRC_A_VALID (1 << 0)
121#define SOR_CRC_A_RESET (1 << 0)
118#define SOR_CRC_B 0x1e 122#define SOR_CRC_B 0x1e
119#define SOR_BLANK 0x1f 123#define SOR_BLANK 0x1f
120#define SOR_SEQ_CTL 0x20 124#define SOR_SEQ_CTL 0x20