Skip to content

Commit

Permalink
viafb: introduce per output device power management
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Florian Tobias Schandinat authored and Florian Tobias Schandinat committed Sep 24, 2010
1 parent c2a07c9 commit 6f9422d
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 111 deletions.
25 changes: 1 addition & 24 deletions drivers/video/via/dvi.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,26 +469,6 @@ static void __devinit dvi_get_panel_size_from_DDCv2(
/* If Disable DVI, turn off pad */
void viafb_dvi_disable(void)
{
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DVP0)
viafb_write_reg(SR1E, VIASR,
viafb_read_reg(VIASR, SR1E) & (~0xC0));

if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DVP1)
viafb_write_reg(SR1E, VIASR,
viafb_read_reg(VIASR, SR1E) & (~0x30));

if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
viafb_write_reg(SR2A, VIASR,
viafb_read_reg(VIASR, SR2A) & (~0x0C));

if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
viafb_write_reg(SR2A, VIASR,
viafb_read_reg(VIASR, SR2A) & (~0x03));

if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_TMDS)
/* Turn off TMDS power. */
Expand Down Expand Up @@ -571,7 +551,6 @@ void viafb_dvi_enable(void)
case INTERFACE_DVP0:
viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
dvi_patch_skew_dvp0();
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
tmds_register_write(0x88, 0x3b);
Expand All @@ -585,7 +564,6 @@ void viafb_dvi_enable(void)
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);

viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
tmds_register_write(0x88, 0x3b);
Expand Down Expand Up @@ -616,14 +594,13 @@ void viafb_dvi_enable(void)
if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
via_write_reg_mask(VIACR, CR97, 0x03, 0x03);

viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
break;

case INTERFACE_DFP_LOW:
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
break;
viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);

dvi_patch_skew_dvp_low();
via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
break;
Expand Down
132 changes: 119 additions & 13 deletions drivers/video/via/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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. */
Expand Down
9 changes: 7 additions & 2 deletions drivers/video/via/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
#define VIA_LVDS1 0x00000040
#define VIA_LVDS2 0x00000080

/* VIA output device power states */
#define VIA_STATE_ON 0
#define VIA_STATE_STANDBY 1
#define VIA_STATE_SUSPEND 2
#define VIA_STATE_OFF 3

/***************************************************
* Definition IGA1 Design Method of CRTC Registers *
****************************************************/
Expand Down Expand Up @@ -904,9 +910,8 @@ void viafb_set_vclock(u32 CLK, int set_iga);
void viafb_load_reg(int timing_value, int viafb_load_reg_num,
struct io_register *reg,
int io_type);
void viafb_crt_disable(void);
void viafb_crt_enable(void);
void via_set_source(u32 devices, u8 iga);
void via_set_state(u32 devices, u8 state);
u32 via_parse_odev(char *input, char **end);
void via_odev_to_seq(struct seq_file *m, u32 odev);
void init_ad9389(void);
Expand Down
10 changes: 0 additions & 10 deletions drivers/video/via/lcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,6 @@ static void integrated_lvds_disable(struct lvds_setting_information
viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
}

/* Turn DFP High/Low Pad off. */
viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);

/* Power off LVDS channel. */
switch (plvds_chip_info->output_interface) {
case INTERFACE_LVDS0:
Expand Down Expand Up @@ -761,9 +758,6 @@ static void integrated_lvds_enable(struct lvds_setting_information
break;
}

/* Turn DFP High/Low pad on. */
viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);

/* Power on LVDS channel. */
switch (plvds_chip_info->output_interface) {
case INTERFACE_LVDS0:
Expand Down Expand Up @@ -812,8 +806,6 @@ void viafb_lcd_disable(void)
viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
&viaparinfo->chip_info->lvds_chip_info);
} else {
/* DFP-HL pad off */
viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
/* Backlight off */
viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
/* 24 bit DI data paht off */
Expand Down Expand Up @@ -879,8 +871,6 @@ void viafb_lcd_enable(void)
viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
&viaparinfo->chip_info->lvds_chip_info);
} else {
/* DFP-HL pad on */
viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
/* Backlight on */
viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
/* 24 bit DI data paht on */
Expand Down
16 changes: 10 additions & 6 deletions drivers/video/via/viafbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,22 +332,22 @@ static int viafb_blank(int blank_mode, struct fb_info *info)
case FB_BLANK_UNBLANK:
/* Screen: On, HSync: On, VSync: On */
/* control CRT monitor power management */
viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
via_set_state(VIA_CRT, VIA_STATE_ON);
break;
case FB_BLANK_HSYNC_SUSPEND:
/* Screen: Off, HSync: Off, VSync: On */
/* control CRT monitor power management */
viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
via_set_state(VIA_CRT, VIA_STATE_STANDBY);
break;
case FB_BLANK_VSYNC_SUSPEND:
/* Screen: Off, HSync: On, VSync: Off */
/* control CRT monitor power management */
viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
break;
case FB_BLANK_POWERDOWN:
/* Screen: Off, HSync: Off, VSync: Off */
/* control CRT monitor power management */
viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
via_set_state(VIA_CRT, VIA_STATE_OFF);
break;
}

Expand Down Expand Up @@ -457,7 +457,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
return -EFAULT;
if (gpu32 & CRT_Device)
viafb_crt_enable();
via_set_state(VIA_CRT, VIA_STATE_ON);
if (gpu32 & DVI_Device)
viafb_dvi_enable();
if (gpu32 & LCD_Device)
Expand All @@ -467,7 +467,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
return -EFAULT;
if (gpu32 & CRT_Device)
viafb_crt_disable();
via_set_state(VIA_CRT, VIA_STATE_OFF);
if (gpu32 & DVI_Device)
viafb_dvi_disable();
if (gpu32 & LCD_Device)
Expand Down Expand Up @@ -1487,7 +1487,9 @@ static ssize_t viafb_iga1_odev_proc_write(struct file *file,
dev_on = dev_new & ~dev_old;
viaparinfo->shared->iga1_devices = dev_new;
viaparinfo->shared->iga2_devices &= ~dev_new;
via_set_state(dev_off, VIA_STATE_OFF);
via_set_source(dev_new, IGA1);
via_set_state(dev_on, VIA_STATE_ON);
return res;
}

Expand Down Expand Up @@ -1525,7 +1527,9 @@ static ssize_t viafb_iga2_odev_proc_write(struct file *file,
dev_on = dev_new & ~dev_old;
viaparinfo->shared->iga2_devices = dev_new;
viaparinfo->shared->iga1_devices &= ~dev_new;
via_set_state(dev_off, VIA_STATE_OFF);
via_set_source(dev_new, IGA2);
via_set_state(dev_on, VIA_STATE_ON);
return res;
}

Expand Down
Loading

0 comments on commit 6f9422d

Please sign in to comment.