Commit 83f34724 authored by Henrique de Moraes Holschuh's avatar Henrique de Moraes Holschuh Committed by Len Brown

ACPI: thinkpad-acpi: cleanup video subdriver

Cleanup video subdriver for sysfs conversion, and properly check
result status of acpi_evalf.
Signed-off-by: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent d6fdd1e9
...@@ -935,111 +935,194 @@ static int __init video_init(struct ibm_init_struct *iibm) ...@@ -935,111 +935,194 @@ static int __init video_init(struct ibm_init_struct *iibm)
static void video_exit(void) static void video_exit(void)
{ {
dbg_printk(TPACPI_DBG_EXIT, "restoring original video autoswitch mode\n"); dbg_printk(TPACPI_DBG_EXIT,
acpi_evalf(vid_handle, NULL, "_DOS", "vd", video_orig_autosw); "restoring original video autoswitch mode\n");
if (video_autosw_set(video_orig_autosw))
printk(IBM_ERR "error while trying to restore original "
"video autoswitch mode\n");
} }
static int video_status(void) static int video_outputsw_get(void)
{ {
int status = 0; int status = 0;
int i; int i;
if (video_supported == TPACPI_VIDEO_570) { switch (video_supported) {
if (acpi_evalf(NULL, &i, "\\_SB.PHS", "dd", 0x87)) case TPACPI_VIDEO_570:
status = i & 3; if (!acpi_evalf(NULL, &i, "\\_SB.PHS", "dd",
} else if (video_supported == TPACPI_VIDEO_770) { TP_ACPI_VIDEO_570_PHSCMD))
if (acpi_evalf(NULL, &i, "\\VCDL", "d")) return -EIO;
status |= 0x01 * i; status = i & TP_ACPI_VIDEO_570_PHSMASK;
if (acpi_evalf(NULL, &i, "\\VCDC", "d")) break;
status |= 0x02 * i; case TPACPI_VIDEO_770:
} else if (video_supported == TPACPI_VIDEO_NEW) { if (!acpi_evalf(NULL, &i, "\\VCDL", "d"))
acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1); return -EIO;
if (acpi_evalf(NULL, &i, "\\VCDC", "d")) if (i)
status |= 0x02 * i; status |= TP_ACPI_VIDEO_S_LCD;
if (!acpi_evalf(NULL, &i, "\\VCDC", "d"))
acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0); return -EIO;
if (acpi_evalf(NULL, &i, "\\VCDL", "d")) if (i)
status |= 0x01 * i; status |= TP_ACPI_VIDEO_S_CRT;
if (acpi_evalf(NULL, &i, "\\VCDD", "d")) break;
status |= 0x08 * i; case TPACPI_VIDEO_NEW:
if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 1) ||
!acpi_evalf(NULL, &i, "\\VCDC", "d"))
return -EIO;
if (i)
status |= TP_ACPI_VIDEO_S_CRT;
if (!acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0) ||
!acpi_evalf(NULL, &i, "\\VCDL", "d"))
return -EIO;
if (i)
status |= TP_ACPI_VIDEO_S_LCD;
if (!acpi_evalf(NULL, &i, "\\VCDD", "d"))
return -EIO;
if (i)
status |= TP_ACPI_VIDEO_S_DVI;
break;
default:
return -ENOSYS;
} }
return status; return status;
} }
static int video_autosw(void) static int video_outputsw_set(int status)
{ {
int autosw = 0; int autosw;
int res = 0;
if (video_supported == TPACPI_VIDEO_570) switch (video_supported) {
acpi_evalf(vid_handle, &autosw, "SWIT", "d"); case TPACPI_VIDEO_570:
else if (video_supported == TPACPI_VIDEO_770 || res = acpi_evalf(NULL, NULL,
video_supported == TPACPI_VIDEO_NEW) "\\_SB.PHS2", "vdd",
acpi_evalf(vid_handle, &autosw, "^VDEE", "d"); TP_ACPI_VIDEO_570_PHS2CMD,
status | TP_ACPI_VIDEO_570_PHS2SET);
break;
case TPACPI_VIDEO_770:
autosw = video_autosw_get();
if (autosw < 0)
return autosw;
return autosw & 1; res = video_autosw_set(1);
if (res)
return res;
res = acpi_evalf(vid_handle, NULL,
"ASWT", "vdd", status * 0x100, 0);
if (!autosw && video_autosw_set(autosw)) {
printk(IBM_ERR "video auto-switch left enabled due to error\n");
return -EIO;
}
break;
case TPACPI_VIDEO_NEW:
res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) &&
acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1);
break;
default:
return -ENOSYS;
}
return (res)? 0 : -EIO;
} }
static int video_switch(void) static int video_autosw_get(void)
{ {
int autosw = video_autosw(); int autosw = 0;
int ret;
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1)) switch (video_supported) {
return -EIO; case TPACPI_VIDEO_570:
ret = video_supported == TPACPI_VIDEO_570 ? if (!acpi_evalf(vid_handle, &autosw, "SWIT", "d"))
acpi_evalf(ec_handle, NULL, "_Q16", "v") : return -EIO;
acpi_evalf(vid_handle, NULL, "VSWT", "v"); break;
acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw); case TPACPI_VIDEO_770:
case TPACPI_VIDEO_NEW:
if (!acpi_evalf(vid_handle, &autosw, "^VDEE", "d"))
return -EIO;
break;
default:
return -ENOSYS;
}
return ret; return autosw & 1;
} }
static int video_expand(void) static int video_autosw_set(int enable)
{ {
if (video_supported == TPACPI_VIDEO_570) if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", (enable)? 1 : 0))
return acpi_evalf(ec_handle, NULL, "_Q17", "v"); return -EIO;
else if (video_supported == TPACPI_VIDEO_770) return 0;
return acpi_evalf(vid_handle, NULL, "VEXP", "v");
else
return acpi_evalf(NULL, NULL, "\\VEXP", "v");
} }
static int video_switch2(int status) static int video_outputsw_cycle(void)
{ {
int ret; int autosw = video_autosw_get();
int res;
if (video_supported == TPACPI_VIDEO_570) {
ret = acpi_evalf(NULL, NULL,
"\\_SB.PHS2", "vdd", 0x8b, status | 0x80);
} else if (video_supported == TPACPI_VIDEO_770) {
int autosw = video_autosw();
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1))
return -EIO;
ret = acpi_evalf(vid_handle, NULL, if (autosw < 0)
"ASWT", "vdd", status * 0x100, 0); return autosw;
acpi_evalf(vid_handle, NULL, "_DOS", "vd", autosw); switch (video_supported) {
} else { case TPACPI_VIDEO_570:
ret = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) && res = video_autosw_set(1);
acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1); if (res)
return res;
res = acpi_evalf(ec_handle, NULL, "_Q16", "v");
break;
case TPACPI_VIDEO_770:
case TPACPI_VIDEO_NEW:
res = video_autosw_set(1);
if (res)
return res;
res = acpi_evalf(vid_handle, NULL, "VSWT", "v");
break;
default:
return -ENOSYS;
}
if (!autosw && video_autosw_set(autosw)) {
printk(IBM_ERR "video auto-switch left enabled due to error\n");
return -EIO;
} }
return ret; return (res)? 0 : -EIO;
}
static int video_expand_toggle(void)
{
switch (video_supported) {
case TPACPI_VIDEO_570:
return acpi_evalf(ec_handle, NULL, "_Q17", "v")?
0 : -EIO;
case TPACPI_VIDEO_770:
return acpi_evalf(vid_handle, NULL, "VEXP", "v")?
0 : -EIO;
case TPACPI_VIDEO_NEW:
return acpi_evalf(NULL, NULL, "\\VEXP", "v")?
0 : -EIO;
default:
return -ENOSYS;
}
/* not reached */
} }
static int video_read(char *p) static int video_read(char *p)
{ {
int status = video_status(); int status, autosw;
int autosw = video_autosw();
int len = 0; int len = 0;
if (!video_supported) { if (video_supported == TPACPI_VIDEO_NONE) {
len += sprintf(p + len, "status:\t\tnot supported\n"); len += sprintf(p + len, "status:\t\tnot supported\n");
return len; return len;
} }
status = video_outputsw_get();
if (status < 0)
return status;
autosw = video_autosw_get();
if (autosw < 0)
return autosw;
len += sprintf(p + len, "status:\t\tsupported\n"); len += sprintf(p + len, "status:\t\tsupported\n");
len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0)); len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1)); len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
...@@ -1060,47 +1143,56 @@ static int video_write(char *buf) ...@@ -1060,47 +1143,56 @@ static int video_write(char *buf)
{ {
char *cmd; char *cmd;
int enable, disable, status; int enable, disable, status;
int res;
if (!video_supported) if (video_supported == TPACPI_VIDEO_NONE)
return -ENODEV; return -ENODEV;
enable = disable = 0; enable = 0;
disable = 0;
while ((cmd = next_cmd(&buf))) { while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "lcd_enable") == 0) { if (strlencmp(cmd, "lcd_enable") == 0) {
enable |= 0x01; enable |= TP_ACPI_VIDEO_S_LCD;
} else if (strlencmp(cmd, "lcd_disable") == 0) { } else if (strlencmp(cmd, "lcd_disable") == 0) {
disable |= 0x01; disable |= TP_ACPI_VIDEO_S_LCD;
} else if (strlencmp(cmd, "crt_enable") == 0) { } else if (strlencmp(cmd, "crt_enable") == 0) {
enable |= 0x02; enable |= TP_ACPI_VIDEO_S_CRT;
} else if (strlencmp(cmd, "crt_disable") == 0) { } else if (strlencmp(cmd, "crt_disable") == 0) {
disable |= 0x02; disable |= TP_ACPI_VIDEO_S_CRT;
} else if (video_supported == TPACPI_VIDEO_NEW && } else if (video_supported == TPACPI_VIDEO_NEW &&
strlencmp(cmd, "dvi_enable") == 0) { strlencmp(cmd, "dvi_enable") == 0) {
enable |= 0x08; enable |= TP_ACPI_VIDEO_S_DVI;
} else if (video_supported == TPACPI_VIDEO_NEW && } else if (video_supported == TPACPI_VIDEO_NEW &&
strlencmp(cmd, "dvi_disable") == 0) { strlencmp(cmd, "dvi_disable") == 0) {
disable |= 0x08; disable |= TP_ACPI_VIDEO_S_DVI;
} else if (strlencmp(cmd, "auto_enable") == 0) { } else if (strlencmp(cmd, "auto_enable") == 0) {
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 1)) res = video_autosw_set(1);
return -EIO; if (res)
return res;
} else if (strlencmp(cmd, "auto_disable") == 0) { } else if (strlencmp(cmd, "auto_disable") == 0) {
if (!acpi_evalf(vid_handle, NULL, "_DOS", "vd", 0)) res = video_autosw_set(0);
return -EIO; if (res)
return res;
} else if (strlencmp(cmd, "video_switch") == 0) { } else if (strlencmp(cmd, "video_switch") == 0) {
if (!video_switch()) res = video_outputsw_cycle();
return -EIO; if (res)
return res;
} else if (strlencmp(cmd, "expand_toggle") == 0) { } else if (strlencmp(cmd, "expand_toggle") == 0) {
if (!video_expand()) res = video_expand_toggle();
return -EIO; if (res)
return res;
} else } else
return -EINVAL; return -EINVAL;
} }
if (enable || disable) { if (enable || disable) {
status = (video_status() & 0x0f & ~disable) | enable; status = video_outputsw_get();
if (!video_switch2(status)) if (status < 0)
return -EIO; return status;
res = video_outputsw_set((status & ~disable) | enable);
if (res)
return res;
} }
return 0; return 0;
......
...@@ -446,17 +446,32 @@ enum video_access_mode { ...@@ -446,17 +446,32 @@ enum video_access_mode {
TPACPI_VIDEO_NEW, /* all others */ TPACPI_VIDEO_NEW, /* all others */
}; };
enum { /* video status flags, based on VIDEO_570 */
TP_ACPI_VIDEO_S_LCD = 0x01, /* LCD output enabled */
TP_ACPI_VIDEO_S_CRT = 0x02, /* CRT output enabled */
TP_ACPI_VIDEO_S_DVI = 0x08, /* DVI output enabled */
};
enum { /* TPACPI_VIDEO_570 constants */
TP_ACPI_VIDEO_570_PHSCMD = 0x87, /* unknown magic constant :( */
TP_ACPI_VIDEO_570_PHSMASK = 0x03, /* PHS bits that map to
* video_status_flags */
TP_ACPI_VIDEO_570_PHS2CMD = 0x8b, /* unknown magic constant :( */
TP_ACPI_VIDEO_570_PHS2SET = 0x80, /* unknown magic constant :( */
};
static enum video_access_mode video_supported; static enum video_access_mode video_supported;
static int video_orig_autosw; static int video_orig_autosw;
static acpi_handle vid_handle, vid2_handle; static acpi_handle vid_handle, vid2_handle;
static int video_init(struct ibm_init_struct *iibm); static int video_init(struct ibm_init_struct *iibm);
static void video_exit(void); static void video_exit(void);
static int video_status(void); static int video_outputsw_get(void);
static int video_autosw(void); static int video_outputsw_set(int status);
static int video_switch(void); static int video_autosw_get(void);
static int video_switch2(int status); static int video_autosw_set(int enable);
static int video_expand(void); static int video_outputsw_cycle(void);
static int video_expand_toggle(void);
static int video_read(char *p); static int video_read(char *p);
static int video_write(char *buf); static int video_write(char *buf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment