linux/drivers/video/backlight/lp855x_bl.c
<<
>>
Prefs
   1/*
   2 * TI LP855x Backlight Driver
   3 *
   4 *                      Copyright (C) 2011 Texas Instruments
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/slab.h>
  14#include <linux/i2c.h>
  15#include <linux/backlight.h>
  16#include <linux/delay.h>
  17#include <linux/err.h>
  18#include <linux/of.h>
  19#include <linux/platform_data/lp855x.h>
  20#include <linux/pwm.h>
  21#include <linux/regulator/consumer.h>
  22
  23/* LP8550/1/2/3/6 Registers */
  24#define LP855X_BRIGHTNESS_CTRL          0x00
  25#define LP855X_DEVICE_CTRL              0x01
  26#define LP855X_EEPROM_START             0xA0
  27#define LP855X_EEPROM_END               0xA7
  28#define LP8556_EPROM_START              0xA0
  29#define LP8556_EPROM_END                0xAF
  30
  31/* LP8555/7 Registers */
  32#define LP8557_BL_CMD                   0x00
  33#define LP8557_BL_MASK                  0x01
  34#define LP8557_BL_ON                    0x01
  35#define LP8557_BL_OFF                   0x00
  36#define LP8557_BRIGHTNESS_CTRL          0x04
  37#define LP8557_CONFIG                   0x10
  38#define LP8555_EPROM_START              0x10
  39#define LP8555_EPROM_END                0x7A
  40#define LP8557_EPROM_START              0x10
  41#define LP8557_EPROM_END                0x1E
  42
  43#define DEFAULT_BL_NAME         "lcd-backlight"
  44#define MAX_BRIGHTNESS          255
  45
  46enum lp855x_brightness_ctrl_mode {
  47        PWM_BASED = 1,
  48        REGISTER_BASED,
  49};
  50
  51struct lp855x;
  52
  53/*
  54 * struct lp855x_device_config
  55 * @pre_init_device: init device function call before updating the brightness
  56 * @reg_brightness: register address for brigthenss control
  57 * @reg_devicectrl: register address for device control
  58 * @post_init_device: late init device function call
  59 */
  60struct lp855x_device_config {
  61        int (*pre_init_device)(struct lp855x *);
  62        u8 reg_brightness;
  63        u8 reg_devicectrl;
  64        int (*post_init_device)(struct lp855x *);
  65};
  66
  67struct lp855x {
  68        const char *chipname;
  69        enum lp855x_chip_id chip_id;
  70        enum lp855x_brightness_ctrl_mode mode;
  71        struct lp855x_device_config *cfg;
  72        struct i2c_client *client;
  73        struct backlight_device *bl;
  74        struct device *dev;
  75        struct lp855x_platform_data *pdata;
  76        struct pwm_device *pwm;
  77        struct regulator *supply;       /* regulator for VDD input */
  78        struct regulator *enable;       /* regulator for EN/VDDIO input */
  79};
  80
  81static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data)
  82{
  83        return i2c_smbus_write_byte_data(lp->client, reg, data);
  84}
  85
  86static int lp855x_update_bit(struct lp855x *lp, u8 reg, u8 mask, u8 data)
  87{
  88        int ret;
  89        u8 tmp;
  90
  91        ret = i2c_smbus_read_byte_data(lp->client, reg);
  92        if (ret < 0) {
  93                dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
  94                return ret;
  95        }
  96
  97        tmp = (u8)ret;
  98        tmp &= ~mask;
  99        tmp |= data & mask;
 100
 101        return lp855x_write_byte(lp, reg, tmp);
 102}
 103
 104static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr)
 105{
 106        u8 start, end;
 107
 108        switch (lp->chip_id) {
 109        case LP8550:
 110        case LP8551:
 111        case LP8552:
 112        case LP8553:
 113                start = LP855X_EEPROM_START;
 114                end = LP855X_EEPROM_END;
 115                break;
 116        case LP8556:
 117                start = LP8556_EPROM_START;
 118                end = LP8556_EPROM_END;
 119                break;
 120        case LP8555:
 121                start = LP8555_EPROM_START;
 122                end = LP8555_EPROM_END;
 123                break;
 124        case LP8557:
 125                start = LP8557_EPROM_START;
 126                end = LP8557_EPROM_END;
 127                break;
 128        default:
 129                return false;
 130        }
 131
 132        return addr >= start && addr <= end;
 133}
 134
 135static int lp8557_bl_off(struct lp855x *lp)
 136{
 137        /* BL_ON = 0 before updating EPROM settings */
 138        return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK,
 139                                LP8557_BL_OFF);
 140}
 141
 142static int lp8557_bl_on(struct lp855x *lp)
 143{
 144        /* BL_ON = 1 after updating EPROM settings */
 145        return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK,
 146                                LP8557_BL_ON);
 147}
 148
 149static struct lp855x_device_config lp855x_dev_cfg = {
 150        .reg_brightness = LP855X_BRIGHTNESS_CTRL,
 151        .reg_devicectrl = LP855X_DEVICE_CTRL,
 152};
 153
 154static struct lp855x_device_config lp8557_dev_cfg = {
 155        .reg_brightness = LP8557_BRIGHTNESS_CTRL,
 156        .reg_devicectrl = LP8557_CONFIG,
 157        .pre_init_device = lp8557_bl_off,
 158        .post_init_device = lp8557_bl_on,
 159};
 160
 161/*
 162 * Device specific configuration flow
 163 *
 164 *    a) pre_init_device(optional)
 165 *    b) update the brightness register
 166 *    c) update device control register
 167 *    d) update ROM area(optional)
 168 *    e) post_init_device(optional)
 169 *
 170 */
 171static int lp855x_configure(struct lp855x *lp)
 172{
 173        u8 val, addr;
 174        int i, ret;
 175        struct lp855x_platform_data *pd = lp->pdata;
 176
 177        switch (lp->chip_id) {
 178        case LP8550:
 179        case LP8551:
 180        case LP8552:
 181        case LP8553:
 182        case LP8556:
 183                lp->cfg = &lp855x_dev_cfg;
 184                break;
 185        case LP8555:
 186        case LP8557:
 187                lp->cfg = &lp8557_dev_cfg;
 188                break;
 189        default:
 190                return -EINVAL;
 191        }
 192
 193        if (lp->cfg->pre_init_device) {
 194                ret = lp->cfg->pre_init_device(lp);
 195                if (ret) {
 196                        dev_err(lp->dev, "pre init device err: %d\n", ret);
 197                        goto err;
 198                }
 199        }
 200
 201        val = pd->initial_brightness;
 202        ret = lp855x_write_byte(lp, lp->cfg->reg_brightness, val);
 203        if (ret)
 204                goto err;
 205
 206        val = pd->device_control;
 207        ret = lp855x_write_byte(lp, lp->cfg->reg_devicectrl, val);
 208        if (ret)
 209                goto err;
 210
 211        if (pd->size_program > 0) {
 212                for (i = 0; i < pd->size_program; i++) {
 213                        addr = pd->rom_data[i].addr;
 214                        val = pd->rom_data[i].val;
 215                        if (!lp855x_is_valid_rom_area(lp, addr))
 216                                continue;
 217
 218                        ret = lp855x_write_byte(lp, addr, val);
 219                        if (ret)
 220                                goto err;
 221                }
 222        }
 223
 224        if (lp->cfg->post_init_device) {
 225                ret = lp->cfg->post_init_device(lp);
 226                if (ret) {
 227                        dev_err(lp->dev, "post init device err: %d\n", ret);
 228                        goto err;
 229                }
 230        }
 231
 232        return 0;
 233
 234err:
 235        return ret;
 236}
 237
 238static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
 239{
 240        unsigned int period = lp->pdata->period_ns;
 241        unsigned int duty = br * period / max_br;
 242        struct pwm_device *pwm;
 243
 244        /* request pwm device with the consumer name */
 245        if (!lp->pwm) {
 246                pwm = devm_pwm_get(lp->dev, lp->chipname);
 247                if (IS_ERR(pwm))
 248                        return;
 249
 250                lp->pwm = pwm;
 251
 252                /*
 253                 * FIXME: pwm_apply_args() should be removed when switching to
 254                 * the atomic PWM API.
 255                 */
 256                pwm_apply_args(pwm);
 257        }
 258
 259        pwm_config(lp->pwm, duty, period);
 260        if (duty)
 261                pwm_enable(lp->pwm);
 262        else
 263                pwm_disable(lp->pwm);
 264}
 265
 266static int lp855x_bl_update_status(struct backlight_device *bl)
 267{
 268        struct lp855x *lp = bl_get_data(bl);
 269        int brightness = bl->props.brightness;
 270
 271        if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
 272                brightness = 0;
 273
 274        if (lp->mode == PWM_BASED)
 275                lp855x_pwm_ctrl(lp, brightness, bl->props.max_brightness);
 276        else if (lp->mode == REGISTER_BASED)
 277                lp855x_write_byte(lp, lp->cfg->reg_brightness, (u8)brightness);
 278
 279        return 0;
 280}
 281
 282static const struct backlight_ops lp855x_bl_ops = {
 283        .options = BL_CORE_SUSPENDRESUME,
 284        .update_status = lp855x_bl_update_status,
 285};
 286
 287static int lp855x_backlight_register(struct lp855x *lp)
 288{
 289        struct backlight_device *bl;
 290        struct backlight_properties props;
 291        struct lp855x_platform_data *pdata = lp->pdata;
 292        const char *name = pdata->name ? : DEFAULT_BL_NAME;
 293
 294        memset(&props, 0, sizeof(props));
 295        props.type = BACKLIGHT_PLATFORM;
 296        props.max_brightness = MAX_BRIGHTNESS;
 297
 298        if (pdata->initial_brightness > props.max_brightness)
 299                pdata->initial_brightness = props.max_brightness;
 300
 301        props.brightness = pdata->initial_brightness;
 302
 303        bl = devm_backlight_device_register(lp->dev, name, lp->dev, lp,
 304                                       &lp855x_bl_ops, &props);
 305        if (IS_ERR(bl))
 306                return PTR_ERR(bl);
 307
 308        lp->bl = bl;
 309
 310        return 0;
 311}
 312
 313static ssize_t lp855x_get_chip_id(struct device *dev,
 314                                struct device_attribute *attr, char *buf)
 315{
 316        struct lp855x *lp = dev_get_drvdata(dev);
 317
 318        return scnprintf(buf, PAGE_SIZE, "%s\n", lp->chipname);
 319}
 320
 321static ssize_t lp855x_get_bl_ctl_mode(struct device *dev,
 322                                     struct device_attribute *attr, char *buf)
 323{
 324        struct lp855x *lp = dev_get_drvdata(dev);
 325        char *strmode = NULL;
 326
 327        if (lp->mode == PWM_BASED)
 328                strmode = "pwm based";
 329        else if (lp->mode == REGISTER_BASED)
 330                strmode = "register based";
 331
 332        return scnprintf(buf, PAGE_SIZE, "%s\n", strmode);
 333}
 334
 335static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL);
 336static DEVICE_ATTR(bl_ctl_mode, S_IRUGO, lp855x_get_bl_ctl_mode, NULL);
 337
 338static struct attribute *lp855x_attributes[] = {
 339        &dev_attr_chip_id.attr,
 340        &dev_attr_bl_ctl_mode.attr,
 341        NULL,
 342};
 343
 344static const struct attribute_group lp855x_attr_group = {
 345        .attrs = lp855x_attributes,
 346};
 347
 348#ifdef CONFIG_OF
 349static int lp855x_parse_dt(struct lp855x *lp)
 350{
 351        struct device *dev = lp->dev;
 352        struct device_node *node = dev->of_node;
 353        struct lp855x_platform_data *pdata;
 354        int rom_length;
 355
 356        if (!node) {
 357                dev_err(dev, "no platform data\n");
 358                return -EINVAL;
 359        }
 360
 361        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 362        if (!pdata)
 363                return -ENOMEM;
 364
 365        of_property_read_string(node, "bl-name", &pdata->name);
 366        of_property_read_u8(node, "dev-ctrl", &pdata->device_control);
 367        of_property_read_u8(node, "init-brt", &pdata->initial_brightness);
 368        of_property_read_u32(node, "pwm-period", &pdata->period_ns);
 369
 370        /* Fill ROM platform data if defined */
 371        rom_length = of_get_child_count(node);
 372        if (rom_length > 0) {
 373                struct lp855x_rom_data *rom;
 374                struct device_node *child;
 375                int i = 0;
 376
 377                rom = devm_kzalloc(dev, sizeof(*rom) * rom_length, GFP_KERNEL);
 378                if (!rom)
 379                        return -ENOMEM;
 380
 381                for_each_child_of_node(node, child) {
 382                        of_property_read_u8(child, "rom-addr", &rom[i].addr);
 383                        of_property_read_u8(child, "rom-val", &rom[i].val);
 384                        i++;
 385                }
 386
 387                pdata->size_program = rom_length;
 388                pdata->rom_data = &rom[0];
 389        }
 390
 391        lp->pdata = pdata;
 392
 393        return 0;
 394}
 395#else
 396static int lp855x_parse_dt(struct lp855x *lp)
 397{
 398        return -EINVAL;
 399}
 400#endif
 401
 402static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 403{
 404        struct lp855x *lp;
 405        int ret;
 406
 407        if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
 408                return -EIO;
 409
 410        lp = devm_kzalloc(&cl->dev, sizeof(struct lp855x), GFP_KERNEL);
 411        if (!lp)
 412                return -ENOMEM;
 413
 414        lp->client = cl;
 415        lp->dev = &cl->dev;
 416        lp->chipname = id->name;
 417        lp->chip_id = id->driver_data;
 418        lp->pdata = dev_get_platdata(&cl->dev);
 419
 420        if (!lp->pdata) {
 421                ret = lp855x_parse_dt(lp);
 422                if (ret < 0)
 423                        return ret;
 424        }
 425
 426        if (lp->pdata->period_ns > 0)
 427                lp->mode = PWM_BASED;
 428        else
 429                lp->mode = REGISTER_BASED;
 430
 431        lp->supply = devm_regulator_get(lp->dev, "power");
 432        if (IS_ERR(lp->supply)) {
 433                if (PTR_ERR(lp->supply) == -EPROBE_DEFER)
 434                        return -EPROBE_DEFER;
 435                lp->supply = NULL;
 436        }
 437
 438        lp->enable = devm_regulator_get_optional(lp->dev, "enable");
 439        if (IS_ERR(lp->enable)) {
 440                ret = PTR_ERR(lp->enable);
 441                if (ret == -ENODEV) {
 442                        lp->enable = NULL;
 443                } else {
 444                        if (ret != -EPROBE_DEFER)
 445                                dev_err(lp->dev, "error getting enable regulator: %d\n",
 446                                        ret);
 447                        return ret;
 448                }
 449        }
 450
 451        if (lp->supply) {
 452                ret = regulator_enable(lp->supply);
 453                if (ret < 0) {
 454                        dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
 455                        return ret;
 456                }
 457        }
 458
 459        if (lp->enable) {
 460                ret = regulator_enable(lp->enable);
 461                if (ret < 0) {
 462                        dev_err(lp->dev, "failed to enable vddio: %d\n", ret);
 463                        return ret;
 464                }
 465
 466                /*
 467                 * LP8555 datasheet says t_RESPONSE (time between VDDIO and
 468                 * I2C) is 1ms.
 469                 */
 470                usleep_range(1000, 2000);
 471        }
 472
 473        i2c_set_clientdata(cl, lp);
 474
 475        ret = lp855x_configure(lp);
 476        if (ret) {
 477                dev_err(lp->dev, "device config err: %d", ret);
 478                return ret;
 479        }
 480
 481        ret = lp855x_backlight_register(lp);
 482        if (ret) {
 483                dev_err(lp->dev,
 484                        "failed to register backlight. err: %d\n", ret);
 485                return ret;
 486        }
 487
 488        ret = sysfs_create_group(&lp->dev->kobj, &lp855x_attr_group);
 489        if (ret) {
 490                dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret);
 491                return ret;
 492        }
 493
 494        backlight_update_status(lp->bl);
 495        return 0;
 496}
 497
 498static int lp855x_remove(struct i2c_client *cl)
 499{
 500        struct lp855x *lp = i2c_get_clientdata(cl);
 501
 502        lp->bl->props.brightness = 0;
 503        backlight_update_status(lp->bl);
 504        if (lp->supply)
 505                regulator_disable(lp->supply);
 506        sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
 507
 508        return 0;
 509}
 510
 511static const struct of_device_id lp855x_dt_ids[] = {
 512        { .compatible = "ti,lp8550", },
 513        { .compatible = "ti,lp8551", },
 514        { .compatible = "ti,lp8552", },
 515        { .compatible = "ti,lp8553", },
 516        { .compatible = "ti,lp8555", },
 517        { .compatible = "ti,lp8556", },
 518        { .compatible = "ti,lp8557", },
 519        { }
 520};
 521MODULE_DEVICE_TABLE(of, lp855x_dt_ids);
 522
 523static const struct i2c_device_id lp855x_ids[] = {
 524        {"lp8550", LP8550},
 525        {"lp8551", LP8551},
 526        {"lp8552", LP8552},
 527        {"lp8553", LP8553},
 528        {"lp8555", LP8555},
 529        {"lp8556", LP8556},
 530        {"lp8557", LP8557},
 531        { }
 532};
 533MODULE_DEVICE_TABLE(i2c, lp855x_ids);
 534
 535static struct i2c_driver lp855x_driver = {
 536        .driver = {
 537                   .name = "lp855x",
 538                   .of_match_table = of_match_ptr(lp855x_dt_ids),
 539                   },
 540        .probe = lp855x_probe,
 541        .remove = lp855x_remove,
 542        .id_table = lp855x_ids,
 543};
 544
 545module_i2c_driver(lp855x_driver);
 546
 547MODULE_DESCRIPTION("Texas Instruments LP855x Backlight driver");
 548MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
 549MODULE_LICENSE("GPL");
 550