diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2007-04-21 10:08:41 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-04-21 23:30:34 -0400 |
commit | 83f34724643a3b0ec9322490b9ad9f1b60170a6c (patch) | |
tree | dcd6da273723dc713c920414506212073ffe738d | |
parent | d6fdd1e91a8a4cd852dc1d945165e3a69ac9e257 (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>
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 262 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.h | 25 |
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 | ||
936 | static void video_exit(void) | 936 | static 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 | ||
942 | static int video_status(void) | 945 | static 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 | ||
970 | static int video_autosw(void) | 991 | static 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 | ||
983 | static int video_switch(void) | 1029 | static 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 | ||
998 | static int video_expand(void) | 1050 | static 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 | ||
1008 | static int video_switch2(int status) | 1057 | static 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 | |||
1090 | static 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 | ||
1032 | static int video_read(char *p) | 1108 | static 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 | ||
449 | enum { /* 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 | |||
455 | enum { /* 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 | |||
449 | static enum video_access_mode video_supported; | 463 | static enum video_access_mode video_supported; |
450 | static int video_orig_autosw; | 464 | static int video_orig_autosw; |
451 | static acpi_handle vid_handle, vid2_handle; | 465 | static acpi_handle vid_handle, vid2_handle; |
452 | 466 | ||
453 | static int video_init(struct ibm_init_struct *iibm); | 467 | static int video_init(struct ibm_init_struct *iibm); |
454 | static void video_exit(void); | 468 | static void video_exit(void); |
455 | static int video_status(void); | 469 | static int video_outputsw_get(void); |
456 | static int video_autosw(void); | 470 | static int video_outputsw_set(int status); |
457 | static int video_switch(void); | 471 | static int video_autosw_get(void); |
458 | static int video_switch2(int status); | 472 | static int video_autosw_set(int enable); |
459 | static int video_expand(void); | 473 | static int video_outputsw_cycle(void); |
474 | static int video_expand_toggle(void); | ||
460 | static int video_read(char *p); | 475 | static int video_read(char *p); |
461 | static int video_write(char *buf); | 476 | static int video_write(char *buf); |
462 | 477 | ||