aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2007-04-21 10:08:41 -0400
committerLen Brown <len.brown@intel.com>2007-04-21 23:30:34 -0400
commit83f34724643a3b0ec9322490b9ad9f1b60170a6c (patch)
treedcd6da273723dc713c920414506212073ffe738d /drivers/misc
parentd6fdd1e91a8a4cd852dc1d945165e3a69ac9e257 (diff)
ACPI: thinkpad-acpi: cleanup video subdriver
Cleanup video subdriver for sysfs conversion, and properly check result status of acpi_evalf. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/thinkpad_acpi.c262
-rw-r--r--drivers/misc/thinkpad_acpi.h25
2 files changed, 197 insertions, 90 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index a77368f90181..19c14bbe8b29 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -935,111 +935,194 @@ static int __init video_init(struct ibm_init_struct *iibm)
935 935
936static void video_exit(void) 936static void video_exit(void)
937{ 937{
938 dbg_printk(TPACPI_DBG_EXIT, "restoring original video autoswitch mode\n"); 938 dbg_printk(TPACPI_DBG_EXIT,
939 acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw); 939 "restoring original video autoswitch mode\n");
940 if (video_autosw_set(video_orig_autosw))
941 printk(IBM_ERR "error while trying to restore original "
942 "video autoswitch mode\n");
940} 943}
941 944
942static int video_status(void) 945static int video_outputsw_get(void)
943{ 946{
944 int status = 0; 947 int status = 0;
945 int i; 948 int i;
946 949
947 if (video_supported == TPACPI_VIDEO_570) { 950 switch (video_supported) {
948 if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87)) 951 case TPACPI_VIDEO_570:
949 status = i & 3; 952 if (!acpi_evalf(NULL, &i, "\\_SB.PHS", "dd",
950 } else if (video_supported == TPACPI_VIDEO_770) { 953 TP_ACPI_VIDEO_570_PHSCMD))
951 if (acpi_evalf(NULL, &i, "\\VCDL", "d")) 954 return -EIO;
952 status |= 0x01 * i; 955 status = i & TP_ACPI_VIDEO_570_PHSMASK;
953 if (acpi_evalf(NULL, &i, "\\VCDC", "d")) 956 break;
954 status |= 0x02 * i; 957 case TPACPI_VIDEO_770:
955 } else if (video_supported == TPACPI_VIDEO_NEW) { 958 if (!acpi_evalf(NULL, &i, "\\VCDL", "d"))
956 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1); 959 return -EIO;
957 if (acpi_evalf(NULL, &i, "\\VCDC", "d")) 960 if (i)
958 status |= 0x02 * i; 961 status |= TP_ACPI_VIDEO_S_LCD;
959 962 if (!acpi_evalf(NULL, &i, "\\VCDC", "d"))
960 acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0); 963 return -EIO;
961 if (acpi_evalf(NULL, &i, "\\VCDL", "d")) 964 if (i)
962 status |= 0x01 * i; 965 status |= TP_ACPI_VIDEO_S_CRT;
963 if (acpi_evalf(NULL, &i, "\\VCDD", "d")) 966 break;
964 status |= 0x08 * i; 967 case TPACPI_VIDEO_NEW:
968 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1) ||
969 !acpi_evalf(NULL, &i, "\\VCDC", "d"))
970 return -EIO;
971 if (i)
972 status |= TP_ACPI_VIDEO_S_CRT;
973
974 if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0) ||
975 !acpi_evalf(NULL, &i, "\\VCDL", "d"))
976 return -EIO;
977 if (i)
978 status |= TP_ACPI_VIDEO_S_LCD;
979 if (!acpi_evalf(NULL, &i, "\\VCDD", "d"))
980 return -EIO;
981 if (i)
982 status |= TP_ACPI_VIDEO_S_DVI;
983 break;
984 default:
985 return -ENOSYS;
965 } 986 }
966 987
967 return status; 988 return status;
968} 989}
969 990
970static int video_autosw(void) 991static int video_outputsw_set(int status)
971{ 992{
972 int autosw = 0; 993 int autosw;
994 int res = 0;
973 995
974 if (video_supported == TPACPI_VIDEO_570) 996 switch (video_supported) {
975 acpi_evalf(vid_handle, &autosw, "SWIT", "d"); 997 case TPACPI_VIDEO_570:
976 else if (video_supported == TPACPI_VIDEO_770 || 998 res = acpi_evalf(NULL, NULL,
977 video_supported == TPACPI_VIDEO_NEW) 999 "\\_SB.PHS2", "vdd",
978 acpi_evalf(vid_handle, &autosw, "^VDEE", "d"); 1000 TP_ACPI_VIDEO_570_PHS2CMD,
1001 status | TP_ACPI_VIDEO_570_PHS2SET);
1002 break;
1003 case TPACPI_VIDEO_770:
1004 autosw = video_autosw_get();
1005 if (autosw < 0)
1006 return autosw;
979 1007
980 return autosw & 1; 1008 res = video_autosw_set(1);
1009 if (res)
1010 return res;
1011 res = acpi_evalf(vid_handle, NULL,
1012 "ASWT", "vdd", status * 0x100, 0);
1013 if (!autosw && video_autosw_set(autosw)) {
1014 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1015 return -EIO;
1016 }
1017 break;
1018 case TPACPI_VIDEO_NEW:
1019 res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
1020 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
1021 break;
1022 default:
1023 return -ENOSYS;
1024 }
1025
1026 return (res)? 0 : -EIO;
981} 1027}
982 1028
983static int video_switch(void) 1029static int video_autosw_get(void)
984{ 1030{
985 int autosw = video_autosw(); 1031 int autosw = 0;
986 int ret;
987 1032
988 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1)) 1033 switch (video_supported) {
989 return -EIO; 1034 case TPACPI_VIDEO_570:
990 ret = video_supported == TPACPI_VIDEO_570 ? 1035 if (!acpi_evalf(vid_handle, &autosw, "SWIT", "d"))
991 acpi_evalf(ec_handle, NULL, "_Q16", "v") : 1036 return -EIO;
992 acpi_evalf(vid_handle, NULL, "VSWT", "v"); 1037 break;
993 acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw); 1038 case TPACPI_VIDEO_770:
1039 case TPACPI_VIDEO_NEW:
1040 if (!acpi_evalf(vid_handle, &autosw, "^VDEE", "d"))
1041 return -EIO;
1042 break;
1043 default:
1044 return -ENOSYS;
1045 }
994 1046
995 return ret; 1047 return autosw & 1;
996} 1048}
997 1049
998static int video_expand(void) 1050static int video_autosw_set(int enable)
999{ 1051{
1000 if (video_supported == TPACPI_VIDEO_570) 1052 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
1001 return acpi_evalf(ec_handle, NULL, "_Q17", "v"); 1053 return -EIO;
1002 else if (video_supported == TPACPI_VIDEO_770) 1054 return 0;
1003 return acpi_evalf(vid_handle, NULL, "VEXP", "v");
1004 else
1005 return acpi_evalf(NULL, NULL, "\\VEXP", "v");
1006} 1055}
1007 1056
1008static int video_switch2(int status) 1057static int video_outputsw_cycle(void)
1009{ 1058{
1010 int ret; 1059 int autosw = video_autosw_get();
1011 1060 int res;
1012 if (video_supported == TPACPI_VIDEO_570) {
1013 ret = acpi_evalf(NULL, NULL,
1014 "\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
1015 } else if (video_supported == TPACPI_VIDEO_770) {
1016 int autosw = video_autosw();
1017 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
1018 return -EIO;
1019 1061
1020 ret = acpi_evalf(vid_handle, NULL, 1062 if (autosw < 0)
1021 "ASWT", "vdd", status * 0x100, 0); 1063 return autosw;
1022 1064
1023 acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw); 1065 switch (video_supported) {
1024 } else { 1066 case TPACPI_VIDEO_570:
1025 ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) && 1067 res = video_autosw_set(1);
1026 acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1); 1068 if (res)
1069 return res;
1070 res = acpi_evalf(ec_handle, NULL, "_Q16", "v");
1071 break;
1072 case TPACPI_VIDEO_770:
1073 case TPACPI_VIDEO_NEW:
1074 res = video_autosw_set(1);
1075 if (res)
1076 return res;
1077 res = acpi_evalf(vid_handle, NULL, "VSWT", "v");
1078 break;
1079 default:
1080 return -ENOSYS;
1081 }
1082 if (!autosw && video_autosw_set(autosw)) {
1083 printk(IBM_ERR "video auto-switch left enabled due to error\n");
1084 return -EIO;
1027 } 1085 }
1028 1086
1029 return ret; 1087 return (res)? 0 : -EIO;
1088}
1089
1090static int video_expand_toggle(void)
1091{
1092 switch (video_supported) {
1093 case TPACPI_VIDEO_570:
1094 return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
1095 0 : -EIO;
1096 case TPACPI_VIDEO_770:
1097 return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
1098 0 : -EIO;
1099 case TPACPI_VIDEO_NEW:
1100 return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
1101 0 : -EIO;
1102 default:
1103 return -ENOSYS;
1104 }
1105 /* not reached */
1030} 1106}
1031 1107
1032static int video_read(char *p) 1108static int video_read(char *p)
1033{ 1109{
1034 int status = video_status(); 1110 int status, autosw;
1035 int autosw = video_autosw();
1036 int len = 0; 1111 int len = 0;
1037 1112
1038 if (!video_supported) { 1113 if (video_supported == TPACPI_VIDEO_NONE) {
1039 len += sprintf(p + len, "status:\t\tnot supported\n"); 1114 len += sprintf(p + len, "status:\t\tnot supported\n");
1040 return len; 1115 return len;
1041 } 1116 }
1042 1117
1118 status = video_outputsw_get();
1119 if (status < 0)
1120 return status;
1121
1122 autosw = video_autosw_get();
1123 if (autosw < 0)
1124 return autosw;
1125
1043 len += sprintf(p + len, "status:\t\tsupported\n"); 1126 len += sprintf(p + len, "status:\t\tsupported\n");
1044 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0)); 1127 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
1045 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1)); 1128 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
@@ -1060,47 +1143,56 @@ static int video_write(char *buf)
1060{ 1143{
1061 char *cmd; 1144 char *cmd;
1062 int enable, disable, status; 1145 int enable, disable, status;
1146 int res;
1063 1147
1064 if (!video_supported) 1148 if (video_supported == TPACPI_VIDEO_NONE)
1065 return -ENODEV; 1149 return -ENODEV;
1066 1150
1067 enable = disable = 0; 1151 enable = 0;
1152 disable = 0;
1068 1153
1069 while ((cmd = next_cmd(&buf))) { 1154 while ((cmd = next_cmd(&buf))) {
1070 if (strlencmp(cmd, "lcd_enable") == 0) { 1155 if (strlencmp(cmd, "lcd_enable") == 0) {
1071 enable |= 0x01; 1156 enable |= TP_ACPI_VIDEO_S_LCD;
1072 } else if (strlencmp(cmd, "lcd_disable") == 0) { 1157 } else if (strlencmp(cmd, "lcd_disable") == 0) {
1073 disable |= 0x01; 1158 disable |= TP_ACPI_VIDEO_S_LCD;
1074 } else if (strlencmp(cmd, "crt_enable") == 0) { 1159 } else if (strlencmp(cmd, "crt_enable") == 0) {
1075 enable |= 0x02; 1160 enable |= TP_ACPI_VIDEO_S_CRT;
1076 } else if (strlencmp(cmd, "crt_disable") == 0) { 1161 } else if (strlencmp(cmd, "crt_disable") == 0) {
1077 disable |= 0x02; 1162 disable |= TP_ACPI_VIDEO_S_CRT;
1078 } else if (video_supported == TPACPI_VIDEO_NEW && 1163 } else if (video_supported == TPACPI_VIDEO_NEW &&
1079 strlencmp(cmd, "dvi_enable") == 0) { 1164 strlencmp(cmd, "dvi_enable") == 0) {
1080 enable |= 0x08; 1165 enable |= TP_ACPI_VIDEO_S_DVI;
1081 } else if (video_supported == TPACPI_VIDEO_NEW && 1166 } else if (video_supported == TPACPI_VIDEO_NEW &&
1082 strlencmp(cmd, "dvi_disable") == 0) { 1167 strlencmp(cmd, "dvi_disable") == 0) {
1083 disable |= 0x08; 1168 disable |= TP_ACPI_VIDEO_S_DVI;
1084 } else if (strlencmp(cmd, "auto_enable") == 0) { 1169 } else if (strlencmp(cmd, "auto_enable") == 0) {
1085 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1)) 1170 res = video_autosw_set(1);
1086 return -EIO; 1171 if (res)
1172 return res;
1087 } else if (strlencmp(cmd, "auto_disable") == 0) { 1173 } else if (strlencmp(cmd, "auto_disable") == 0) {
1088 if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0)) 1174 res = video_autosw_set(0);
1089 return -EIO; 1175 if (res)
1176 return res;
1090 } else if (strlencmp(cmd, "video_switch") == 0) { 1177 } else if (strlencmp(cmd, "video_switch") == 0) {
1091 if (!video_switch()) 1178 res = video_outputsw_cycle();
1092 return -EIO; 1179 if (res)
1180 return res;
1093 } else if (strlencmp(cmd, "expand_toggle") == 0) { 1181 } else if (strlencmp(cmd, "expand_toggle") == 0) {
1094 if (!video_expand()) 1182 res = video_expand_toggle();
1095 return -EIO; 1183 if (res)
1184 return res;
1096 } else 1185 } else
1097 return -EINVAL; 1186 return -EINVAL;
1098 } 1187 }
1099 1188
1100 if (enable || disable) { 1189 if (enable || disable) {
1101 status = (video_status() & 0x0f & ~disable) | enable; 1190 status = video_outputsw_get();
1102 if (!video_switch2(status)) 1191 if (status < 0)
1103 return -EIO; 1192 return status;
1193 res = video_outputsw_set((status & ~disable) | enable);
1194 if (res)
1195 return res;
1104 } 1196 }
1105 1197
1106 return 0; 1198 return 0;
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index e06bad5c8fe4..3a8718a08116 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -446,17 +446,32 @@ enum video_access_mode {
446 TPACPI_VIDEO_NEW, /* all others */ 446 TPACPI_VIDEO_NEW, /* all others */
447}; 447};
448 448
449enum { /* video status flags, based on VIDEO_570 */
450 TP_ACPI_VIDEO_S_LCD = 0x01, /* LCD output enabled */
451 TP_ACPI_VIDEO_S_CRT = 0x02, /* CRT output enabled */
452 TP_ACPI_VIDEO_S_DVI = 0x08, /* DVI output enabled */
453};
454
455enum { /* TPACPI_VIDEO_570 constants */
456 TP_ACPI_VIDEO_570_PHSCMD = 0x87, /* unknown magic constant :( */
457 TP_ACPI_VIDEO_570_PHSMASK = 0x03, /* PHS bits that map to
458 * video_status_flags */
459 TP_ACPI_VIDEO_570_PHS2CMD = 0x8b, /* unknown magic constant :( */
460 TP_ACPI_VIDEO_570_PHS2SET = 0x80, /* unknown magic constant :( */
461};
462
449static enum video_access_mode video_supported; 463static enum video_access_mode video_supported;
450static int video_orig_autosw; 464static int video_orig_autosw;
451static acpi_handle vid_handle, vid2_handle; 465static acpi_handle vid_handle, vid2_handle;
452 466
453static int video_init(struct ibm_init_struct *iibm); 467static int video_init(struct ibm_init_struct *iibm);
454static void video_exit(void); 468static void video_exit(void);
455static int video_status(void); 469static int video_outputsw_get(void);
456static int video_autosw(void); 470static int video_outputsw_set(int status);
457static int video_switch(void); 471static int video_autosw_get(void);
458static int video_switch2(int status); 472static int video_autosw_set(int enable);
459static int video_expand(void); 473static int video_outputsw_cycle(void);
474static int video_expand_toggle(void);
460static int video_read(char *p); 475static int video_read(char *p);
461static int video_write(char *buf); 476static int video_write(char *buf);
462 477