1/* 2 * Backlight Driver for Frontpath ProGear HX1050+ 3 * 4 * Copyright (c) 2006 Marcin Juszkiewicz 5 * 6 * Based on Progear LCD driver by M Schacht 7 * <mschacht at alumni dot washington dot edu> 8 * 9 * Based on Sharp's Corgi Backlight Driver 10 * Based on Backlight Driver for HP Jornada 680 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 * 16 */ 17 18#include <linux/module.h> 19#include <linux/kernel.h> 20#include <linux/init.h> 21#include <linux/platform_device.h> 22#include <linux/mutex.h> 23#include <linux/fb.h> 24#include <linux/backlight.h> 25#include <linux/pci.h> 26#include <asm/uaccess.h> 27 28#define PMU_LPCR 0xB0 29#define SB_MPS1 0x61 30#define HW_LEVEL_MAX 0x77 31#define HW_LEVEL_MIN 0x4f 32 33static struct pci_dev *pmu_dev = NULL; 34static struct pci_dev *sb_dev = NULL; 35 36static int progearbl_set_intensity(struct backlight_device *bd) 37{ 38 int intensity = bd->props.brightness; 39 40 if (bd->props.power != FB_BLANK_UNBLANK) 41 intensity = 0; 42 if (bd->props.fb_blank != FB_BLANK_UNBLANK) 43 intensity = 0; 44 45 pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN); 46 47 return 0; 48} 49 50static int progearbl_get_intensity(struct backlight_device *bd) 51{ 52 u8 intensity; 53 pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity); 54 55 return intensity - HW_LEVEL_MIN; 56} 57 58static struct backlight_ops progearbl_ops = { 59 .get_brightness = progearbl_get_intensity, 60 .update_status = progearbl_set_intensity, 61}; 62 63static int progearbl_probe(struct platform_device *pdev) 64{ 65 u8 temp; 66 struct backlight_device *progear_backlight_device; 67 68 pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); 69 if (!pmu_dev) { 70 printk("ALI M7101 PMU not found.\n"); 71 return -ENODEV; 72 } 73 74 sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); 75 if (!sb_dev) { 76 printk("ALI 1533 SB not found.\n"); 77 pci_dev_put(pmu_dev); 78 return -ENODEV; 79 } 80 81 /* Set SB_MPS1 to enable brightness control. */ 82 pci_read_config_byte(sb_dev, SB_MPS1, &temp); 83 pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); 84 85 progear_backlight_device = backlight_device_register("progear-bl", 86 &pdev->dev, NULL, 87 &progearbl_ops); 88 if (IS_ERR(progear_backlight_device)) 89 return PTR_ERR(progear_backlight_device); 90 91 platform_set_drvdata(pdev, progear_backlight_device); 92 93 progear_backlight_device->props.power = FB_BLANK_UNBLANK; 94 progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; 95 progear_backlight_device->props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; 96 progearbl_set_intensity(progear_backlight_device); 97 98 return 0; 99} 100 101static int progearbl_remove(struct platform_device *pdev) 102{ 103 struct backlight_device *bd = platform_get_drvdata(pdev); 104 backlight_device_unregister(bd); 105 106 return 0; 107} 108 109static struct platform_driver progearbl_driver = { 110 .probe = progearbl_probe, 111 .remove = progearbl_remove, 112 .driver = { 113 .name = "progear-bl", 114 }, 115}; 116 117static struct platform_device *progearbl_device; 118 119static int __init progearbl_init(void) 120{ 121 int ret = platform_driver_register(&progearbl_driver); 122 123 if (!ret) { 124 progearbl_device = platform_device_alloc("progear-bl", -1); 125 if (!progearbl_device) 126 return -ENOMEM; 127 128 ret = platform_device_add(progearbl_device); 129 130 if (ret) { 131 platform_device_put(progearbl_device); 132 platform_driver_unregister(&progearbl_driver); 133 } 134 } 135 136 return ret; 137} 138 139static void __exit progearbl_exit(void) 140{ 141 pci_dev_put(pmu_dev); 142 pci_dev_put(sb_dev); 143 144 platform_device_unregister(progearbl_device); 145 platform_driver_unregister(&progearbl_driver); 146} 147 148module_init(progearbl_init); 149module_exit(progearbl_exit); 150 151MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>"); 152MODULE_DESCRIPTION("ProGear Backlight Driver"); 153MODULE_LICENSE("GPL"); 154