diff options
Diffstat (limited to 'drivers/staging/sm7xx/smtcfb.c')
-rw-r--r-- | drivers/staging/sm7xx/smtcfb.c | 215 |
1 files changed, 112 insertions, 103 deletions
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c index 3e2230f0879a..a164fc43bd8e 100644 --- a/drivers/staging/sm7xx/smtcfb.c +++ b/drivers/staging/sm7xx/smtcfb.c @@ -8,21 +8,24 @@ * Copyright (C) 2009 Lemote, Inc. * Author: Wu Zhangjin, wuzhangjin@gmail.com * + * Copyright (C) 2011 Igalia, S.L. + * Author: Javier M. Mellid <jmunhoz@igalia.com> + * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * * Version 0.10.26192.21.01 * - Add PowerPC/Big endian support - * - Add 2D support for Lynx - * - Verified on2.6.19.2 Boyod.yang <boyod.yang@siliconmotion.com.cn> + * - Verified on 2.6.19.2 + * Boyod.yang <boyod.yang@siliconmotion.com.cn> * * Version 0.09.2621.00.01 - * - Only support Linux Kernel's version 2.6.21. - * Boyod.yang <boyod.yang@siliconmotion.com.cn> + * - Only support Linux Kernel's version 2.6.21 + * Boyod.yang <boyod.yang@siliconmotion.com.cn> * * Version 0.09 - * - Only support Linux Kernel's version 2.6.12. + * - Only support Linux Kernel's version 2.6.12 * Boyod.yang <boyod.yang@siliconmotion.com.cn> */ @@ -39,16 +42,16 @@ #include <linux/pm.h> #endif -struct screen_info smtc_screen_info; - #include "smtcfb.h" #ifdef DEBUG -#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg) +#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg) #else #define smdbg(format, arg...) #endif +struct screen_info smtc_screen_info; + /* * Private structure */ @@ -99,17 +102,17 @@ struct vesa_mode_table { static struct vesa_mode_table vesa_mode[] = { {"0x301", 640, 480, 8}, {"0x303", 800, 600, 8}, - {"0x305", 1024, 768, 8}, + {"0x305", 1024, 768, 8}, {"0x307", 1280, 1024, 8}, {"0x311", 640, 480, 16}, {"0x314", 800, 600, 16}, - {"0x317", 1024, 768, 16}, + {"0x317", 1024, 768, 16}, {"0x31A", 1280, 1024, 16}, {"0x312", 640, 480, 24}, {"0x315", 800, 600, 24}, - {"0x318", 1024, 768, 24}, + {"0x318", 1024, 768, 24}, {"0x31B", 1280, 1024, 24}, }; @@ -125,7 +128,30 @@ u16 smtc_ChipIDs[] = { 0x720 }; -#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16)) +#define numSMTCchipIDs ARRAY_SIZE(smtc_ChipIDs) + +static struct fb_var_screeninfo smtcfb_var = { + .xres = 1024, + .yres = 600, + .xres_virtual = 1024, + .yres_virtual = 600, + .bits_per_pixel = 16, + .red = {16, 8, 0}, + .green = {8, 8, 0}, + .blue = {0, 8, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo smtcfb_fix = { + .id = "sm712fb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = 800 * 3, + .accel = FB_ACCEL_SMI_LYNX, +}; static void sm712_set_timing(struct smtcfb_info *sfb, struct par_info *ppar_info) @@ -268,29 +294,6 @@ static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info } } -static struct fb_var_screeninfo smtcfb_var = { - .xres = 1024, - .yres = 600, - .xres_virtual = 1024, - .yres_virtual = 600, - .bits_per_pixel = 16, - .red = {16, 8, 0}, - .green = {8, 8, 0}, - .blue = {0, 8, 0}, - .activate = FB_ACTIVATE_NOW, - .height = -1, - .width = -1, - .vmode = FB_VMODE_NONINTERLACED, -}; - -static struct fb_fix_screeninfo smtcfb_fix = { - .id = "sm712fb", - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .line_length = 800 * 3, - .accel = FB_ACCEL_SMI_LYNX, -}; - /* chan_to_field * * convert a colour value into a field position @@ -604,20 +607,6 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, } #endif /* ! __BIG_ENDIAN */ -static struct fb_ops smtcfb_ops = { - .owner = THIS_MODULE, - .fb_setcolreg = smtc_setcolreg, - .fb_blank = cfb_blank, - .fb_fillrect = cfb_fillrect, - .fb_imageblit = cfb_imageblit, - .fb_copyarea = cfb_copyarea, -#ifdef __BIG_ENDIAN - .fb_read = smtcfb_read, - .fb_write = smtcfb_write, -#endif - -}; - void smtcfb_setmode(struct smtcfb_info *sfb) { switch (sfb->fb.var.bits_per_pixel) { @@ -676,6 +665,47 @@ void smtcfb_setmode(struct smtcfb_info *sfb) smtc_set_timing(sfb, &hw); } +static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + /* sanity checks */ + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + /* set valid default bpp */ + if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) && + (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32)) + var->bits_per_pixel = 16; + + return 0; +} + +static int smtc_set_par(struct fb_info *info) +{ + struct smtcfb_info *sfb = (struct smtcfb_info *)info; + + smtcfb_setmode(sfb); + + return 0; +} + +static struct fb_ops smtcfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = smtc_check_var, + .fb_set_par = smtc_set_par, + .fb_setcolreg = smtc_setcolreg, + .fb_blank = cfb_blank, + .fb_fillrect = cfb_fillrect, + .fb_imageblit = cfb_imageblit, + .fb_copyarea = cfb_copyarea, +#ifdef __BIG_ENDIAN + .fb_read = smtcfb_read, + .fb_write = smtcfb_write, +#endif +}; + /* * Alloc struct smtcfb_info and assign the default value */ @@ -684,7 +714,7 @@ static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev, { struct smtcfb_info *sfb; - sfb = kzalloc(sizeof(struct smtcfb_info), GFP_KERNEL); + sfb = kzalloc(sizeof(*sfb), GFP_KERNEL); if (!sfb) return NULL; @@ -753,7 +783,7 @@ static int smtc_map_smem(struct smtcfb_info *sfb, sfb->fb.screen_base = smtc_VRAMBaseAddress; if (!sfb->fb.screen_base) { - printk(KERN_INFO "%s: unable to map screen memory\n", + printk(KERN_ERR "%s: unable to map screen memory\n", sfb->fb.fix.id); return -ENOMEM; } @@ -796,7 +826,7 @@ static void smtc_free_fb_info(struct smtcfb_info *sfb) * Returns zero. * */ -static int __init __maybe_unused sm712vga_setup(char *options) +static int __init sm712vga_setup(char *options) { int index; @@ -812,7 +842,7 @@ static int __init __maybe_unused sm712vga_setup(char *options) smdbg("\nsm712vga_setup = %s\n", options); for (index = 0; - index < (sizeof(vesa_mode) / sizeof(struct vesa_mode_table)); + index < ARRAY_SIZE(vesa_mode); index++) { if (strstr(options, vesa_mode[index].mode_index)) { smtc_screen_info.lfb_width = vesa_mode[index].lfb_width; @@ -846,7 +876,6 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); /* enable SMTC chip */ if (err) return err; - err = -ENOMEM; hw.chipID = ent->device; sprintf(name, "sm%Xfb", hw.chipID); @@ -909,7 +938,7 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, } #endif if (!smtc_RegBaseAddress) { - printk(KERN_INFO + printk(KERN_ERR "%s: unable to map memory mapped IO\n", sfb->fb.fix.id); err = -ENOMEM; @@ -944,7 +973,7 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, smtc_seqw(0x6b, 0x02); break; default: - printk(KERN_INFO + printk(KERN_ERR "No valid Silicon Motion display chip was detected!\n"); goto failed_fb; @@ -976,8 +1005,8 @@ static int __devinit smtcfb_pci_probe(struct pci_dev *pdev, return 0; - failed: - printk(KERN_INFO "Silicon Motion, Inc. primary display init fail\n"); +failed: + printk(KERN_ERR "Silicon Motion, Inc. primary display init fail\n"); smtc_unmap_smem(sfb); smtc_unmap_mmio(sfb); @@ -1016,13 +1045,10 @@ static void __devexit smtcfb_pci_remove(struct pci_dev *pdev) } #ifdef CONFIG_PM -/* Jason (08/14/2009) - * suspend function, called when the suspend event is triggered - */ -static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg) +static int smtcfb_pci_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct smtcfb_info *sfb; - int retv; sfb = pci_get_drvdata(pdev); @@ -1032,25 +1058,9 @@ static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg) smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0)); smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7)); - switch (msg.event) { - case PM_EVENT_FREEZE: - case PM_EVENT_PRETHAW: - pdev->dev.power.power_state = msg; - return 0; - } - - /* when doing suspend, call fb apis and pci apis */ - if (msg.event == PM_EVENT_SUSPEND) { - console_lock(); - fb_set_suspend(&sfb->fb, 1); - console_unlock(); - retv = pci_save_state(pdev); - pci_disable_device(pdev); - retv = pci_choose_state(pdev, msg); - retv = pci_set_power_state(pdev, retv); - } - - pdev->dev.power.power_state = msg; + console_lock(); + fb_set_suspend(&sfb->fb, 1); + console_unlock(); /* additionally turn off all function blocks including internal PLLs */ smtc_seqw(0x21, 0xff); @@ -1058,22 +1068,13 @@ static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg) return 0; } -static int __maybe_unused smtcfb_resume(struct pci_dev *pdev) +static int smtcfb_pci_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct smtcfb_info *sfb; - int retv; sfb = pci_get_drvdata(pdev); - /* when resuming, restore pci data and fb cursor */ - if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) { - retv = pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - if (pci_enable_device(pdev)) - return -1; - pci_set_master(pdev); - } - /* reinit hardware */ sm7xx_init_hw(); switch (hw.chipID) { @@ -1108,22 +1109,30 @@ static int __maybe_unused smtcfb_resume(struct pci_dev *pdev) return 0; } -#endif -/* Jason (08/13/2009) - * pci_driver struct used to wrap the original driver - * so that it can be registered into the kernel and - * the proper method would be called when suspending and resuming - */ +static const struct dev_pm_ops sm7xx_pm_ops = { + .suspend = smtcfb_pci_suspend, + .resume = smtcfb_pci_resume, + .freeze = smtcfb_pci_suspend, + .thaw = smtcfb_pci_resume, + .poweroff = smtcfb_pci_suspend, + .restore = smtcfb_pci_resume, +}; + +#define SM7XX_PM_OPS (&sm7xx_pm_ops) + +#else /* !CONFIG_PM */ + +#define SM7XX_PM_OPS NULL + +#endif /* !CONFIG_PM */ + static struct pci_driver smtcfb_driver = { .name = "smtcfb", .id_table = smtcfb_pci_table, .probe = smtcfb_pci_probe, .remove = __devexit_p(smtcfb_pci_remove), -#ifdef CONFIG_PM - .suspend = smtcfb_suspend, - .resume = smtcfb_resume, -#endif + .driver.pm = SM7XX_PM_OPS, }; static int __init smtcfb_init(void) |