Commit | Line | Data |
---|---|---|
7a208463 MJ |
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 | ||
c3539731 JH |
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
19 | ||
7a208463 MJ |
20 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | |
22 | #include <linux/init.h> | |
23 | #include <linux/platform_device.h> | |
24 | #include <linux/mutex.h> | |
25 | #include <linux/fb.h> | |
26 | #include <linux/backlight.h> | |
27 | #include <linux/pci.h> | |
7a208463 MJ |
28 | |
29 | #define PMU_LPCR 0xB0 | |
30 | #define SB_MPS1 0x61 | |
31 | #define HW_LEVEL_MAX 0x77 | |
32 | #define HW_LEVEL_MIN 0x4f | |
33 | ||
34 | static struct pci_dev *pmu_dev = NULL; | |
35 | static struct pci_dev *sb_dev = NULL; | |
36 | ||
37 | static int progearbl_set_intensity(struct backlight_device *bd) | |
38 | { | |
599a52d1 | 39 | int intensity = bd->props.brightness; |
7a208463 | 40 | |
599a52d1 | 41 | if (bd->props.power != FB_BLANK_UNBLANK) |
7a208463 | 42 | intensity = 0; |
599a52d1 | 43 | if (bd->props.fb_blank != FB_BLANK_UNBLANK) |
7a208463 MJ |
44 | intensity = 0; |
45 | ||
46 | pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN); | |
47 | ||
48 | return 0; | |
49 | } | |
50 | ||
51 | static int progearbl_get_intensity(struct backlight_device *bd) | |
52 | { | |
53 | u8 intensity; | |
54 | pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity); | |
55 | ||
56 | return intensity - HW_LEVEL_MIN; | |
57 | } | |
58 | ||
9905a43b | 59 | static const struct backlight_ops progearbl_ops = { |
7a208463 MJ |
60 | .get_brightness = progearbl_get_intensity, |
61 | .update_status = progearbl_set_intensity, | |
62 | }; | |
63 | ||
64 | static int progearbl_probe(struct platform_device *pdev) | |
65 | { | |
a19a6ee6 | 66 | struct backlight_properties props; |
7a208463 MJ |
67 | u8 temp; |
68 | struct backlight_device *progear_backlight_device; | |
a4ebb780 | 69 | int ret; |
7a208463 | 70 | |
89952d13 | 71 | pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); |
7a208463 | 72 | if (!pmu_dev) { |
c3539731 | 73 | pr_err("ALI M7101 PMU not found.\n"); |
7a208463 MJ |
74 | return -ENODEV; |
75 | } | |
76 | ||
89952d13 | 77 | sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); |
7a208463 | 78 | if (!sb_dev) { |
c3539731 | 79 | pr_err("ALI 1533 SB not found.\n"); |
a4ebb780 JS |
80 | ret = -ENODEV; |
81 | goto put_pmu; | |
7a208463 MJ |
82 | } |
83 | ||
84 | /* Set SB_MPS1 to enable brightness control. */ | |
85 | pci_read_config_byte(sb_dev, SB_MPS1, &temp); | |
86 | pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); | |
87 | ||
a19a6ee6 | 88 | memset(&props, 0, sizeof(struct backlight_properties)); |
bb7ca747 | 89 | props.type = BACKLIGHT_RAW; |
a19a6ee6 | 90 | props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; |
7a208463 MJ |
91 | progear_backlight_device = backlight_device_register("progear-bl", |
92 | &pdev->dev, NULL, | |
a19a6ee6 MG |
93 | &progearbl_ops, |
94 | &props); | |
a4ebb780 JS |
95 | if (IS_ERR(progear_backlight_device)) { |
96 | ret = PTR_ERR(progear_backlight_device); | |
97 | goto put_sb; | |
98 | } | |
7a208463 MJ |
99 | |
100 | platform_set_drvdata(pdev, progear_backlight_device); | |
101 | ||
599a52d1 RP |
102 | progear_backlight_device->props.power = FB_BLANK_UNBLANK; |
103 | progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; | |
7a208463 MJ |
104 | progearbl_set_intensity(progear_backlight_device); |
105 | ||
106 | return 0; | |
a4ebb780 JS |
107 | put_sb: |
108 | pci_dev_put(sb_dev); | |
109 | put_pmu: | |
110 | pci_dev_put(pmu_dev); | |
111 | return ret; | |
7a208463 MJ |
112 | } |
113 | ||
114 | static int progearbl_remove(struct platform_device *pdev) | |
115 | { | |
116 | struct backlight_device *bd = platform_get_drvdata(pdev); | |
117 | backlight_device_unregister(bd); | |
118 | ||
119 | return 0; | |
120 | } | |
121 | ||
122 | static struct platform_driver progearbl_driver = { | |
123 | .probe = progearbl_probe, | |
124 | .remove = progearbl_remove, | |
125 | .driver = { | |
126 | .name = "progear-bl", | |
127 | }, | |
128 | }; | |
129 | ||
130 | static struct platform_device *progearbl_device; | |
131 | ||
132 | static int __init progearbl_init(void) | |
133 | { | |
134 | int ret = platform_driver_register(&progearbl_driver); | |
135 | ||
6cd6f35a AM |
136 | if (ret) |
137 | return ret; | |
138 | progearbl_device = platform_device_register_simple("progear-bl", -1, | |
139 | NULL, 0); | |
140 | if (IS_ERR(progearbl_device)) { | |
141 | platform_driver_unregister(&progearbl_driver); | |
142 | return PTR_ERR(progearbl_device); | |
7a208463 MJ |
143 | } |
144 | ||
6cd6f35a | 145 | return 0; |
7a208463 MJ |
146 | } |
147 | ||
148 | static void __exit progearbl_exit(void) | |
149 | { | |
150 | pci_dev_put(pmu_dev); | |
151 | pci_dev_put(sb_dev); | |
152 | ||
153 | platform_device_unregister(progearbl_device); | |
154 | platform_driver_unregister(&progearbl_driver); | |
155 | } | |
156 | ||
157 | module_init(progearbl_init); | |
158 | module_exit(progearbl_exit); | |
159 | ||
160 | MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>"); | |
161 | MODULE_DESCRIPTION("ProGear Backlight Driver"); | |
162 | MODULE_LICENSE("GPL"); |