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