Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

pmic_light.c

Go to the documentation of this file.
/*
 * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @file mc13892/pmic_light.c
 * @brief This is the main file of PMIC(mc13783) Light and Backlight driver.
 *
 * @ingroup PMIC_LIGHT
 */

/*
 * Includes
 */
#define DEBUG
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/pmic_light.h>
#include <linux/pmic_status.h>

#define BIT_CL_MAIN_LSH       9
#define BIT_CL_AUX_LSH        21
#define BIT_CL_KEY_LSH        9
#define BIT_CL_RED_LSH        9
#define BIT_CL_GREEN_LSH      21
#define BIT_CL_BLUE_LSH       9

#define BIT_CL_MAIN_WID       3
#define BIT_CL_AUX_WID        3
#define BIT_CL_KEY_WID        3
#define BIT_CL_RED_WID        3
#define BIT_CL_GREEN_WID      3
#define BIT_CL_BLUE_WID       3

#define BIT_DC_MAIN_LSH       3
#define BIT_DC_AUX_LSH        15
#define BIT_DC_KEY_LSH        3
#define BIT_DC_RED_LSH        3
#define BIT_DC_GREEN_LSH      15
#define BIT_DC_BLUE_LSH       3

#define BIT_DC_MAIN_WID       6
#define BIT_DC_AUX_WID        6
#define BIT_DC_KEY_WID        6
#define BIT_DC_RED_WID        6
#define BIT_DC_GREEN_WID      6
#define BIT_DC_BLUE_WID       6

#define BIT_RP_MAIN_LSH       2
#define BIT_RP_AUX_LSH        14
#define BIT_RP_KEY_LSH        2
#define BIT_RP_RED_LSH        2
#define BIT_RP_GREEN_LSH      14
#define BIT_RP_BLUE_LSH       2

#define BIT_RP_MAIN_WID       1
#define BIT_RP_AUX_WID        1
#define BIT_RP_KEY_WID        1
#define BIT_RP_RED_WID        1
#define BIT_RP_GREEN_WID      1
#define BIT_RP_BLUE_WID       1

#define BIT_HC_MAIN_LSH       1
#define BIT_HC_AUX_LSH        13
#define BIT_HC_KEY_LSH        1

#define BIT_HC_MAIN_WID       1
#define BIT_HC_AUX_WID        1
#define BIT_HC_KEY_WID        1

#define BIT_BP_RED_LSH        0
#define BIT_BP_GREEN_LSH      12
#define BIT_BP_BLUE_LSH       0

#define BIT_BP_RED_WID        2
#define BIT_BP_GREEN_WID      2
#define BIT_BP_BLUE_WID       2

00089 int pmic_light_init_reg(void)
{
      CHECK_ERROR(pmic_write_reg(REG_LED_CTL0, 0, PMIC_ALL_BITS));
      CHECK_ERROR(pmic_write_reg(REG_LED_CTL1, 0, PMIC_ALL_BITS));
      CHECK_ERROR(pmic_write_reg(REG_LED_CTL2, 0, PMIC_ALL_BITS));
      CHECK_ERROR(pmic_write_reg(REG_LED_CTL3, 0, PMIC_ALL_BITS));

      return 0;
}

static int pmic_light_suspend(struct platform_device *dev, pm_message_t state)
{
      return 0;
};

static int pmic_light_resume(struct platform_device *pdev)
{
      return 0;
};

