13d831da8d9687c173218ed0322b177664c86ee1
[pandora-kernel.git] / drivers / video / backlight / progear_bl.c
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
33 static struct pci_dev *pmu_dev = NULL;
34 static struct pci_dev *sb_dev = NULL;
35
36 static 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
50 static 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
58 static struct backlight_properties progearbl_data = {
59         .owner = THIS_MODULE,
60         .get_brightness = progearbl_get_intensity,
61         .update_status = progearbl_set_intensity,
62 };
63
64 static int progearbl_probe(struct platform_device *pdev)
65 {
66         u8 temp;
67         struct backlight_device *progear_backlight_device;
68
69         pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0);
70         if (!pmu_dev) {
71                 printk("ALI M7101 PMU not found.\n");
72                 return -ENODEV;
73         }
74
75         sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0);
76         if (!sb_dev) {
77                 printk("ALI 1533 SB not found.\n");
78                 pci_dev_put(pmu_dev);
79                 return -ENODEV;
80         }
81
82         /*     Set SB_MPS1 to enable brightness control. */
83         pci_read_config_byte(sb_dev, SB_MPS1, &temp);
84         pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
85
86         progear_backlight_device = backlight_device_register("progear-bl",
87                                                              &pdev->dev, NULL,
88                                                              &progearbl_data);
89         if (IS_ERR(progear_backlight_device))
90                 return PTR_ERR(progear_backlight_device);
91
92         platform_set_drvdata(pdev, progear_backlight_device);
93
94         progearbl_data.power = FB_BLANK_UNBLANK;
95         progearbl_data.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
96         progearbl_data.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
97         progearbl_set_intensity(progear_backlight_device);
98
99         return 0;
100 }
101
102 static int progearbl_remove(struct platform_device *pdev)
103 {
104         struct backlight_device *bd = platform_get_drvdata(pdev);
105         backlight_device_unregister(bd);
106
107         return 0;
108 }
109
110 static struct platform_driver progearbl_driver = {
111         .probe = progearbl_probe,
112         .remove = progearbl_remove,
113         .driver = {
114                    .name = "progear-bl",
115                    },
116 };
117
118 static struct platform_device *progearbl_device;
119
120 static int __init progearbl_init(void)
121 {
122         int ret = platform_driver_register(&progearbl_driver);
123
124         if (!ret) {
125                 progearbl_device = platform_device_alloc("progear-bl", -1);
126                 if (!progearbl_device)
127                         return -ENOMEM;
128
129                 ret = platform_device_add(progearbl_device);
130
131                 if (ret) {
132                         platform_device_put(progearbl_device);
133                         platform_driver_unregister(&progearbl_driver);
134                 }
135         }
136
137         return ret;
138 }
139
140 static void __exit progearbl_exit(void)
141 {
142         pci_dev_put(pmu_dev);
143         pci_dev_put(sb_dev);
144
145         platform_device_unregister(progearbl_device);
146         platform_driver_unregister(&progearbl_driver);
147 }
148
149 module_init(progearbl_init);
150 module_exit(progearbl_exit);
151
152 MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>");
153 MODULE_DESCRIPTION("ProGear Backlight Driver");
154 MODULE_LICENSE("GPL");