root/drivers/video/backlight/cr_bllcd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cr_backlight_set_intensity
  2. cr_backlight_get_intensity
  3. cr_panel_on
  4. cr_panel_off
  5. cr_lcd_set_power
  6. cr_backlight_probe
  7. cr_backlight_remove
  8. cr_backlight_init
  9. cr_backlight_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (c) Intel Corp. 2007.
   4  * All Rights Reserved.
   5  *
   6  * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
   7  * develop this driver.
   8  *
   9  * This file is part of the Carillo Ranch video subsystem driver.
  10  *
  11  * Authors:
  12  *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
  13  *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
  14  */
  15 
  16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  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/lcd.h>
  26 #include <linux/pci.h>
  27 #include <linux/slab.h>
  28 
  29 /* The LVDS- and panel power controls sits on the
  30  * GPIO port of the ISA bridge.
  31  */
  32 
  33 #define CRVML_DEVICE_LPC    0x27B8
  34 #define CRVML_REG_GPIOBAR   0x48
  35 #define CRVML_REG_GPIOEN    0x4C
  36 #define CRVML_GPIOEN_BIT    (1 << 4)
  37 #define CRVML_PANEL_PORT    0x38
  38 #define CRVML_LVDS_ON       0x00000001
  39 #define CRVML_PANEL_ON      0x00000002
  40 #define CRVML_BACKLIGHT_OFF 0x00000004
  41 
  42 /* The PLL Clock register sits on Host bridge */
  43 #define CRVML_DEVICE_MCH   0x5001
  44 #define CRVML_REG_MCHBAR   0x44
  45 #define CRVML_REG_MCHEN    0x54
  46 #define CRVML_MCHEN_BIT    (1 << 28)
  47 #define CRVML_MCHMAP_SIZE  4096
  48 #define CRVML_REG_CLOCK    0xc3c
  49 #define CRVML_CLOCK_SHIFT  8
  50 #define CRVML_CLOCK_MASK   0x00000f00
  51 
  52 static struct pci_dev *lpc_dev;
  53 static u32 gpio_bar;
  54 
  55 struct cr_panel {
  56         struct backlight_device *cr_backlight_device;
  57         struct lcd_device *cr_lcd_device;
  58 };
  59 
  60 static int cr_backlight_set_intensity(struct backlight_device *bd)
  61 {
  62         int intensity = bd->props.brightness;
  63         u32 addr = gpio_bar + CRVML_PANEL_PORT;
  64         u32 cur = inl(addr);
  65 
  66         if (bd->props.power == FB_BLANK_UNBLANK)
  67                 intensity = FB_BLANK_UNBLANK;
  68         if (bd->props.fb_blank == FB_BLANK_UNBLANK)
  69                 intensity = FB_BLANK_UNBLANK;
  70         if (bd->props.power == FB_BLANK_POWERDOWN)
  71                 intensity = FB_BLANK_POWERDOWN;
  72         if (bd->props.fb_blank == FB_BLANK_POWERDOWN)
  73                 intensity = FB_BLANK_POWERDOWN;
  74 
  75         if (intensity == FB_BLANK_UNBLANK) { /* FULL ON */
  76                 cur &= ~CRVML_BACKLIGHT_OFF;
  77                 outl(cur, addr);
  78         } else if (intensity == FB_BLANK_POWERDOWN) { /* OFF */
  79                 cur |= CRVML_BACKLIGHT_OFF;
  80                 outl(cur, addr);
  81         } /* anything else, don't bother */
  82 
  83         return 0;
  84 }
  85 
  86 static int cr_backlight_get_intensity(struct backlight_device *bd)
  87 {
  88         u32 addr = gpio_bar + CRVML_PANEL_PORT;
  89         u32 cur = inl(addr);
  90         u8 intensity;
  91 
  92         if (cur & CRVML_BACKLIGHT_OFF)
  93                 intensity = FB_BLANK_POWERDOWN;
  94         else
  95                 intensity = FB_BLANK_UNBLANK;
  96 
  97         return intensity;
  98 }
  99 
 100 static const struct backlight_ops cr_backlight_ops = {
 101         .get_brightness = cr_backlight_get_intensity,
 102         .update_status = cr_backlight_set_intensity,
 103 };
 104 
 105 static void cr_panel_on(void)
 106 {
 107         u32 addr = gpio_bar + CRVML_PANEL_PORT;
 108         u32 cur = inl(addr);
 109 
 110         if (!(cur & CRVML_PANEL_ON)) {
 111                 /* Make sure LVDS controller is down. */
 112                 if (cur & 0x00000001) {
 113                         cur &= ~CRVML_LVDS_ON;
 114                         outl(cur, addr);
 115                 }
 116                 /* Power up Panel */
 117                 schedule_timeout(HZ / 10);
 118                 cur |= CRVML_PANEL_ON;
 119                 outl(cur, addr);
 120         }
 121 
 122         /* Power up LVDS controller */
 123 
 124         if (!(cur & CRVML_LVDS_ON)) {
 125                 schedule_timeout(HZ / 10);
 126                 outl(cur | CRVML_LVDS_ON, addr);
 127         }
 128 }
 129 
 130 static void cr_panel_off(void)
 131 {
 132         u32 addr = gpio_bar + CRVML_PANEL_PORT;
 133         u32 cur = inl(addr);
 134 
 135         /* Power down LVDS controller first to avoid high currents */
 136         if (cur & CRVML_LVDS_ON) {
 137                 cur &= ~CRVML_LVDS_ON;
 138                 outl(cur, addr);
 139         }
 140         if (cur & CRVML_PANEL_ON) {
 141                 schedule_timeout(HZ / 10);
 142                 outl(cur & ~CRVML_PANEL_ON, addr);
 143         }
 144 }
 145 
 146 static int cr_lcd_set_power(struct lcd_device *ld, int power)
 147 {
 148         if (power == FB_BLANK_UNBLANK)
 149                 cr_panel_on();
 150         if (power == FB_BLANK_POWERDOWN)
 151                 cr_panel_off();
 152 
 153         return 0;
 154 }
 155 
 156 static struct lcd_ops cr_lcd_ops = {
 157         .set_power = cr_lcd_set_power,
 158 };
 159 
 160 static int cr_backlight_probe(struct platform_device *pdev)
 161 {
 162         struct backlight_properties props;
 163         struct backlight_device *bdp;
 164         struct lcd_device *ldp;
 165         struct cr_panel *crp;
 166         u8 dev_en;
 167 
 168         lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
 169                                         CRVML_DEVICE_LPC, NULL);
 170         if (!lpc_dev) {
 171                 pr_err("INTEL CARILLO RANCH LPC not found.\n");
 172                 return -ENODEV;
 173         }
 174 
 175         pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
 176         if (!(dev_en & CRVML_GPIOEN_BIT)) {
 177                 pr_err("Carillo Ranch GPIO device was not enabled.\n");
 178                 pci_dev_put(lpc_dev);
 179                 return -ENODEV;
 180         }
 181 
 182         memset(&props, 0, sizeof(struct backlight_properties));
 183         props.type = BACKLIGHT_RAW;
 184         bdp = devm_backlight_device_register(&pdev->dev, "cr-backlight",
 185                                         &pdev->dev, NULL, &cr_backlight_ops,
 186                                         &props);
 187         if (IS_ERR(bdp)) {
 188                 pci_dev_put(lpc_dev);
 189                 return PTR_ERR(bdp);
 190         }
 191 
 192         ldp = devm_lcd_device_register(&pdev->dev, "cr-lcd", &pdev->dev, NULL,
 193                                         &cr_lcd_ops);
 194         if (IS_ERR(ldp)) {
 195                 pci_dev_put(lpc_dev);
 196                 return PTR_ERR(ldp);
 197         }
 198 
 199         pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
 200                               &gpio_bar);
 201         gpio_bar &= ~0x3F;
 202 
 203         crp = devm_kzalloc(&pdev->dev, sizeof(*crp), GFP_KERNEL);
 204         if (!crp) {
 205                 pci_dev_put(lpc_dev);
 206                 return -ENOMEM;
 207         }
 208 
 209         crp->cr_backlight_device = bdp;
 210         crp->cr_lcd_device = ldp;
 211         crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK;
 212         crp->cr_backlight_device->props.brightness = 0;
 213         cr_backlight_set_intensity(crp->cr_backlight_device);
 214         cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK);
 215 
 216         platform_set_drvdata(pdev, crp);
 217 
 218         return 0;
 219 }
 220 
 221 static int cr_backlight_remove(struct platform_device *pdev)
 222 {
 223         struct cr_panel *crp = platform_get_drvdata(pdev);
 224 
 225         crp->cr_backlight_device->props.power = FB_BLANK_POWERDOWN;
 226         crp->cr_backlight_device->props.brightness = 0;
 227         crp->cr_backlight_device->props.max_brightness = 0;
 228         cr_backlight_set_intensity(crp->cr_backlight_device);
 229         cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN);
 230         pci_dev_put(lpc_dev);
 231 
 232         return 0;
 233 }
 234 
 235 static struct platform_driver cr_backlight_driver = {
 236         .probe = cr_backlight_probe,
 237         .remove = cr_backlight_remove,
 238         .driver = {
 239                    .name = "cr_backlight",
 240                    },
 241 };
 242 
 243 static struct platform_device *crp;
 244 
 245 static int __init cr_backlight_init(void)
 246 {
 247         int ret = platform_driver_register(&cr_backlight_driver);
 248 
 249         if (ret)
 250                 return ret;
 251 
 252         crp = platform_device_register_simple("cr_backlight", -1, NULL, 0);
 253         if (IS_ERR(crp)) {
 254                 platform_driver_unregister(&cr_backlight_driver);
 255                 return PTR_ERR(crp);
 256         }
 257 
 258         pr_info("Carillo Ranch Backlight Driver Initialized.\n");
 259 
 260         return 0;
 261 }
 262 
 263 static void __exit cr_backlight_exit(void)
 264 {
 265         platform_device_unregister(crp);
 266         platform_driver_unregister(&cr_backlight_driver);
 267 }
 268 
 269 module_init(cr_backlight_init);
 270 module_exit(cr_backlight_exit);
 271 
 272 MODULE_AUTHOR("Tungsten Graphics Inc.");
 273 MODULE_DESCRIPTION("Carillo Ranch Backlight Driver");
 274 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */