From 0839d687f35b2f1a5e15fe5ee03bc4918457798d Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 16 Feb 2011 03:49:02 +0000 Subject: sh: mach-ecovec24: support for main lcd backlight Add support for the main LCD backlight that is controlled through the PTR1 GPIO. Signed-off-by: Alexandre Courbot Signed-off-by: Paul Mundt --- arch/sh/boards/mach-ecovec24/setup.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 701667acfd89..a2c06220bbab 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -261,6 +261,18 @@ const static struct fb_videomode ecovec_dvi_modes[] = { }, }; +static int ecovec24_set_brightness(void *board_data, int brightness) +{ + gpio_set_value(GPIO_PTR1, brightness); + + return 0; +} + +static int ecovec24_get_brightness(void *board_data) +{ + return gpio_get_value(GPIO_PTR1); +} + static struct sh_mobile_lcdc_info lcdc_info = { .ch[0] = { .interface_type = RGB18, @@ -271,6 +283,12 @@ static struct sh_mobile_lcdc_info lcdc_info = { .height = 91, }, .board_cfg = { + .set_brightness = ecovec24_set_brightness, + .get_brightness = ecovec24_get_brightness, + }, + .bl_info = { + .name = "sh_mobile_lcdc_bl", + .max_brightness = 1, }, } }; -- cgit v1.2.3-59-g8ed1b From bacbe55b63d434b7a33f01a03628b6302c75417b Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 16 Feb 2011 03:49:03 +0000 Subject: sh: mach-ap325rxa: move backlight control code Move the backlight control code into the appropriate hooks for the LCDC driver. Signed-off-by: Alexandre Courbot Signed-off-by: Paul Mundt --- arch/sh/boards/mach-ap325rxa/setup.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 3e5fc3bbf3ed..d695e43d3c6b 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -156,24 +156,34 @@ static struct platform_device nand_flash_device = { #define PORT_DRVCRA 0xA405018A #define PORT_DRVCRB 0xA405018C +static int ap320_wvga_set_brightness(void *board_data, int brightness) +{ + if (brightness) { + gpio_set_value(GPIO_PTS3, 0); + __raw_writew(0x100, FPGA_BKLREG); + } else { + __raw_writew(0, FPGA_BKLREG); + gpio_set_value(GPIO_PTS3, 1); + } + + return 0; +} + +static int ap320_wvga_get_brightness(void *board_data) +{ + return gpio_get_value(GPIO_PTS3); +} + static void ap320_wvga_power_on(void *board_data, struct fb_info *info) { msleep(100); /* ASD AP-320/325 LCD ON */ __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG); - - /* backlight */ - gpio_set_value(GPIO_PTS3, 0); - __raw_writew(0x100, FPGA_BKLREG); } static void ap320_wvga_power_off(void *board_data) { - /* backlight */ - __raw_writew(0, FPGA_BKLREG); - gpio_set_value(GPIO_PTS3, 1); - /* ASD AP-320/325 LCD OFF */ __raw_writew(0, FPGA_LCDREG); } @@ -209,6 +219,12 @@ static struct sh_mobile_lcdc_info lcdc_info = { .board_cfg = { .display_on = ap320_wvga_power_on, .display_off = ap320_wvga_power_off, + .set_brightness = ap320_wvga_set_brightness, + .get_brightness = ap320_wvga_get_brightness, + }, + .bl_info = { + .name = "sh_mobile_lcdc_bl", + .max_brightness = 1, }, } }; -- cgit v1.2.3-59-g8ed1b From 726abbc7957a2feeaf6f5e3d72579b3fd0211134 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Wed, 16 Mar 2011 16:31:32 +0000 Subject: viafb: refresh rate bug collection This patch fixes multiple issues with the handling of refresh rates especially for multi-display setups. If you experienced problems with wrong refresh rates this patch might fix them. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/chip.h | 1 - drivers/video/via/hw.c | 17 +++++++---------- drivers/video/via/hw.h | 3 +-- drivers/video/via/viafbdev.c | 45 +++++++++++++++++++++++++++----------------- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 781f3aa66b42..29d70244a21f 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -139,7 +139,6 @@ struct chip_information { struct crt_setting_information { int iga_path; - int refresh_rate; }; struct tmds_setting_information { diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 5728fd76bc11..dc4c778877ce 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2002,13 +2002,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, int i; int index = 0; int h_addr, v_addr; - u32 pll_D_N, clock; + u32 pll_D_N, clock, refresh = viafb_refresh; + + if (viafb_SAMM_ON && set_iga == IGA2) + refresh = viafb_refresh1; for (i = 0; i < video_mode->mode_array; i++) { index = i; - if (crt_table[i].refresh_rate == viaparinfo-> - crt_setting_info->refresh_rate) + if (crt_table[i].refresh_rate == refresh) break; } @@ -2019,7 +2021,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, if ((viafb_LCD_ON | viafb_DVI_ON) && video_mode->crtc[0].crtc.hor_addr == 640 && video_mode->crtc[0].crtc.ver_addr == 480 - && viaparinfo->crt_setting_info->refresh_rate == 60) { + && refresh == 60) { /* The border is 8 pixels. */ crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; @@ -2070,7 +2072,6 @@ void __devinit viafb_init_chip_info(int chip_type) init_lvds_chip_info(); viaparinfo->crt_setting_info->iga_path = IGA1; - viaparinfo->crt_setting_info->refresh_rate = viafb_refresh; /*Set IGA path for each device */ viafb_set_iga_path(); @@ -2083,13 +2084,9 @@ void __devinit viafb_init_chip_info(int chip_type) viaparinfo->lvds_setting_info->lcd_mode; } -void viafb_update_device_setting(int hres, int vres, - int bpp, int vmode_refresh, int flag) +void viafb_update_device_setting(int hres, int vres, int bpp, int flag) { if (flag == 0) { - viaparinfo->crt_setting_info->refresh_rate = - vmode_refresh; - viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 7295263299f7..8858593405aa 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -949,8 +949,7 @@ void __devinit viafb_init_chip_info(int chip_type); void __devinit viafb_init_dac(int set_iga); int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh); -void viafb_update_device_setting(int hres, int vres, int bpp, - int vmode_refresh, int flag); +void viafb_update_device_setting(int hres, int vres, int bpp, int flag); void viafb_set_iga_path(void); void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index f555b891cc72..fd6a15f0decd 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -182,13 +182,24 @@ static int viafb_release(struct fb_info *info, int user) return 0; } +static inline int get_var_refresh(struct fb_var_screeninfo *var) +{ + u32 htotal, vtotal; + + htotal = var->left_margin + var->xres + var->right_margin + + var->hsync_len; + vtotal = var->upper_margin + var->yres + var->lower_margin + + var->vsync_len; + return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal); +} + static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - int htotal, vtotal, depth; + int depth, refresh; struct VideoModeTable *vmode_entry; struct viafb_par *ppar = info->par; - u32 long_refresh, line; + u32 line; DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ @@ -231,17 +242,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var, /* Based on var passed in to calculate the refresh, * because our driver use some modes special. */ - htotal = var->xres + var->left_margin + - var->right_margin + var->hsync_len; - vtotal = var->yres + var->upper_margin + - var->lower_margin + var->vsync_len; - long_refresh = 1000000000UL / var->pixclock * 1000; - long_refresh /= (htotal * vtotal); - - viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); + refresh = viafb_get_refresh(var->xres, var->yres, + get_var_refresh(var)); /* Adjust var according to our driver's own table */ - viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); + viafb_fill_var_timing_info(var, refresh, vmode_entry); if (var->accel_flags & FB_ACCELF_TEXT && !ppar->shared->vdev->engine_mmio) var->accel_flags = 0; @@ -253,12 +258,13 @@ static int viafb_set_par(struct fb_info *info) { struct viafb_par *viapar = info->par; struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; + int refresh; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); viafb_update_fix(info); viapar->depth = fb_get_color_depth(&info->var, &info->fix); viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, - viafbinfo->var.bits_per_pixel, viafb_refresh, 0); + viafbinfo->var.bits_per_pixel, 0); vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); if (viafb_dual_fb) { @@ -266,7 +272,7 @@ static int viafb_set_par(struct fb_info *info) viafbinfo1->var.yres); viafb_update_device_setting(viafbinfo1->var.xres, viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, - viafb_refresh1, 1); + 1); } else if (viafb_SAMM_ON == 1) { DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", @@ -275,14 +281,19 @@ static int viafb_set_par(struct fb_info *info) viafb_second_yres); viafb_update_device_setting(viafb_second_xres, - viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); + viafb_second_yres, viafb_bpp1, 1); } + refresh = viafb_get_refresh(info->var.xres, info->var.yres, + get_var_refresh(&info->var)); if (vmode_entry) { - if (viafb_dual_fb && viapar->iga_path == IGA2) + if (viafb_dual_fb && viapar->iga_path == IGA2) { viafb_bpp1 = info->var.bits_per_pixel; - else + viafb_refresh1 = refresh; + } else { viafb_bpp = info->var.bits_per_pixel; + viafb_refresh = refresh; + } if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; @@ -1843,7 +1854,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) default_var.bits_per_pixel = viafb_bpp1; default_var.pixclock = viafb_get_pixclock(viafb_second_xres, viafb_second_yres, - viafb_refresh); + viafb_refresh1); default_var.left_margin = (viafb_second_xres >> 3) & 0xf8; default_var.right_margin = 32; default_var.upper_margin = 16; -- cgit v1.2.3-59-g8ed1b From 3f086fe93f734ba76f2e130777687f81e0cbb318 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Mon, 21 Mar 2011 17:01:07 +0000 Subject: viafb: initialize margins correct This patch initializes the margins for the initial mode correct. This is required to get the desired initial refresh rate. Also do more verbose sanity checking to prevent misbehavior. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/viafbdev.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index fd6a15f0decd..9d9bb9b4ed3f 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1806,14 +1806,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) default_var.xres_virtual = default_xres; default_var.yres_virtual = default_yres; default_var.bits_per_pixel = viafb_bpp; - default_var.pixclock = - viafb_get_pixclock(default_xres, default_yres, viafb_refresh); - default_var.left_margin = (default_xres >> 3) & 0xf8; - default_var.right_margin = 32; - default_var.upper_margin = 16; - default_var.lower_margin = 4; - default_var.hsync_len = default_var.left_margin; - default_var.vsync_len = 4; + viafb_fill_var_timing_info(&default_var, viafb_get_refresh( + default_var.xres, default_var.yres, viafb_refresh), + viafb_get_mode(default_var.xres, default_var.yres)); viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); viafbinfo->var = default_var; @@ -1852,15 +1847,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) default_var.xres_virtual = viafb_second_virtual_xres; default_var.yres_virtual = viafb_second_virtual_yres; default_var.bits_per_pixel = viafb_bpp1; - default_var.pixclock = - viafb_get_pixclock(viafb_second_xres, viafb_second_yres, - viafb_refresh1); - default_var.left_margin = (viafb_second_xres >> 3) & 0xf8; - default_var.right_margin = 32; - default_var.upper_margin = 16; - default_var.lower_margin = 4; - default_var.hsync_len = default_var.left_margin; - default_var.vsync_len = 4; + viafb_fill_var_timing_info(&default_var, viafb_get_refresh( + default_var.xres, default_var.yres, viafb_refresh1), + viafb_get_mode(default_var.xres, default_var.yres)); viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); viafb_check_var(&default_var, viafbinfo1); @@ -2015,15 +2004,17 @@ static int __init viafb_setup(char *options) */ int __init viafb_init(void) { - u32 dummy; + u32 dummy_x, dummy_y; #ifndef MODULE char *option = NULL; if (fb_get_options("viafb", &option)) return -ENODEV; viafb_setup(option); #endif - if (parse_mode(viafb_mode, &dummy, &dummy) - || parse_mode(viafb_mode1, &dummy, &dummy) + if (parse_mode(viafb_mode, &dummy_x, &dummy_y) + || !viafb_get_mode(dummy_x, dummy_y) + || parse_mode(viafb_mode1, &dummy_x, &dummy_y) + || !viafb_get_mode(dummy_x, dummy_y) || viafb_bpp < 0 || viafb_bpp > 32 || viafb_bpp1 < 0 || viafb_bpp1 > 32 || parse_active_dev()) -- cgit v1.2.3-59-g8ed1b From 8857b9aa7e64a70852545ee01fa638481cb08a76 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 23 Feb 2011 08:36:30 +0000 Subject: fbdev: sh_mobile_lcdcfb: add blanking support Add a blanking callback to the LCDC driver in order to support both FBIOBLANK and TIOCLINUX blanking ioctls. LCDC clocks are also released if the requested blanking level is superior to FB_BLANK_NORMAL, to allow runtime PM to disable the clocks if possible. Signed-off-by: Alexandre Courbot Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 44 ++++++++++++++++++++++++++++++++++++++++ drivers/video/sh_mobile_lcdcfb.h | 1 + 2 files changed, 45 insertions(+) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index e040e46d7d91..65c4ee3628c4 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -977,6 +977,49 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in return 0; } +/* + * Screen blanking. Behavior is as follows: + * FB_BLANK_UNBLANK: screen unblanked, clocks enabled + * FB_BLANK_NORMAL: screen blanked, clocks enabled + * FB_BLANK_VSYNC, + * FB_BLANK_HSYNC, + * FB_BLANK_POWEROFF: screen blanked, clocks disabled + */ +static int sh_mobile_lcdc_blank(int blank, struct fb_info *info) +{ + struct sh_mobile_lcdc_chan *ch = info->par; + struct sh_mobile_lcdc_priv *p = ch->lcdc; + + /* blank the screen? */ + if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { + struct fb_fillrect rect = { + .width = info->var.xres, + .height = info->var.yres, + }; + sh_mobile_lcdc_fillrect(info, &rect); + } + /* turn clocks on? */ + if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) { + sh_mobile_lcdc_clk_on(p); + } + /* turn clocks off? */ + if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) { + /* make sure the screen is updated with the black fill before + * switching the clocks off. one vsync is not enough since + * blanking may occur in the middle of a refresh. deferred io + * mode will reenable the clocks and update the screen in time, + * so it does not need this. */ + if (!info->fbdefio) { + sh_mobile_wait_for_vsync(info); + sh_mobile_wait_for_vsync(info); + } + sh_mobile_lcdc_clk_off(p); + } + + ch->blank_status = blank; + return 0; +} + static struct fb_ops sh_mobile_lcdc_ops = { .owner = THIS_MODULE, .fb_setcolreg = sh_mobile_lcdc_setcolreg, @@ -985,6 +1028,7 @@ static struct fb_ops sh_mobile_lcdc_ops = { .fb_fillrect = sh_mobile_lcdc_fillrect, .fb_copyarea = sh_mobile_lcdc_copyarea, .fb_imageblit = sh_mobile_lcdc_imageblit, + .fb_blank = sh_mobile_lcdc_blank, .fb_pan_display = sh_mobile_fb_pan_display, .fb_ioctl = sh_mobile_ioctl, .fb_open = sh_mobile_open, diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index 03a22dcbcc59..fad353a7e44c 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h @@ -37,6 +37,7 @@ struct sh_mobile_lcdc_chan { struct completion vsync_completion; struct fb_var_screeninfo display_var; int use_count; + int blank_status; struct mutex open_lock; /* protects the use counter */ }; -- cgit v1.2.3-59-g8ed1b From 247f99386100d1d1c369ba98120d2edebf5426fc Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 23 Feb 2011 08:41:50 +0000 Subject: fbdev: sh_mobile_lcdcfb: fix module lock acquisition Whenever the LCDC is to be started or stopped, a board callback is checked for existence and invoked. Prior to the invokation, the callback's module lock is also acquired, to be released once the callback returns. However, the order of testing makes it possible for the lock to be acquired and not released in case the callback does not exist. This patch reorders the tests to prevent this particular case. Signed-off-by: Alexandre Courbot Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 65c4ee3628c4..69e2833bd460 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -616,7 +616,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) continue; board_cfg = &ch->cfg.board_cfg; - if (try_module_get(board_cfg->owner) && board_cfg->display_on) { + if (board_cfg->display_on && try_module_get(board_cfg->owner)) { board_cfg->display_on(board_cfg->board_data, ch->info); module_put(board_cfg->owner); } @@ -661,7 +661,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) } board_cfg = &ch->cfg.board_cfg; - if (try_module_get(board_cfg->owner) && board_cfg->display_off) { + if (board_cfg->display_off && try_module_get(board_cfg->owner)) { board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } @@ -1228,7 +1228,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, switch(action) { case FB_EVENT_SUSPEND: - if (try_module_get(board_cfg->owner) && board_cfg->display_off) { + if (board_cfg->display_off && try_module_get(board_cfg->owner)) { board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } @@ -1241,7 +1241,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, mutex_unlock(&ch->open_lock); /* HDMI must be enabled before LCDC configuration */ - if (try_module_get(board_cfg->owner) && board_cfg->display_on) { + if (board_cfg->display_on && try_module_get(board_cfg->owner)) { board_cfg->display_on(board_cfg->board_data, info); module_put(board_cfg->owner); } -- cgit v1.2.3-59-g8ed1b From 62e0ff1ef2d8ea0814487f73a7de431396a1e914 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Thu, 24 Mar 2011 20:50:52 +0000 Subject: fbcon: Remove unused 'display *p' variable from fb_flashcursor() Signed-off-by: Sergey Senozhatsky Signed-off-by: Paul Mundt --- drivers/video/console/fbcon.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index c58393402da2..8745637e4b7e 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -370,7 +370,6 @@ static void fb_flashcursor(struct work_struct *work) { struct fb_info *info = container_of(work, struct fb_info, queue); struct fbcon_ops *ops = info->fbcon_par; - struct display *p; struct vc_data *vc = NULL; int c; int mode; @@ -386,7 +385,6 @@ static void fb_flashcursor(struct work_struct *work) return; } - p = &fb_display[vc->vc_num]; c = scr_readw((u16 *) vc->vc_pos); mode = (!ops->cursor_flash || ops->cursor_state.enable) ? CM_ERASE : CM_DRAW; -- cgit v1.2.3-59-g8ed1b From 94e948e6e43cd34e0e2ca496d5e90e4ff0d884f9 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 29 Mar 2011 19:07:08 +0000 Subject: s3fb: fix Virge/GX2 Fix Virge/GX2 support in s3fb: - fix IDs: 86C357 is GX2, 86C359 is GX2+, 86C356 probably does not exist - add memory size detection - drive it the same way as Trio3D/2X The original IDs most likely came from S3 website which claims that: - 356 is Virge/GX2 with ID=8A10, driver included in Windows 2K, XP - 357 is Virge/GX2+ with ID=8A11, driver included in Windows ME - 359 is Virge/GX2+ with ID=8A12, driver included in Windows ME but: - google search for 86C356 only reveals references to Trio3D (probably because of a typo - Trio3D is 86C365) - my card is clearly marked as 86C357, Virge/GX2 and has ID=8A10 - there is no driver for IDs 8A11 and 8A12 in Windows ME - there is a driver for ID 8A10 in Windows ME that says it's GX2 (357) Tested with #9 Reality 334 (86C357 Virge/GX2, ID=0x8A10). Signed-off-by: Ondrej Zary Signed-off-by: Paul Mundt --- drivers/video/s3fb.c | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index ddedad9cd069..c4482f2e5799 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -71,9 +71,9 @@ static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+", "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", - "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", + "S3 Plato/PX", "S3 Aurora64V+", "S3 Virge", "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", - "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", + "S3 Virge/GX2", "S3 Virge/GX2+", "", "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X", "S3 Trio3D"}; @@ -90,9 +90,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", #define CHIP_988_VIRGE_VX 0x0A #define CHIP_375_VIRGE_DX 0x0B #define CHIP_385_VIRGE_GX 0x0C -#define CHIP_356_VIRGE_GX2 0x0D -#define CHIP_357_VIRGE_GX2P 0x0E -#define CHIP_359_VIRGE_GX2P 0x0F +#define CHIP_357_VIRGE_GX2 0x0D +#define CHIP_359_VIRGE_GX2P 0x0E #define CHIP_360_TRIO3D_1X 0x10 #define CHIP_362_TRIO3D_2X 0x11 #define CHIP_368_TRIO3D_2X 0x12 @@ -359,7 +358,9 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); /* Set S3 clock registers */ - if (par->chip == CHIP_360_TRIO3D_1X || + if (par->chip == CHIP_357_VIRGE_GX2 || + par->chip == CHIP_359_VIRGE_GX2P || + par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_368_TRIO3D_2X) { vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ @@ -560,7 +561,9 @@ static int s3fb_set_par(struct fb_info *info) pr_debug("fb%d: offset register : %d\n", info->node, offset_value); svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value); - if (par->chip != CHIP_360_TRIO3D_1X && + if (par->chip != CHIP_357_VIRGE_GX2 && + par->chip != CHIP_359_VIRGE_GX2P && + par->chip != CHIP_360_TRIO3D_1X && par->chip != CHIP_362_TRIO3D_2X && par->chip != CHIP_368_TRIO3D_2X) { vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */ @@ -604,7 +607,9 @@ static int s3fb_set_par(struct fb_info *info) vga_wcrt(par->state.vgabase, 0x66, 0x90); } - if (par->chip == CHIP_360_TRIO3D_1X || + if (par->chip == CHIP_357_VIRGE_GX2 || + par->chip == CHIP_359_VIRGE_GX2P || + par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_368_TRIO3D_2X || par->chip == CHIP_365_TRIO3D || @@ -617,8 +622,7 @@ static int s3fb_set_par(struct fb_info *info) vga_wcrt(par->state.vgabase, 0x66, 0x81); } - if (par->chip == CHIP_356_VIRGE_GX2 || - par->chip == CHIP_357_VIRGE_GX2P || + if (par->chip == CHIP_357_VIRGE_GX2 || par->chip == CHIP_359_VIRGE_GX2P || par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || @@ -674,6 +678,8 @@ static int s3fb_set_par(struct fb_info *info) pr_debug("fb%d: 8 bit pseudocolor\n", info->node); svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); if (info->var.pixclock > 20000 || + par->chip == CHIP_357_VIRGE_GX2 || + par->chip == CHIP_359_VIRGE_GX2P || par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_368_TRIO3D_2X) @@ -702,7 +708,9 @@ static int s3fb_set_par(struct fb_info *info) } else { svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); - if (par->chip != CHIP_360_TRIO3D_1X && + if (par->chip != CHIP_357_VIRGE_GX2 && + par->chip != CHIP_359_VIRGE_GX2P && + par->chip != CHIP_360_TRIO3D_1X && par->chip != CHIP_362_TRIO3D_2X && par->chip != CHIP_368_TRIO3D_2X) hmul = 2; @@ -727,7 +735,9 @@ static int s3fb_set_par(struct fb_info *info) } else { svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); - if (par->chip != CHIP_360_TRIO3D_1X && + if (par->chip != CHIP_357_VIRGE_GX2 && + par->chip != CHIP_359_VIRGE_GX2P && + par->chip != CHIP_360_TRIO3D_1X && par->chip != CHIP_362_TRIO3D_2X && par->chip != CHIP_368_TRIO3D_2X) hmul = 2; @@ -1069,6 +1079,16 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i info->screen_size = 2 << 20; break; } + } else if (par->chip == CHIP_357_VIRGE_GX2 || + par->chip == CHIP_359_VIRGE_GX2P) { + switch ((regval & 0xC0) >> 6) { + case 1: /* 4MB */ + info->screen_size = 4 << 20; + break; + case 3: /* 2MB */ + info->screen_size = 2 << 20; + break; + } } else info->screen_size = s3_memsizes[regval >> 5] << 10; info->fix.smem_len = info->screen_size; @@ -1268,8 +1288,8 @@ static struct pci_device_id s3_devices[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX}, - {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, - {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, + {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2}, + {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D}, -- cgit v1.2.3-59-g8ed1b From e9c5db0b8dce1bcdc99ad26e718230810d6b5cff Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 31 Mar 2011 00:12:22 +0000 Subject: efifb: support AMD Radeon HD 6490 This patch enables the framebuffer for the AMD Radeon 6490 found in the new MacBook Pro 8,2 generation. The framebuffer's base is located at 0x90010000, the method for obtaining it was found in the same way mentioned in https://patchwork.kernel.org/patch/91704/ Signed-off-by: Davidlohr Bueso Signed-off-by: Jonathan Gonzalez Signed-off-by: Paul Mundt --- drivers/video/efifb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 70477c2e4b61..a9645b86a623 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -64,6 +64,7 @@ enum { M_MBP_6_1, /* MacBook Pro, 6,1th gen */ M_MBP_6_2, /* MacBook Pro, 6,2th gen */ M_MBP_7_1, /* MacBook Pro, 7,1th gen */ + M_MBP_8_2, /* MacBook Pro, 8,2nd gen */ M_UNKNOWN /* placeholder */ }; @@ -100,6 +101,7 @@ static struct efifb_dmi_info { [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, + [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900 }, [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } }; @@ -151,6 +153,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2), {}, }; -- cgit v1.2.3-59-g8ed1b From b73a21fc66fee35b41db755abebfacba48b2fc76 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 1 Apr 2011 07:17:27 +0000 Subject: video: s3c-fb: fix checkpatch errors and warning This patch fixes the checkpatch errors listed below: ERROR: space required before the open parenthesis '(' ERROR: need consistent spacing around '+' (ctx:WxV) ERROR: space prohibited before that close parenthesis ')' Also, following warning is fixed by adding 'platid' variable which can reduce number of lines exceeding 80 characters. WARNING: line over 80 characters Signed-off-by: Jingoo Han Signed-off-by: Paul Mundt --- drivers/video/s3c-fb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 6817d187d46e..3b6cdcac8f1a 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -48,7 +48,7 @@ #undef writel #define writel(v, r) do { \ printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ - __raw_writel(v, r); } while(0) + __raw_writel(v, r); } while (0) #endif /* FB_S3C_DEBUG_REGWRITE */ /* irq_flags bits */ @@ -518,7 +518,7 @@ static int s3c_fb_set_par(struct fb_info *info) data = VIDTCON2_LINEVAL(var->yres - 1) | VIDTCON2_HOZVAL(var->xres - 1); - writel(data, regs +sfb->variant.vidtcon + 8 ); + writel(data, regs + sfb->variant.vidtcon + 8); } /* write the buffer address */ @@ -1304,6 +1304,7 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) static int __devinit s3c_fb_probe(struct platform_device *pdev) { + const struct platform_device_id *platid; struct s3c_fb_driverdata *fbdrv; struct device *dev = &pdev->dev; struct s3c_fb_platdata *pd; @@ -1312,7 +1313,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) int win; int ret = 0; - fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data; + platid = platform_get_device_id(pdev); + fbdrv = (struct s3c_fb_driverdata *)platid->driver_data; if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) { dev_err(dev, "too many windows, cannot attach\n"); -- cgit v1.2.3-59-g8ed1b From a8c908d353e52336b864025dbd8253134c3f5411 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 1 Apr 2011 14:23:47 +0000 Subject: drivers/video/bfin-lq035q1-fb.c: introduce missing kfree Error handling code following a kmalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,f1,l; position p1,p2; expression *ptr != NULL; @@ x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S <... when != x when != if (...) { <+...x...+> } ( x->f1 = E | (x->f1 == NULL || ...) | f(...,x->f1,...) ) ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Acked-by: Mike Frysinger Signed-off-by: Paul Mundt --- drivers/video/bfin-lq035q1-fb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index c8e1f04941bd..23b6c4b62c78 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c @@ -154,8 +154,10 @@ static int __devinit lq035q1_spidev_probe(struct spi_device *spi) ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); - if (ret) + if (ret) { + kfree(ctl); return ret; + } spi_set_drvdata(spi, ctl); -- cgit v1.2.3-59-g8ed1b From a564d301e93f96a23c808b4cf234ac08b073c96d Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 3 Apr 2011 12:54:04 +0000 Subject: savagefb: Replace magic register address with define MM_SERIAL1 was already defined, but not used. Signed-off-by: Tormod Volden Signed-off-by: Paul Mundt --- drivers/video/savage/savagefb-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index b16e6138fdd4..58c8a3ce33c5 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -191,7 +191,7 @@ void savagefb_create_i2c_busses(struct fb_info *info) par->chan.algo.getscl = prosavage_gpio_getscl; break; case FB_ACCEL_SAVAGE2000: - par->chan.reg = 0xff20; + par->chan.reg = MM_SERIAL1; par->chan.ioaddr = par->mmio.vbase; par->chan.algo.setsda = savage4_gpio_setsda; par->chan.algo.setscl = savage4_gpio_setscl; -- cgit v1.2.3-59-g8ed1b From 21cd72e7cb424f1686855602ec0fdc6e5830f249 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 3 Apr 2011 12:54:05 +0000 Subject: savagefb: Set up I2C based on chip family instead of card id In practice this means enabling I2C (for DDC2) on all prosavage cards, like the xorg ddx does. The savage4 and savage2000 families have only one member each, so there is no change for those. Tested on TwisterK. Signed-off-by: Tormod Volden Signed-off-by: Paul Mundt --- drivers/video/savage/savagefb-i2c.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 58c8a3ce33c5..5e7acda2ba90 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -170,9 +170,8 @@ void savagefb_create_i2c_busses(struct fb_info *info) struct savagefb_par *par = info->par; par->chan.par = par; - switch(info->fix.accel) { - case FB_ACCEL_PROSAVAGE_DDRK: - case FB_ACCEL_PROSAVAGE_PM: + switch (par->chip) { + case S3_PROSAVAGE: par->chan.reg = CR_SERIAL2; par->chan.ioaddr = par->mmio.vbase; par->chan.algo.setsda = prosavage_gpio_setsda; @@ -180,7 +179,7 @@ void savagefb_create_i2c_busses(struct fb_info *info) par->chan.algo.getsda = prosavage_gpio_getsda; par->chan.algo.getscl = prosavage_gpio_getscl; break; - case FB_ACCEL_SAVAGE4: + case S3_SAVAGE4: par->chan.reg = CR_SERIAL1; if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40)) par->chan.reg = CR_SERIAL2; @@ -190,7 +189,7 @@ void savagefb_create_i2c_busses(struct fb_info *info) par->chan.algo.getsda = prosavage_gpio_getsda; par->chan.algo.getscl = prosavage_gpio_getscl; break; - case FB_ACCEL_SAVAGE2000: + case S3_SAVAGE2000: par->chan.reg = MM_SERIAL1; par->chan.ioaddr = par->mmio.vbase; par->chan.algo.setsda = savage4_gpio_setsda; -- cgit v1.2.3-59-g8ed1b From 787dffa5c790fdae40a0706e0b3847e31282eb3b Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Sun, 3 Apr 2011 12:54:06 +0000 Subject: savagefb: Remove obsolete else clause in savage_setup_i2c_bus The else clause was not needed after the cleanup in commit b8901b091db260b0f0101d6395ce5c6016835a47 Signed-off-by: Tormod Volden Signed-off-by: Paul Mundt --- drivers/video/savage/savagefb-i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 5e7acda2ba90..bb71fea07284 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -159,8 +159,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, else dev_warn(&chan->par->pcidev->dev, "Failed to register I2C bus %s.\n", name); - } else - chan->par = NULL; + } return rc; } -- cgit v1.2.3-59-g8ed1b From 47c87d930f3db4fc3a30505075e07f5597e2e953 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 4 Apr 2011 21:39:54 +0000 Subject: fb: Reduce priority of resource conflict message It's expected that efifb will conflict with a native driver, so the handover message should be informational rather than an error. Signed-off-by: Matthew Garrett Acked-by: Dave Airlie Signed-off-by: Paul Mundt --- drivers/video/fbmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e2bf95370e40..e0c2284924b6 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1507,7 +1507,7 @@ void remove_conflicting_framebuffers(struct apertures_struct *a, (primary && gen_aper && gen_aper->count && gen_aper->ranges[0].base == VGA_FB_PHYS)) { - printk(KERN_ERR "fb: conflicting fb hw usage " + printk(KERN_INFO "fb: conflicting fb hw usage " "%s vs %s - removing generic driver\n", name, registered_fb[i]->fix.id); unregister_framebuffer(registered_fb[i]); -- cgit v1.2.3-59-g8ed1b From 47dfe51f8f0b9540cbe15072cd352d9f3857d47f Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 6 Apr 2011 17:34:58 +0000 Subject: efifb: Support overriding fields FW tells us with the DMI data. Some machines apparently give us bogus linelength/stride/pitch data, so we need to support letting the DMI table override the supplied data. I bet you can't guess whose machines I'm talking about. Signed-off-by: Peter Jones Signed-off-by: Paul Mundt --- drivers/video/efifb.c | 149 +++++++++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index a9645b86a623..2359b6403a16 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -68,41 +68,48 @@ enum { M_UNKNOWN /* placeholder */ }; +#define OVERRIDE_NONE 0x0 +#define OVERRIDE_BASE 0x1 +#define OVERRIDE_STRIDE 0x2 +#define OVERRIDE_HEIGHT 0x4 +#define OVERRIDE_WIDTH 0x8 + static struct efifb_dmi_info { char *optname; unsigned long base; int stride; int width; int height; + int flags; } dmi_list[] __initdata = { - [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, - [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ - [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, - [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ - [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, - [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, - [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, - [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, - [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, - [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, - [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, - [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, - [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, - [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, - [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, - [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, - [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ - [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, - [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, - [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, - [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, - [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, - [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, - [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, - [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, - [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, - [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900 }, - [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } + [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, + [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */ + [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, + [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */ + [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, + [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE }, + [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE }, + [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE }, + [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE }, + [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, + [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, + [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */ + [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, + [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, + [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, + [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, + [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, + [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, + [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, + [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE }, + [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, + [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } }; static int set_system(const struct dmi_system_id *id); @@ -157,16 +164,22 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { {}, }; +#define choose_value(dmivalue, fwvalue, field, flags) ({ \ + typeof(fwvalue) _ret_ = fwvalue; \ + if ((flags) & (field)) \ + _ret_ = dmivalue; \ + else if ((fwvalue) == 0) \ + _ret_ = dmivalue; \ + _ret_; \ + }) + static int set_system(const struct dmi_system_id *id) { struct efifb_dmi_info *info = id->driver_data; - if (info->base == 0) - return 0; - printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " - "(%dx%d, stride %d)\n", id->ident, - (void *)info->base, info->width, info->height, - info->stride); + if (info->base == 0 && info->height == 0 && info->width == 0 + && info->stride == 0) + return 0; /* Trust the bootloader over the DMI tables */ if (screen_info.lfb_base == 0) { @@ -174,40 +187,47 @@ static int set_system(const struct dmi_system_id *id) struct pci_dev *dev = NULL; int found_bar = 0; #endif - screen_info.lfb_base = info->base; + if (info->base) { + screen_info.lfb_base = choose_value(info->base, + screen_info.lfb_base, OVERRIDE_BASE, + info->flags); #if defined(CONFIG_PCI) - /* make sure that the address in the table is actually on a - * VGA device's PCI BAR */ - - for_each_pci_dev(dev) { - int i; - if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) - continue; - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - resource_size_t start, end; - - start = pci_resource_start(dev, i); - if (start == 0) - break; - end = pci_resource_end(dev, i); - if (screen_info.lfb_base >= start && - screen_info.lfb_base < end) { - found_bar = 1; + /* make sure that the address in the table is actually + * on a VGA device's PCI BAR */ + + for_each_pci_dev(dev) { + int i; + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + continue; + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + resource_size_t start, end; + + start = pci_resource_start(dev, i); + if (start == 0) + break; + end = pci_resource_end(dev, i); + if (screen_info.lfb_base >= start && + screen_info.lfb_base < end) { + found_bar = 1; + } } } - } - if (!found_bar) - screen_info.lfb_base = 0; + if (!found_bar) + screen_info.lfb_base = 0; #endif + } } if (screen_info.lfb_base) { - if (screen_info.lfb_linelength == 0) - screen_info.lfb_linelength = info->stride; - if (screen_info.lfb_width == 0) - screen_info.lfb_width = info->width; - if (screen_info.lfb_height == 0) - screen_info.lfb_height = info->height; + screen_info.lfb_linelength = choose_value(info->stride, + screen_info.lfb_linelength, OVERRIDE_STRIDE, + info->flags); + screen_info.lfb_width = choose_value(info->width, + screen_info.lfb_width, OVERRIDE_WIDTH, + info->flags); + screen_info.lfb_height = choose_value(info->height, + screen_info.lfb_height, OVERRIDE_HEIGHT, + info->flags); if (screen_info.orig_video_isVGA == 0) screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; } else { @@ -217,6 +237,13 @@ static int set_system(const struct dmi_system_id *id) screen_info.orig_video_isVGA = 0; return 0; } + + printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " + "(%dx%d, stride %d)\n", id->ident, + (void *)screen_info.lfb_base, screen_info.lfb_width, + screen_info.lfb_height, screen_info.lfb_linelength); + + return 1; } -- cgit v1.2.3-59-g8ed1b From 97fb85076c2d3adcc559dee577e0a3bf7215d48e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 6 Apr 2011 17:34:59 +0000 Subject: efifb: Add override for 11" Macbook Air 3,1 The 11" Macbook Air appears to claim that its stride is 1366, when it's actually 2048. Override it. Signed-off-by: Matthew Garrett Signed-off-by: Peter Jones Signed-off-by: Paul Mundt --- drivers/video/efifb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 2359b6403a16..4eb38db36e4b 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -53,6 +53,7 @@ enum { M_MB_7_1, /* MacBook, 7th rev. */ M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ M_MBA, /* MacBook Air */ + M_MBA_3, /* Macbook Air, 3rd rev */ M_MBP, /* MacBook Pro */ M_MBP_2, /* MacBook Pro 2nd gen */ M_MBP_2_2, /* MacBook Pro 2,2nd gen */ @@ -97,6 +98,8 @@ static struct efifb_dmi_info { [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, + /* 11" Macbook Air 3,1 passes the wrong stride */ + [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE }, [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */ [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, @@ -147,6 +150,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), -- cgit v1.2.3-59-g8ed1b