aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/hw.c
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2010-09-07 10:28:26 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2010-09-23 22:15:03 -0400
commit6f9422d4e407bd63a9bd665ea09e57c1e3800c47 (patch)
treea8db0fe983bf177ed2653249aa55c9c846a0ce25 /drivers/video/via/hw.c
parentc2a07c932dad49b3b80b11132183b8b2ec8ea1aa (diff)
viafb: introduce per output device power management
This patch moves common parts of dvi.c, lcd.c and vt1636.c to hw.c to start a per output device power management. There should be no runtime changes aside that this patch enables the proc interface to enable/disable devices when needed which greatly increases the chances that changes to the output device configuration will work. However the power management is not yet complete so it might fail on some configurations. As this area is quite complex and touches undocumented things there is a slight chance of regressions. Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: Joseph Chan <JosephChan@via.com.tw>
Diffstat (limited to 'drivers/video/via/hw.c')
-rw-r--r--drivers/video/via/hw.c132
1 files changed, 119 insertions, 13 deletions
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index e65edcea46e..132d811525e 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1036,6 +1036,121 @@ void via_set_source(u32 devices, u8 iga)
1036 set_lvds2_source(iga); 1036 set_lvds2_source(iga);
1037} 1037}
1038 1038
1039static void set_crt_state(u8 state)
1040{
1041 u8 value;
1042
1043 switch (state) {
1044 case VIA_STATE_ON:
1045 value = 0x00;
1046 break;
1047 case VIA_STATE_STANDBY:
1048 value = 0x10;
1049 break;
1050 case VIA_STATE_SUSPEND:
1051 value = 0x20;
1052 break;
1053 case VIA_STATE_OFF:
1054 value = 0x30;
1055 break;
1056 default:
1057 return;
1058 }
1059
1060 via_write_reg_mask(VIACR, 0x36, value, 0x30);
1061}
1062
1063static void set_96_state(u8 state)
1064{
1065 u8 value;
1066
1067 switch (state) {
1068 case VIA_STATE_ON:
1069 value = 0xC0;
1070 break;
1071 case VIA_STATE_OFF:
1072 value = 0x00;
1073 break;
1074 default:
1075 return;
1076 }
1077
1078 via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
1079}
1080
1081static void set_dvp1_state(u8 state)
1082{
1083 u8 value;
1084
1085 switch (state) {
1086 case VIA_STATE_ON:
1087 value = 0x30;
1088 break;
1089 case VIA_STATE_OFF:
1090 value = 0x00;
1091 break;
1092 default:
1093 return;
1094 }
1095
1096 via_write_reg_mask(VIASR, 0x1E, value, 0x30);
1097}
1098
1099static void set_lvds1_state(u8 state)
1100{
1101 u8 value;
1102
1103 switch (state) {
1104 case VIA_STATE_ON:
1105 value = 0x03;
1106 break;
1107 case VIA_STATE_OFF:
1108 value = 0x00;
1109 break;
1110 default:
1111 return;
1112 }
1113
1114 via_write_reg_mask(VIASR, 0x2A, value, 0x03);
1115}
1116
1117static void set_lvds2_state(u8 state)
1118{
1119 u8 value;
1120
1121 switch (state) {
1122 case VIA_STATE_ON:
1123 value = 0x0C;
1124 break;
1125 case VIA_STATE_OFF:
1126 value = 0x00;
1127 break;
1128 default:
1129 return;
1130 }
1131
1132 via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
1133}
1134
1135void via_set_state(u32 devices, u8 state)
1136{
1137 /*
1138 TODO: Can we enable/disable these devices? How?
1139 if (devices & VIA_6C)
1140 if (devices & VIA_93)
1141 */
1142 if (devices & VIA_96)
1143 set_96_state(state);
1144 if (devices & VIA_CRT)
1145 set_crt_state(state);
1146 if (devices & VIA_DVP1)
1147 set_dvp1_state(state);
1148 if (devices & VIA_LVDS1)
1149 set_lvds1_state(state);
1150 if (devices & VIA_LVDS2)
1151 set_lvds2_state(state);
1152}
1153
1039u32 via_parse_odev(char *input, char **end) 1154u32 via_parse_odev(char *input, char **end)
1040{ 1155{
1041 char *ptr = input; 1156 char *ptr = input;
@@ -2224,6 +2339,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2224{ 2339{
2225 int i, j; 2340 int i, j;
2226 int port; 2341 int port;
2342 u32 devices = viaparinfo->shared->iga1_devices
2343 | viaparinfo->shared->iga2_devices;
2227 u8 value, index, mask; 2344 u8 value, index, mask;
2228 struct crt_mode_table *crt_timing; 2345 struct crt_mode_table *crt_timing;
2229 struct crt_mode_table *crt_timing1 = NULL; 2346 struct crt_mode_table *crt_timing1 = NULL;
@@ -2271,6 +2388,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2271 } 2388 }
2272 2389
2273 device_off(); 2390 device_off();
2391 via_set_state(devices, VIA_STATE_OFF);
2274 2392
2275 /* Fill VPIT Parameters */ 2393 /* Fill VPIT Parameters */
2276 /* Write Misc Register */ 2394 /* Write Misc Register */
@@ -2430,6 +2548,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2430 viafb_DeviceStatus = CRT_Device; 2548 viafb_DeviceStatus = CRT_Device;
2431 } 2549 }
2432 device_on(); 2550 device_on();
2551 via_set_state(devices, VIA_STATE_ON);
2433 device_screen_on(); 2552 device_screen_on();
2434 return 1; 2553 return 1;
2435} 2554}
@@ -2470,31 +2589,18 @@ int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2470 2589
2471static void device_off(void) 2590static void device_off(void)
2472{ 2591{
2473 viafb_crt_disable();
2474 viafb_dvi_disable(); 2592 viafb_dvi_disable();
2475 viafb_lcd_disable(); 2593 viafb_lcd_disable();
2476} 2594}
2477 2595
2478static void device_on(void) 2596static void device_on(void)
2479{ 2597{
2480 if (viafb_CRT_ON == 1)
2481 viafb_crt_enable();
2482 if (viafb_DVI_ON == 1) 2598 if (viafb_DVI_ON == 1)
2483 viafb_dvi_enable(); 2599 viafb_dvi_enable();
2484 if (viafb_LCD_ON == 1) 2600 if (viafb_LCD_ON == 1)
2485 viafb_lcd_enable(); 2601 viafb_lcd_enable();
2486} 2602}
2487 2603
2488void viafb_crt_disable(void)
2489{
2490 viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
2491}
2492
2493void viafb_crt_enable(void)
2494{
2495 viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
2496}
2497
2498static void enable_second_display_channel(void) 2604static void enable_second_display_channel(void)
2499{ 2605{
2500 /* to enable second display channel. */ 2606 /* to enable second display channel. */