linux/drivers/video/backlight/lm3630a_bl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3* Simple driver for Texas Instruments LM3630A Backlight driver chip
   4* Copyright (C) 2012 Texas Instruments
   5*/
   6#include <linux/module.h>
   7#include <linux/slab.h>
   8#include <linux/i2c.h>
   9#include <linux/backlight.h>
  10#include <linux/err.h>
  11#include <linux/delay.h>
  12#include <linux/uaccess.h>
  13#include <linux/interrupt.h>
  14#include <linux/regmap.h>
  15#include <linux/gpio/consumer.h>
  16#include <linux/pwm.h>
  17#include <linux/platform_data/lm3630a_bl.h>
  18
  19#define REG_CTRL        0x00
  20#define REG_BOOST       0x02
  21#define REG_CONFIG      0x01
  22#define REG_BRT_A       0x03
  23#define REG_BRT_B       0x04
  24#define REG_I_A         0x05
  25#define REG_I_B         0x06
  26#define REG_INT_STATUS  0x09
  27#define REG_INT_EN      0x0A
  28#define REG_FAULT       0x0B
  29#define REG_PWM_OUTLOW  0x12
  30#define REG_PWM_OUTHIGH 0x13
  31#define REG_FILTER_STRENGTH     0x50
  32#define REG_MAX         0x50
  33
  34#define INT_DEBOUNCE_MSEC       10
  35
  36#define LM3630A_BANK_0          0
  37#define LM3630A_BANK_1          1
  38
  39#define LM3630A_NUM_SINKS       2
  40#define LM3630A_SINK_0          0
  41#define LM3630A_SINK_1          1
  42
  43struct lm3630a_chip {
  44        struct device *dev;
  45        struct delayed_work work;
  46
  47        int irq;
  48        struct workqueue_struct *irqthread;
  49        struct lm3630a_platform_data *pdata;
  50        struct backlight_device *bleda;
  51        struct backlight_device *bledb;
  52        struct gpio_desc *enable_gpio;
  53        struct regmap *regmap;
  54        struct pwm_device *pwmd;
  55        struct pwm_state pwmd_state;
  56};
  57
  58/* i2c access */
  59static int lm3630a_read(struct lm3630a_chip *pchip, unsigned int reg)
  60{
  61        int rval;
  62        unsigned int reg_val;
  63
  64        rval = regmap_read(pchip->regmap, reg, &reg_val);
  65        if (rval < 0)
  66                return rval;
  67        return reg_val & 0xFF;
  68}
  69
  70static int lm3630a_write(struct lm3630a_chip *pchip,
  71                         unsigned int reg, unsigned int data)
  72{
  73        return regmap_write(pchip->regmap, reg, data);
  74}
  75
  76static int lm3630a_update(struct lm3630a_chip *pchip,
  77                          unsigned int reg, unsigned int mask,
  78                          unsigned int data)
  79{
  80        return regmap_update_bits(pchip->regmap, reg, mask, data);
  81}
  82
  83/* initialize chip */
  84static int lm3630a_chip_init(struct lm3630a_chip *pchip)
  85{
  86        int rval;
  87        struct lm3630a_platform_data *pdata = pchip->pdata;
  88
  89        usleep_range(1000, 2000);
  90        /* set Filter Strength Register */
  91        rval = lm3630a_write(pchip, REG_FILTER_STRENGTH, 0x03);
  92        /* set Cofig. register */
  93        rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl);
  94        /* set boost control */
  95        rval |= lm3630a_write(pchip, REG_BOOST, 0x38);
  96        /* set current A */
  97        rval |= lm3630a_update(pchip, REG_I_A, 0x1F, 0x1F);
  98        /* set current B */
  99        rval |= lm3630a_write(pchip, REG_I_B, 0x1F);
 100        /* set control */
 101        rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl);
 102        rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl);
 103        usleep_range(1000, 2000);
 104        /* set brightness A and B */
 105        rval |= lm3630a_write(pchip, REG_BRT_A, pdata->leda_init_brt);
 106        rval |= lm3630a_write(pchip, REG_BRT_B, pdata->ledb_init_brt);
 107
 108        if (rval < 0)
 109                dev_err(pchip->dev, "i2c failed to access register\n");
 110        return rval;
 111}
 112
 113/* interrupt handling */
 114static void lm3630a_delayed_func(struct work_struct *work)
 115{
 116        int rval;
 117        struct lm3630a_chip *pchip;
 118
 119        pchip = container_of(work, struct lm3630a_chip, work.work);
 120
 121        rval = lm3630a_read(pchip, REG_INT_STATUS);
 122        if (rval < 0) {
 123                dev_err(pchip->dev,
 124                        "i2c failed to access REG_INT_STATUS Register\n");
 125                return;
 126        }
 127
 128        dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", rval);
 129}
 130
 131static irqreturn_t lm3630a_isr_func(int irq, void *chip)
 132{
 133        int rval;
 134        struct lm3630a_chip *pchip = chip;
 135        unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
 136
 137        queue_delayed_work(pchip->irqthread, &pchip->work, delay);
 138
 139        rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
 140        if (rval < 0) {
 141                dev_err(pchip->dev, "i2c failed to access register\n");
 142                return IRQ_NONE;
 143        }
 144        return IRQ_HANDLED;
 145}
 146
 147static int lm3630a_intr_config(struct lm3630a_chip *pchip)
 148{
 149        int rval;
 150
 151        rval = lm3630a_write(pchip, REG_INT_EN, 0x87);
 152        if (rval < 0)
 153                return rval;
 154
 155        INIT_DELAYED_WORK(&pchip->work, lm3630a_delayed_func);
 156        pchip->irqthread = create_singlethread_workqueue("lm3630a-irqthd");
 157        if (!pchip->irqthread) {
 158                dev_err(pchip->dev, "create irq thread fail\n");
 159                return -ENOMEM;
 160        }
 161        if (request_threaded_irq
 162            (pchip->irq, NULL, lm3630a_isr_func,
 163             IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630a_irq", pchip)) {
 164                dev_err(pchip->dev, "request threaded irq fail\n");
 165                destroy_workqueue(pchip->irqthread);
 166                return -ENOMEM;
 167        }
 168        return rval;
 169}
 170
 171static int lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
 172{
 173        int err;
 174
 175        pchip->pwmd_state.period = pchip->pdata->pwm_period;
 176
 177        err = pwm_set_relative_duty_cycle(&pchip->pwmd_state, br, br_max);
 178        if (err)
 179                return err;
 180
 181        pchip->pwmd_state.enabled = pchip->pwmd_state.duty_cycle ? true : false;
 182
 183        return pwm_apply_state(pchip->pwmd, &pchip->pwmd_state);
 184}
 185
 186/* update and get brightness */
 187static int lm3630a_bank_a_update_status(struct backlight_device *bl)
 188{
 189        int ret;
 190        struct lm3630a_chip *pchip = bl_get_data(bl);
 191        enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
 192
 193        /* pwm control */
 194        if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0)
 195                return lm3630a_pwm_ctrl(pchip, bl->props.brightness,
 196                                        bl->props.max_brightness);
 197
 198        /* disable sleep */
 199        ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
 200        if (ret < 0)
 201                goto out_i2c_err;
 202        usleep_range(1000, 2000);
 203        /* minimum brightness is 0x04 */
 204        ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
 205        if (bl->props.brightness < 0x4)
 206                ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
 207        else
 208                ret |= lm3630a_update(pchip, REG_CTRL,
 209                                      LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE);
 210        if (ret < 0)
 211                goto out_i2c_err;
 212        return 0;
 213
 214out_i2c_err:
 215        dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret));
 216        return ret;
 217}
 218
 219static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
 220{
 221        int brightness, rval;
 222        struct lm3630a_chip *pchip = bl_get_data(bl);
 223        enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
 224
 225        if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) {
 226                rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
 227                if (rval < 0)
 228                        goto out_i2c_err;
 229                brightness = (rval & 0x01) << 8;
 230                rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
 231                if (rval < 0)
 232                        goto out_i2c_err;
 233                brightness |= rval;
 234                goto out;
 235        }
 236
 237        /* disable sleep */
 238        rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
 239        if (rval < 0)
 240                goto out_i2c_err;
 241        usleep_range(1000, 2000);
 242        rval = lm3630a_read(pchip, REG_BRT_A);
 243        if (rval < 0)
 244                goto out_i2c_err;
 245        brightness = rval;
 246
 247out:
 248        bl->props.brightness = brightness;
 249        return bl->props.brightness;
 250out_i2c_err:
 251        dev_err(pchip->dev, "i2c failed to access register\n");
 252        return 0;
 253}
 254
 255static const struct backlight_ops lm3630a_bank_a_ops = {
 256        .options = BL_CORE_SUSPENDRESUME,
 257        .update_status = lm3630a_bank_a_update_status,
 258        .get_brightness = lm3630a_bank_a_get_brightness,
 259};
 260
 261/* update and get brightness */
 262static int lm3630a_bank_b_update_status(struct backlight_device *bl)
 263{
 264        int ret;
 265        struct lm3630a_chip *pchip = bl_get_data(bl);
 266        enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
 267
 268        /* pwm control */
 269        if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0)
 270                return lm3630a_pwm_ctrl(pchip, bl->props.brightness,
 271                                        bl->props.max_brightness);
 272
 273        /* disable sleep */
 274        ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
 275        if (ret < 0)
 276                goto out_i2c_err;
 277        usleep_range(1000, 2000);
 278        /* minimum brightness is 0x04 */
 279        ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
 280        if (bl->props.brightness < 0x4)
 281                ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
 282        else
 283                ret |= lm3630a_update(pchip, REG_CTRL,
 284                                      LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE);
 285        if (ret < 0)
 286                goto out_i2c_err;
 287        return 0;
 288
 289out_i2c_err:
 290        dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret));
 291        return ret;
 292}
 293
 294static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
 295{
 296        int brightness, rval;
 297        struct lm3630a_chip *pchip = bl_get_data(bl);
 298        enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
 299
 300        if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) {
 301                rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
 302                if (rval < 0)
 303                        goto out_i2c_err;
 304                brightness = (rval & 0x01) << 8;
 305                rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
 306                if (rval < 0)
 307                        goto out_i2c_err;
 308                brightness |= rval;
 309                goto out;
 310        }
 311
 312        /* disable sleep */
 313        rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
 314        if (rval < 0)
 315                goto out_i2c_err;
 316        usleep_range(1000, 2000);
 317        rval = lm3630a_read(pchip, REG_BRT_B);
 318        if (rval < 0)
 319                goto out_i2c_err;
 320        brightness = rval;
 321
 322out:
 323        bl->props.brightness = brightness;
 324        return bl->props.brightness;
 325out_i2c_err:
 326        dev_err(pchip->dev, "i2c failed to access register\n");
 327        return 0;
 328}
 329
 330static const struct backlight_ops lm3630a_bank_b_ops = {
 331        .options = BL_CORE_SUSPENDRESUME,
 332        .update_status = lm3630a_bank_b_update_status,
 333        .get_brightness = lm3630a_bank_b_get_brightness,
 334};
 335
 336static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
 337{
 338        struct lm3630a_platform_data *pdata = pchip->pdata;
 339        struct backlight_properties props;
 340        const char *label;
 341
 342        props.type = BACKLIGHT_RAW;
 343        if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
 344                props.brightness = pdata->leda_init_brt;
 345                props.max_brightness = pdata->leda_max_brt;
 346                label = pdata->leda_label ? pdata->leda_label : "lm3630a_leda";
 347                pchip->bleda =
 348                    devm_backlight_device_register(pchip->dev, label,
 349                                                   pchip->dev, pchip,
 350                                                   &lm3630a_bank_a_ops, &props);
 351                if (IS_ERR(pchip->bleda))
 352                        return PTR_ERR(pchip->bleda);
 353        }
 354
 355        if ((pdata->ledb_ctrl != LM3630A_LEDB_DISABLE) &&
 356            (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) {
 357                props.brightness = pdata->ledb_init_brt;
 358                props.max_brightness = pdata->ledb_max_brt;
 359                label = pdata->ledb_label ? pdata->ledb_label : "lm3630a_ledb";
 360                pchip->bledb =
 361                    devm_backlight_device_register(pchip->dev, label,
 362                                                   pchip->dev, pchip,
 363                                                   &lm3630a_bank_b_ops, &props);
 364                if (IS_ERR(pchip->bledb))
 365                        return PTR_ERR(pchip->bledb);
 366        }
 367        return 0;
 368}
 369
 370static const struct regmap_config lm3630a_regmap = {
 371        .reg_bits = 8,
 372        .val_bits = 8,
 373        .max_register = REG_MAX,
 374};
 375
 376static int lm3630a_parse_led_sources(struct fwnode_handle *node,
 377                                     int default_led_sources)
 378{
 379        u32 sources[LM3630A_NUM_SINKS];
 380        int ret, num_sources, i;
 381
 382        num_sources = fwnode_property_count_u32(node, "led-sources");
 383        if (num_sources < 0)
 384                return default_led_sources;
 385        else if (num_sources > ARRAY_SIZE(sources))
 386                return -EINVAL;
 387
 388        ret = fwnode_property_read_u32_array(node, "led-sources", sources,
 389                                             num_sources);
 390        if (ret)
 391                return ret;
 392
 393        for (i = 0; i < num_sources; i++) {
 394                if (sources[i] != LM3630A_SINK_0 && sources[i] != LM3630A_SINK_1)
 395                        return -EINVAL;
 396
 397                ret |= BIT(sources[i]);
 398        }
 399
 400        return ret;
 401}
 402
 403static int lm3630a_parse_bank(struct lm3630a_platform_data *pdata,
 404                              struct fwnode_handle *node, int *seen_led_sources)
 405{
 406        int led_sources, ret;
 407        const char *label;
 408        u32 bank, val;
 409        bool linear;
 410
 411        ret = fwnode_property_read_u32(node, "reg", &bank);
 412        if (ret)
 413                return ret;
 414
 415        if (bank != LM3630A_BANK_0 && bank != LM3630A_BANK_1)
 416                return -EINVAL;
 417
 418        led_sources = lm3630a_parse_led_sources(node, BIT(bank));
 419        if (led_sources < 0)
 420                return led_sources;
 421
 422        if (*seen_led_sources & led_sources)
 423                return -EINVAL;
 424
 425        *seen_led_sources |= led_sources;
 426
 427        linear = fwnode_property_read_bool(node,
 428                                           "ti,linear-mapping-mode");
 429        if (bank) {
 430                if (led_sources & BIT(LM3630A_SINK_0) ||
 431                    !(led_sources & BIT(LM3630A_SINK_1)))
 432                        return -EINVAL;
 433
 434                pdata->ledb_ctrl = linear ?
 435                        LM3630A_LEDB_ENABLE_LINEAR :
 436                        LM3630A_LEDB_ENABLE;
 437        } else {
 438                if (!(led_sources & BIT(LM3630A_SINK_0)))
 439                        return -EINVAL;
 440
 441                pdata->leda_ctrl = linear ?
 442                        LM3630A_LEDA_ENABLE_LINEAR :
 443                        LM3630A_LEDA_ENABLE;
 444
 445                if (led_sources & BIT(LM3630A_SINK_1))
 446                        pdata->ledb_ctrl = LM3630A_LEDB_ON_A;
 447        }
 448
 449        ret = fwnode_property_read_string(node, "label", &label);
 450        if (!ret) {
 451                if (bank)
 452                        pdata->ledb_label = label;
 453                else
 454                        pdata->leda_label = label;
 455        }
 456
 457        ret = fwnode_property_read_u32(node, "default-brightness",
 458                                       &val);
 459        if (!ret) {
 460                if (bank)
 461                        pdata->ledb_init_brt = val;
 462                else
 463                        pdata->leda_init_brt = val;
 464        }
 465
 466        ret = fwnode_property_read_u32(node, "max-brightness", &val);
 467        if (!ret) {
 468                if (bank)
 469                        pdata->ledb_max_brt = val;
 470                else
 471                        pdata->leda_max_brt = val;
 472        }
 473
 474        return 0;
 475}
 476
 477static int lm3630a_parse_node(struct lm3630a_chip *pchip,
 478                              struct lm3630a_platform_data *pdata)
 479{
 480        int ret = -ENODEV, seen_led_sources = 0;
 481        struct fwnode_handle *node;
 482
 483        device_for_each_child_node(pchip->dev, node) {
 484                ret = lm3630a_parse_bank(pdata, node, &seen_led_sources);
 485                if (ret) {
 486                        fwnode_handle_put(node);
 487                        return ret;
 488                }
 489        }
 490
 491        return ret;
 492}
 493
 494static int lm3630a_probe(struct i2c_client *client,
 495                         const struct i2c_device_id *id)
 496{
 497        struct lm3630a_platform_data *pdata = dev_get_platdata(&client->dev);
 498        struct lm3630a_chip *pchip;
 499        int rval;
 500
 501        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 502                dev_err(&client->dev, "fail : i2c functionality check\n");
 503                return -EOPNOTSUPP;
 504        }
 505
 506        pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630a_chip),
 507                             GFP_KERNEL);
 508        if (!pchip)
 509                return -ENOMEM;
 510        pchip->dev = &client->dev;
 511
 512        pchip->regmap = devm_regmap_init_i2c(client, &lm3630a_regmap);
 513        if (IS_ERR(pchip->regmap)) {
 514                rval = PTR_ERR(pchip->regmap);
 515                dev_err(&client->dev, "fail : allocate reg. map: %d\n", rval);
 516                return rval;
 517        }
 518
 519        i2c_set_clientdata(client, pchip);
 520        if (pdata == NULL) {
 521                pdata = devm_kzalloc(pchip->dev,
 522                                     sizeof(struct lm3630a_platform_data),
 523                                     GFP_KERNEL);
 524                if (pdata == NULL)
 525                        return -ENOMEM;
 526
 527                /* default values */
 528                pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS;
 529                pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS;
 530                pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS;
 531                pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS;
 532
 533                rval = lm3630a_parse_node(pchip, pdata);
 534                if (rval) {
 535                        dev_err(&client->dev, "fail : parse node\n");
 536                        return rval;
 537                }
 538        }
 539        pchip->pdata = pdata;
 540
 541        pchip->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
 542                                                GPIOD_OUT_HIGH);
 543        if (IS_ERR(pchip->enable_gpio)) {
 544                rval = PTR_ERR(pchip->enable_gpio);
 545                return rval;
 546        }
 547
 548        /* chip initialize */
 549        rval = lm3630a_chip_init(pchip);
 550        if (rval < 0) {
 551                dev_err(&client->dev, "fail : init chip\n");
 552                return rval;
 553        }
 554        /* backlight register */
 555        rval = lm3630a_backlight_register(pchip);
 556        if (rval < 0) {
 557                dev_err(&client->dev, "fail : backlight register.\n");
 558                return rval;
 559        }
 560        /* pwm */
 561        if (pdata->pwm_ctrl != LM3630A_PWM_DISABLE) {
 562                pchip->pwmd = devm_pwm_get(pchip->dev, "lm3630a-pwm");
 563                if (IS_ERR(pchip->pwmd)) {
 564                        dev_err(&client->dev, "fail : get pwm device\n");
 565                        return PTR_ERR(pchip->pwmd);
 566                }
 567
 568                pwm_init_state(pchip->pwmd, &pchip->pwmd_state);
 569        }
 570
 571        /* interrupt enable  : irq 0 is not allowed */
 572        pchip->irq = client->irq;
 573        if (pchip->irq) {
 574                rval = lm3630a_intr_config(pchip);
 575                if (rval < 0)
 576                        return rval;
 577        }
 578        dev_info(&client->dev, "LM3630A backlight register OK.\n");
 579        return 0;
 580}
 581
 582static int lm3630a_remove(struct i2c_client *client)
 583{
 584        int rval;
 585        struct lm3630a_chip *pchip = i2c_get_clientdata(client);
 586
 587        rval = lm3630a_write(pchip, REG_BRT_A, 0);
 588        if (rval < 0)
 589                dev_err(pchip->dev, "i2c failed to access register\n");
 590
 591        rval = lm3630a_write(pchip, REG_BRT_B, 0);
 592        if (rval < 0)
 593                dev_err(pchip->dev, "i2c failed to access register\n");
 594
 595        if (pchip->irq) {
 596                free_irq(pchip->irq, pchip);
 597                flush_workqueue(pchip->irqthread);
 598                destroy_workqueue(pchip->irqthread);
 599        }
 600        return 0;
 601}
 602
 603static const struct i2c_device_id lm3630a_id[] = {
 604        {LM3630A_NAME, 0},
 605        {}
 606};
 607
 608MODULE_DEVICE_TABLE(i2c, lm3630a_id);
 609
 610static const struct of_device_id lm3630a_match_table[] = {
 611        { .compatible = "ti,lm3630a", },
 612        { },
 613};
 614
 615MODULE_DEVICE_TABLE(of, lm3630a_match_table);
 616
 617static struct i2c_driver lm3630a_i2c_driver = {
 618        .driver = {
 619                   .name = LM3630A_NAME,
 620                   .of_match_table = lm3630a_match_table,
 621                   },
 622        .probe = lm3630a_probe,
 623        .remove = lm3630a_remove,
 624        .id_table = lm3630a_id,
 625};
 626
 627module_i2c_driver(lm3630a_i2c_driver);
 628
 629MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630A");
 630MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
 631MODULE_AUTHOR("LDD MLP <ldd-mlp@list.ti.com>");
 632MODULE_LICENSE("GPL v2");
 633