mtw(4) remove misplaced DEBUG_FLAGS
[freebsd/src.git] / sys / powerpc / powermac / atibl.c
blob1bc521f8bfad5f3fabb6617624e45494c3189041
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2012 Justin Hibbits
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <sys/param.h>
30 #include <sys/bus.h>
31 #include <sys/systm.h>
32 #include <sys/module.h>
33 #include <sys/kernel.h>
34 #include <sys/rman.h>
35 #include <sys/sysctl.h>
37 #include <machine/bus.h>
39 #include <dev/ofw/openfirm.h>
40 #include <dev/pci/pcivar.h>
42 #ifndef PCI_VENDOR_ID_ATI
43 #define PCI_VENDOR_ID_ATI 0x1002
44 #endif
46 /* From the xf86-video-ati driver's radeon_reg.h */
47 #define RADEON_LVDS_GEN_CNTL 0x02d0
48 #define RADEON_LVDS_ON (1 << 0)
49 #define RADEON_LVDS_DISPLAY_DIS (1 << 1)
50 #define RADEON_LVDS_PANEL_TYPE (1 << 2)
51 #define RADEON_LVDS_PANEL_FORMAT (1 << 3)
52 #define RADEON_LVDS_RST_FM (1 << 6)
53 #define RADEON_LVDS_EN (1 << 7)
54 #define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8
55 #define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8)
56 #define RADEON_LVDS_BL_MOD_EN (1 << 16)
57 #define RADEON_LVDS_DIGON (1 << 18)
58 #define RADEON_LVDS_BLON (1 << 19)
59 #define RADEON_LVDS_PLL_CNTL 0x02d4
60 #define RADEON_LVDS_PLL_EN (1 << 16)
61 #define RADEON_LVDS_PLL_RESET (1 << 17)
62 #define RADEON_PIXCLKS_CNTL 0x002d
63 #define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14)
64 #define RADEON_DISP_PWR_MAN 0x0d08
65 #define RADEON_AUTO_PWRUP_EN (1 << 26)
66 #define RADEON_CLOCK_CNTL_DATA 0x000c
67 #define RADEON_CLOCK_CNTL_INDEX 0x0008
68 #define RADEON_PLL_WR_EN (1 << 7)
69 #define RADEON_CRTC_GEN_CNTL 0x0050
71 struct atibl_softc {
72 struct resource *sc_memr;
73 int sc_level;
76 static void atibl_identify(driver_t *driver, device_t parent);
77 static int atibl_probe(device_t dev);
78 static int atibl_attach(device_t dev);
79 static int atibl_setlevel(struct atibl_softc *sc, int newlevel);
80 static int atibl_getlevel(struct atibl_softc *sc);
81 static int atibl_resume(device_t dev);
82 static int atibl_suspend(device_t dev);
83 static int atibl_sysctl(SYSCTL_HANDLER_ARGS);
85 static device_method_t atibl_methods[] = {
86 /* Device interface */
87 DEVMETHOD(device_identify, atibl_identify),
88 DEVMETHOD(device_probe, atibl_probe),
89 DEVMETHOD(device_attach, atibl_attach),
90 DEVMETHOD(device_suspend, atibl_suspend),
91 DEVMETHOD(device_resume, atibl_resume),
92 {0, 0},
95 static driver_t atibl_driver = {
96 "backlight",
97 atibl_methods,
98 sizeof(struct atibl_softc)
101 DRIVER_MODULE(atibl, vgapci, atibl_driver, 0, 0);
103 static void
104 atibl_identify(driver_t *driver, device_t parent)
106 if (OF_finddevice("mac-io/backlight") == -1)
107 return;
108 if (device_find_child(parent, "backlight", -1) == NULL)
109 device_add_child(parent, "backlight", DEVICE_UNIT_ANY);
112 static int
113 atibl_probe(device_t dev)
115 char control[8];
116 phandle_t handle;
118 handle = OF_finddevice("mac-io/backlight");
120 if (handle == -1)
121 return (ENXIO);
123 if (OF_getprop(handle, "backlight-control", &control, sizeof(control)) < 0)
124 return (ENXIO);
126 if (strcmp(control, "ati") != 0 &&
127 (strcmp(control, "mnca") != 0 ||
128 pci_get_vendor(device_get_parent(dev)) != 0x1002))
129 return (ENXIO);
131 device_set_desc(dev, "PowerBook backlight for ATI graphics");
133 return (0);
136 static int
137 atibl_attach(device_t dev)
139 struct atibl_softc *sc;
140 struct sysctl_ctx_list *ctx;
141 struct sysctl_oid *tree;
142 int rid;
144 sc = device_get_softc(dev);
146 rid = 0x18; /* BAR[2], for the MMIO register */
147 sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
148 RF_ACTIVE | RF_SHAREABLE);
149 if (sc->sc_memr == NULL) {
150 device_printf(dev, "Could not alloc mem resource!\n");
151 return (ENXIO);
154 ctx = device_get_sysctl_ctx(dev);
155 tree = device_get_sysctl_tree(dev);
157 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
158 "level", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
159 atibl_sysctl, "I", "Backlight level (0-100)");
161 return (0);
164 static uint32_t __inline
165 atibl_pll_rreg(struct atibl_softc *sc, uint32_t reg)
167 uint32_t data, save, tmp;
169 bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, (reg & 0x3f));
170 (void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
171 (void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL);
173 data = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
175 /* Only necessary on R300, but won't hurt others. */
176 save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX);
177 tmp = save & (~0x3f | RADEON_PLL_WR_EN);
178 bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp);
179 tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
180 bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save);
182 return data;
185 static void __inline
186 atibl_pll_wreg(struct atibl_softc *sc, uint32_t reg, uint32_t val)
188 uint32_t save, tmp;
190 bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX,
191 ((reg & 0x3f) | RADEON_PLL_WR_EN));
192 (void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
193 (void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL);
195 bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA, val);
196 DELAY(5000);
198 /* Only necessary on R300, but won't hurt others. */
199 save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX);
200 tmp = save & (~0x3f | RADEON_PLL_WR_EN);
201 bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp);
202 tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
203 bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save);
206 static int
207 atibl_setlevel(struct atibl_softc *sc, int newlevel)
209 uint32_t lvds_gen_cntl;
210 uint32_t lvds_pll_cntl;
211 uint32_t pixclks_cntl;
212 uint32_t disp_pwr_reg;
214 if (newlevel > 100)
215 newlevel = 100;
217 if (newlevel < 0)
218 newlevel = 0;
220 lvds_gen_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL);
222 if (newlevel > 0) {
223 newlevel = (newlevel * 5) / 2 + 5;
224 disp_pwr_reg = bus_read_4(sc->sc_memr, RADEON_DISP_PWR_MAN);
225 disp_pwr_reg |= RADEON_AUTO_PWRUP_EN;
226 bus_write_4(sc->sc_memr, RADEON_DISP_PWR_MAN, disp_pwr_reg);
227 lvds_pll_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL);
228 lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
229 bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
230 lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
231 bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
232 DELAY(1000);
234 lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
235 RADEON_LVDS_BL_MOD_LEVEL_MASK);
236 lvds_gen_cntl |= RADEON_LVDS_ON | RADEON_LVDS_EN |
237 RADEON_LVDS_DIGON | RADEON_LVDS_BLON;
238 lvds_gen_cntl |= (newlevel << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) &
239 RADEON_LVDS_BL_MOD_LEVEL_MASK;
240 lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
241 DELAY(200000);
242 bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
243 } else {
244 pixclks_cntl = atibl_pll_rreg(sc, RADEON_PIXCLKS_CNTL);
245 atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL,
246 pixclks_cntl & ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
247 lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
248 lvds_gen_cntl &= ~(RADEON_LVDS_BL_MOD_EN | RADEON_LVDS_BL_MOD_LEVEL_MASK);
249 bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
250 lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
251 DELAY(200000);
252 bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
254 atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL, pixclks_cntl);
255 DELAY(200000);
258 return (0);
261 static int
262 atibl_getlevel(struct atibl_softc *sc)
264 uint32_t lvds_gen_cntl;
265 int level;
267 lvds_gen_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL);
269 level = ((lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >>
270 RADEON_LVDS_BL_MOD_LEVEL_SHIFT);
271 if (level != 0)
272 level = ((level - 5) * 2) / 5;
274 return (level);
277 static int
278 atibl_suspend(device_t dev)
280 struct atibl_softc *sc;
282 sc = device_get_softc(dev);
284 sc->sc_level = atibl_getlevel(sc);
285 atibl_setlevel(sc, 0);
287 return (0);
290 static int
291 atibl_resume(device_t dev)
293 struct atibl_softc *sc;
295 sc = device_get_softc(dev);
297 atibl_setlevel(sc, sc->sc_level);
299 return (0);
302 static int
303 atibl_sysctl(SYSCTL_HANDLER_ARGS)
305 struct atibl_softc *sc;
306 int newlevel, error;
308 sc = arg1;
310 newlevel = atibl_getlevel(sc);
312 error = sysctl_handle_int(oidp, &newlevel, 0, req);
314 if (error || !req->newptr)
315 return (error);
317 return (atibl_setlevel(sc, newlevel));