PMIC_STATUS mc13892_bklit_set_hi_current(enum lit_channel channel, int mode)
{
      unsigned int mask;
      unsigned int value;
      int reg;

      switch (channel) {
      case LIT_MAIN:
            value = BITFVAL(BIT_HC_MAIN, mode);
            mask = BITFMASK(BIT_HC_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            value = BITFVAL(BIT_HC_AUX, mode);
            mask = BITFMASK(BIT_HC_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            value = BITFVAL(BIT_HC_KEY, mode);
            mask = BITFMASK(BIT_HC_KEY);
            reg = REG_LED_CTL1;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }
      CHECK_ERROR(pmic_write_reg(reg, value, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_get_hi_current(enum lit_channel channel, int *mode)
{
      unsigned int mask;
      int reg;

      switch (channel) {
      case LIT_MAIN:
            mask = BITFMASK(BIT_HC_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            mask = BITFMASK(BIT_HC_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            mask = BITFMASK(BIT_HC_KEY);
            reg = REG_LED_CTL1;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }

      CHECK_ERROR(pmic_read_reg(reg, mode, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_set_current(enum lit_channel channel,
                              unsigned char level)
{
      unsigned int mask;
      unsigned int value;
      int reg;

      if (level > LIT_CURR_HI_42)
            return PMIC_PARAMETER_ERROR;
      else if (level >= LIT_CURR_HI_0) {
            CHECK_ERROR(mc13892_bklit_set_hi_current(channel, 1));
            level -= LIT_CURR_HI_0;
      }

      switch (channel) {
      case LIT_MAIN:
            value = BITFVAL(BIT_CL_MAIN, level);
            mask = BITFMASK(BIT_CL_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            value = BITFVAL(BIT_CL_AUX, level);
            mask = BITFMASK(BIT_CL_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            value = BITFVAL(BIT_CL_KEY, level);
            mask = BITFMASK(BIT_CL_KEY);
            reg = REG_LED_CTL1;
            break;
      case LIT_RED:
            value = BITFVAL(BIT_CL_RED, level);
            mask = BITFMASK(BIT_CL_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            value = BITFVAL(BIT_CL_GREEN, level);
            mask = BITFMASK(BIT_CL_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            value = BITFVAL(BIT_CL_BLUE, level);
            mask = BITFMASK(BIT_CL_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }
      CHECK_ERROR(pmic_write_reg(reg, value, mask));

      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_get_current(enum lit_channel channel,
                              unsigned char *level)
{
      unsigned int reg_value = 0;
      unsigned int mask = 0;
      int reg, mode;

      CHECK_ERROR(mc13892_bklit_get_hi_current(channel, &mode));

      switch (channel) {
      case LIT_MAIN:
            mask = BITFMASK(BIT_CL_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            mask = BITFMASK(BIT_CL_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            mask = BITFMASK(BIT_CL_KEY);
            reg = REG_LED_CTL1;
            break;
      case LIT_RED:
            mask = BITFMASK(BIT_CL_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            mask = BITFMASK(BIT_CL_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            mask = BITFMASK(BIT_CL_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }

      CHECK_ERROR(pmic_read_reg(reg, &reg_value, mask));

      switch (channel) {
      case LIT_MAIN:
            *level = BITFEXT(reg_value, BIT_CL_MAIN);
            break;
      case LIT_AUX:
            *level = BITFEXT(reg_value, BIT_CL_AUX);
            break;
      case LIT_KEY:
            *level = BITFEXT(reg_value, BIT_CL_KEY);
            break;
      case LIT_RED:
            *level = BITFEXT(reg_value, BIT_CL_RED);
            break;
      case LIT_GREEN:
            *level = BITFEXT(reg_value, BIT_CL_GREEN);
            break;
      case LIT_BLUE:
            *level = BITFEXT(reg_value, BIT_CL_BLUE);
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }

      if (mode == 1)
            *level += LIT_CURR_HI_0;

      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_set_dutycycle(enum lit_channel channel,
                              unsigned char dc)
{
      unsigned int mask;
      unsigned int value;
      int reg;

      switch (channel) {
      case LIT_MAIN:
            value = BITFVAL(BIT_DC_MAIN, dc);
            mask = BITFMASK(BIT_DC_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            value = BITFVAL(BIT_DC_AUX, dc);
            mask = BITFMASK(BIT_DC_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            value = BITFVAL(BIT_DC_KEY, dc);
            mask = BITFMASK(BIT_DC_KEY);
            reg = REG_LED_CTL1;
            break;
      case LIT_RED:
            value = BITFVAL(BIT_DC_RED, dc);
            mask = BITFMASK(BIT_DC_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            value = BITFVAL(BIT_DC_GREEN, dc);
            mask = BITFMASK(BIT_DC_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            value = BITFVAL(BIT_DC_BLUE, dc);
            mask = BITFMASK(BIT_DC_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }
      CHECK_ERROR(pmic_write_reg(reg, value, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_get_dutycycle(enum lit_channel channel,
                              unsigned char *dc)
{
      unsigned int mask;
      int reg;
      unsigned int reg_value = 0;

      switch (channel) {
      case LIT_MAIN:
            mask = BITFMASK(BIT_DC_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            mask = BITFMASK(BIT_DC_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            mask = BITFMASK(BIT_DC_KEY);
            reg = REG_LED_CTL1;
            break;
      case LIT_RED:
            mask = BITFMASK(BIT_DC_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            mask = BITFMASK(BIT_DC_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            mask = BITFMASK(BIT_DC_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }

      CHECK_ERROR(pmic_read_reg(reg, &reg_value, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_set_ramp(enum lit_channel channel, int flag)
{
      unsigned int mask;
      unsigned int value;
      int reg;

      switch (channel) {
      case LIT_MAIN:
            value = BITFVAL(BIT_RP_MAIN, flag);
            mask = BITFMASK(BIT_RP_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            value = BITFVAL(BIT_RP_AUX, flag);
            mask = BITFMASK(BIT_RP_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            value = BITFVAL(BIT_RP_KEY, flag);
            mask = BITFMASK(BIT_RP_KEY);
            reg = REG_LED_CTL1;
            break;
      case LIT_RED:
            value = BITFVAL(BIT_RP_RED, flag);
            mask = BITFMASK(BIT_RP_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            value = BITFVAL(BIT_RP_GREEN, flag);
            mask = BITFMASK(BIT_RP_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            value = BITFVAL(BIT_RP_BLUE, flag);
            mask = BITFMASK(BIT_RP_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }
      CHECK_ERROR(pmic_write_reg(reg, value, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_get_ramp(enum lit_channel channel, int *flag)
{
      unsigned int mask;
      int reg;

      switch (channel) {
      case LIT_MAIN:
            mask = BITFMASK(BIT_RP_MAIN);
            reg = REG_LED_CTL0;
            break;
      case LIT_AUX:
            mask = BITFMASK(BIT_RP_AUX);
            reg = REG_LED_CTL0;
            break;
      case LIT_KEY:
            mask = BITFMASK(BIT_RP_KEY);
            reg = REG_LED_CTL1;
            break;
      case LIT_RED:
            mask = BITFMASK(BIT_RP_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            mask = BITFMASK(BIT_RP_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            mask = BITFMASK(BIT_RP_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }

      CHECK_ERROR(pmic_read_reg(reg, flag, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_set_blink_p(enum lit_channel channel, int period)
{
      unsigned int mask;
      unsigned int value;
      int reg;

      switch (channel) {
      case LIT_RED:
            value = BITFVAL(BIT_BP_RED, period);
            mask = BITFMASK(BIT_BP_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            value = BITFVAL(BIT_BP_GREEN, period);
            mask = BITFMASK(BIT_BP_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            value = BITFVAL(BIT_BP_BLUE, period);
            mask = BITFMASK(BIT_BP_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }
      CHECK_ERROR(pmic_write_reg(reg, value, mask));
      return PMIC_SUCCESS;
}

PMIC_STATUS mc13892_bklit_get_blink_p(enum lit_channel channel, int *period)
{
      unsigned int mask;
      int reg;

      switch (channel) {
      case LIT_RED:
            mask = BITFMASK(BIT_BP_RED);
            reg = REG_LED_CTL2;
            break;
      case LIT_GREEN:
            mask = BITFMASK(BIT_BP_GREEN);
            reg = REG_LED_CTL2;
            break;
      case LIT_BLUE:
            mask = BITFMASK(BIT_BP_BLUE);
            reg = REG_LED_CTL3;
            break;
      default:
            return PMIC_PARAMETER_ERROR;
      }

      CHECK_ERROR(pmic_read_reg(reg, period, mask));
      return PMIC_SUCCESS;
}

EXPORT_SYMBOL(mc13892_bklit_set_current);
EXPORT_SYMBOL(mc13892_bklit_get_current);
EXPORT_SYMBOL(mc13892_bklit_set_dutycycle);
EXPORT_SYMBOL(mc13892_bklit_get_dutycycle);
EXPORT_SYMBOL(mc13892_bklit_set_ramp);
EXPORT_SYMBOL(mc13892_bklit_get_ramp);
EXPORT_SYMBOL(mc13892_bklit_set_blink_p);
EXPORT_SYMBOL(mc13892_bklit_get_blink_p);

static int pmic_light_remove(struct platform_device *pdev)
{
      return 0;
}

#ifdef DEBUG
static ssize_t lit_info(struct device *dev, struct device_attribute *attr,
                  char *buf)
{
      return 0;
}

enum {
      SET_CURR = 0,
      SET_DC,
      SET_RAMP,
      SET_BP,
      SET_CH,
      LIT_CMD_MAX
};

static const char *const lit_cmd[LIT_CMD_MAX] = {
      [SET_CURR] = "cur",
      [SET_DC] = "dc",
      [SET_RAMP] = "ra",
      [SET_BP] = "bp",
      [SET_CH] = "ch"
};

static int cmd(unsigned int index, int value)
{
      static int ch = LIT_MAIN;
      int ret = 0;

      switch (index) {
      case SET_CH:
            ch = value;
            break;
      case SET_CURR:
            pr_debug("set %d cur %d\n", ch, value);
            ret = mc13892_bklit_set_current(ch, value);
            break;
      case SET_DC:
            pr_debug("set %d dc %d\n", ch, value);
            ret = mc13892_bklit_set_dutycycle(ch, value);
            break;
      case SET_RAMP:
            pr_debug("set %d ramp %d\n", ch, value);
            ret = mc13892_bklit_set_ramp(ch, value);
            break;
      case SET_BP:
            pr_debug("set %d bp %d\n", ch, value);
            ret = mc13892_bklit_set_blink_p(ch, value);
            break;
      default:
            pr_debug("error command\n");
            break;
      }

      if (ret == PMIC_SUCCESS)
            pr_debug("command exec successfully!\n");

      return 0;
}

static ssize_t lit_ctl(struct device *dev, struct device_attribute *attr,
                   const char *buf, size_t count)
{
      int state = 0;
      const char *const *s;
      char *p, *q;
      int error;
      int len, value = 0;

      pr_debug("lit_ctl\n");

      q = NULL;
      q = memchr(buf, ' ', count);

      if (q != NULL) {
            len = q - buf;
            q += 1;
            value = simple_strtoul(q, NULL, 10);
      } else {
            p = memchr(buf, '\n', count);
            len = p ? p - buf : count;
      }

      for (s = &lit_cmd[state]; state < LIT_CMD_MAX; s++, state++) {
            if (*s && !strncmp(buf, *s, len))
                  break;
      }
      if (state < LIT_CMD_MAX && *s)
            error = cmd(state, value);
      else
            error = -EINVAL;

      return count;
}

#else
static ssize_t lit_info(struct device *dev, struct device_attribute *attr,
                  char *buf)
{
      return 0;
}

static ssize_t lit_ctl(struct device *dev, struct device_attribute *attr,
                   const char *buf, size_t count)
{
      return count;
}

#endif

static DEVICE_ATTR(lit, 0644, lit_info, lit_ctl);

static int pmic_light_probe(struct platform_device *pdev)
{
      int ret = 0;

      pr_debug("PMIC ADC start probe\n");
      ret = device_create_file(&(pdev->dev), &dev_attr_lit);
      if (ret) {
            pr_debug("Can't create device file!\n");
            return -ENODEV;
      }

      pmic_light_init_reg();

      pr_debug("PMIC Light successfully loaded\n");
      return 0;
}

static struct platform_driver pmic_light_driver_ldm = {
      .driver = {
               .name = "pmic_light",
               },
      .suspend = pmic_light_suspend,
      .resume = pmic_light_resume,
      .probe = pmic_light_probe,
      .remove = pmic_light_remove,
};

/*
 * Initialization and Exit
 */

static int __init pmic_light_init(void)
{
      pr_debug("PMIC Light driver loading...\n");
      return platform_driver_register(&pmic_light_driver_ldm);
}
static void __exit pmic_light_exit(void)
{
      platform_driver_unregister(&pmic_light_driver_ldm);
      pr_debug("PMIC Light driver successfully unloaded\n");
}

/*
 * Module entry points
 */

subsys_initcall(pmic_light_init);
module_exit(pmic_light_exit);

MODULE_DESCRIPTION("PMIC_LIGHT");
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_LICENSE("GPL");

Generated by  Doxygen 1.6.0   Back to index