diff options
author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2010-09-07 14:28:26 +0000 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2010-09-24 02:15:03 +0000 |
commit | 6f9422d4e407bd63a9bd665ea09e57c1e3800c47 (patch) | |
tree | a8db0fe983bf177ed2653249aa55c9c846a0ce25 /drivers/video/via/hw.c | |
parent | c2a07c932dad49b3b80b11132183b8b2ec8ea1aa (diff) | |
download | blackbird-op-linux-6f9422d4e407bd63a9bd665ea09e57c1e3800c47.tar.gz blackbird-op-linux-6f9422d4e407bd63a9bd665ea09e57c1e3800c47.zip |
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.c | 132 |
1 files changed, 119 insertions, 13 deletions
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index e65edcea46eb..132d811525ed 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) set_lvds2_source(iga); } +static void set_crt_state(u8 state) +{ + u8 value; + + switch (state) { + case VIA_STATE_ON: + value = 0x00; + break; + case VIA_STATE_STANDBY: + value = 0x10; + break; + case VIA_STATE_SUSPEND: + value = 0x20; + break; + case VIA_STATE_OFF: + value = 0x30; + break; + default: + return; + } + + via_write_reg_mask(VIACR, 0x36, value, 0x30); +} + +static void set_96_state(u8 state) +{ + u8 value; + + switch (state) { + case VIA_STATE_ON: + value = 0xC0; + break; + case VIA_STATE_OFF: + value = 0x00; + break; + default: + return; + } + + via_write_reg_mask(VIASR, 0x1E, value, 0xC0); +} + +static void set_dvp1_state(u8 state) +{ + u8 value; + + switch (state) { + case VIA_STATE_ON: + value = 0x30; + break; + case VIA_STATE_OFF: + value = 0x00; + break; + default: + return; + } + + via_write_reg_mask(VIASR, 0x1E, value, 0x30); +} + +static void set_lvds1_state(u8 state) +{ + u8 value; + + switch (state) { + case VIA_STATE_ON: + value = 0x03; + break; + case VIA_STATE_OFF: + value = 0x00; + break; + default: + return; + } + + via_write_reg_mask(VIASR, 0x2A, value, 0x03); +} + +static void set_lvds2_state(u8 state) +{ + u8 value; + + switch (state) { + case VIA_STATE_ON: + value = 0x0C; + break; + case VIA_STATE_OFF: + value = 0x00; + break; + default: + return; + } + + via_write_reg_mask(VIASR, 0x2A, value, 0x0C); +} + +void via_set_state(u32 devices, u8 state) +{ + /* + TODO: Can we enable/disable these devices? How? + if (devices & VIA_6C) + if (devices & VIA_93) + */ + if (devices & VIA_96) + set_96_state(state); + if (devices & VIA_CRT) + set_crt_state(state); + if (devices & VIA_DVP1) + set_dvp1_state(state); + if (devices & VIA_LVDS1) + set_lvds1_state(state); + if (devices & VIA_LVDS2) + set_lvds2_state(state); +} + u32 via_parse_odev(char *input, char **end) { char *ptr = input; @@ -2224,6 +2339,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, { int i, j; int port; + u32 devices = viaparinfo->shared->iga1_devices + | viaparinfo->shared->iga2_devices; u8 value, index, mask; struct crt_mode_table *crt_timing; struct crt_mode_table *crt_timing1 = NULL; @@ -2271,6 +2388,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, } device_off(); + via_set_state(devices, VIA_STATE_OFF); /* Fill VPIT Parameters */ /* Write Misc Register */ @@ -2430,6 +2548,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, viafb_DeviceStatus = CRT_Device; } device_on(); + via_set_state(devices, VIA_STATE_ON); device_screen_on(); return 1; } @@ -2470,31 +2589,18 @@ int viafb_get_refresh(int hres, int vres, u32 long_refresh) static void device_off(void) { - viafb_crt_disable(); viafb_dvi_disable(); viafb_lcd_disable(); } static void device_on(void) { - if (viafb_CRT_ON == 1) - viafb_crt_enable(); if (viafb_DVI_ON == 1) viafb_dvi_enable(); if (viafb_LCD_ON == 1) viafb_lcd_enable(); } -void viafb_crt_disable(void) -{ - viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4); -} - -void viafb_crt_enable(void) -{ - viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4); -} - static void enable_second_display_channel(void) { /* to enable second display channel. */ |