Blame view

drivers/leds/leds-lp8788.c 3.71 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
eb80411b5   Kim, Milo   leds: add new lp8...
2
3
4
5
6
7
  /*
   * TI LP8788 MFD - keyled driver
   *
   * Copyright 2012 Texas Instruments
   *
   * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
eb80411b5   Kim, Milo   leds: add new lp8...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   */
  
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/platform_device.h>
  #include <linux/leds.h>
  #include <linux/mutex.h>
  #include <linux/mfd/lp8788.h>
  #include <linux/mfd/lp8788-isink.h>
  
  #define MAX_BRIGHTNESS			LP8788_ISINK_MAX_PWM
  #define DEFAULT_LED_NAME		"keyboard-backlight"
  
  struct lp8788_led {
  	struct lp8788 *lp;
  	struct mutex lock;
eb80411b5   Kim, Milo   leds: add new lp8...
25
26
  	struct led_classdev led_dev;
  	enum lp8788_isink_number isink_num;
eb80411b5   Kim, Milo   leds: add new lp8...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  	int on;
  };
  
  struct lp8788_led_config {
  	enum lp8788_isink_scale scale;
  	enum lp8788_isink_number num;
  	int iout;
  };
  
  static struct lp8788_led_config default_led_config = {
  	.scale = LP8788_ISINK_SCALE_100mA,
  	.num   = LP8788_ISINK_3,
  	.iout  = 0,
  };
  
  static int lp8788_led_init_device(struct lp8788_led *led,
  				struct lp8788_led_platform_data *pdata)
  {
  	struct lp8788_led_config *cfg = &default_led_config;
  	u8 addr, mask, val;
  	int ret;
  
  	if (pdata) {
  		cfg->scale = pdata->scale;
  		cfg->num = pdata->num;
  		cfg->iout = pdata->iout_code;
  	}
  
  	led->isink_num = cfg->num;
  
  	/* scale configuration */
  	addr = LP8788_ISINK_CTRL;
  	mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET);
4df7309af   Axel Lin   leds: lp8788: Fix...
60
  	val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET);
eb80411b5   Kim, Milo   leds: add new lp8...
61
62
63
64
65
66
67
68
69
70
71
  	ret = lp8788_update_bits(led->lp, addr, mask, val);
  	if (ret)
  		return ret;
  
  	/* current configuration */
  	addr = lp8788_iout_addr[cfg->num];
  	mask = lp8788_iout_mask[cfg->num];
  	val = cfg->iout;
  
  	return lp8788_update_bits(led->lp, addr, mask, val);
  }
64998371e   Andrew Lunn   leds: lp8788: Rem...
72
  static int lp8788_led_enable(struct lp8788_led *led,
eb80411b5   Kim, Milo   leds: add new lp8...
73
74
  			enum lp8788_isink_number num, int on)
  {
64998371e   Andrew Lunn   leds: lp8788: Rem...
75
  	int ret;
eb80411b5   Kim, Milo   leds: add new lp8...
76
77
  	u8 mask = 1 << num;
  	u8 val = on << num;
64998371e   Andrew Lunn   leds: lp8788: Rem...
78
79
80
  	ret = lp8788_update_bits(led->lp, LP8788_ISINK_CTRL, mask, val);
  	if (ret == 0)
  		led->on = on;
eb80411b5   Kim, Milo   leds: add new lp8...
81

64998371e   Andrew Lunn   leds: lp8788: Rem...
82
  	return ret;
eb80411b5   Kim, Milo   leds: add new lp8...
83
  }
64998371e   Andrew Lunn   leds: lp8788: Rem...
84
85
  static int lp8788_brightness_set(struct led_classdev *led_cdev,
  				enum led_brightness val)
eb80411b5   Kim, Milo   leds: add new lp8...
86
  {
64998371e   Andrew Lunn   leds: lp8788: Rem...
87
88
  	struct lp8788_led *led =
  			container_of(led_cdev, struct lp8788_led, led_dev);
eb80411b5   Kim, Milo   leds: add new lp8...
89
  	enum lp8788_isink_number num = led->isink_num;
64998371e   Andrew Lunn   leds: lp8788: Rem...
90
  	int enable, ret;
eb80411b5   Kim, Milo   leds: add new lp8...
91
92
93
94
95
96
97
  
  	mutex_lock(&led->lock);
  
  	switch (num) {
  	case LP8788_ISINK_1:
  	case LP8788_ISINK_2:
  	case LP8788_ISINK_3:
64998371e   Andrew Lunn   leds: lp8788: Rem...
98
99
100
  		ret = lp8788_write_byte(led->lp, lp8788_pwm_addr[num], val);
  		if (ret < 0)
  			goto unlock;
eb80411b5   Kim, Milo   leds: add new lp8...
101
102
  		break;
  	default:
d45bb1161   Devendra Naga   leds-lp8788: forg...
103
  		mutex_unlock(&led->lock);
64998371e   Andrew Lunn   leds: lp8788: Rem...
104
  		return -EINVAL;
eb80411b5   Kim, Milo   leds: add new lp8...
105
106
107
108
  	}
  
  	enable = (val > 0) ? 1 : 0;
  	if (enable != led->on)
64998371e   Andrew Lunn   leds: lp8788: Rem...
109
110
  		ret = lp8788_led_enable(led, num, enable);
  unlock:
eb80411b5   Kim, Milo   leds: add new lp8...
111
  	mutex_unlock(&led->lock);
64998371e   Andrew Lunn   leds: lp8788: Rem...
112
  	return ret;
eb80411b5   Kim, Milo   leds: add new lp8...
113
  }
98ea1ea20   Bill Pemberton   leds: remove use ...
114
  static int lp8788_led_probe(struct platform_device *pdev)
eb80411b5   Kim, Milo   leds: add new lp8...
115
116
117
118
  {
  	struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
  	struct lp8788_led_platform_data *led_pdata;
  	struct lp8788_led *led;
a1932edf8   Kim, Milo   leds-lp8788: fix ...
119
  	struct device *dev = &pdev->dev;
eb80411b5   Kim, Milo   leds: add new lp8...
120
  	int ret;
a1932edf8   Kim, Milo   leds-lp8788: fix ...
121
  	led = devm_kzalloc(dev, sizeof(struct lp8788_led), GFP_KERNEL);
eb80411b5   Kim, Milo   leds: add new lp8...
122
123
124
125
126
  	if (!led)
  		return -ENOMEM;
  
  	led->lp = lp;
  	led->led_dev.max_brightness = MAX_BRIGHTNESS;
64998371e   Andrew Lunn   leds: lp8788: Rem...
127
  	led->led_dev.brightness_set_blocking = lp8788_brightness_set;
eb80411b5   Kim, Milo   leds: add new lp8...
128
129
130
131
132
133
134
135
136
  
  	led_pdata = lp->pdata ? lp->pdata->led_pdata : NULL;
  
  	if (!led_pdata || !led_pdata->name)
  		led->led_dev.name = DEFAULT_LED_NAME;
  	else
  		led->led_dev.name = led_pdata->name;
  
  	mutex_init(&led->lock);
eb80411b5   Kim, Milo   leds: add new lp8...
137

eb80411b5   Kim, Milo   leds: add new lp8...
138
139
  	ret = lp8788_led_init_device(led, led_pdata);
  	if (ret) {
a1932edf8   Kim, Milo   leds-lp8788: fix ...
140
141
  		dev_err(dev, "led init device err: %d
  ", ret);
eb80411b5   Kim, Milo   leds: add new lp8...
142
143
  		return ret;
  	}
f165a66e1   Amitoj Kaur Chawla   leds: lp8788: Use...
144
  	ret = devm_led_classdev_register(dev, &led->led_dev);
eb80411b5   Kim, Milo   leds: add new lp8...
145
  	if (ret) {
a1932edf8   Kim, Milo   leds-lp8788: fix ...
146
147
  		dev_err(dev, "led register err: %d
  ", ret);
eb80411b5   Kim, Milo   leds: add new lp8...
148
149
150
151
152
  		return ret;
  	}
  
  	return 0;
  }
eb80411b5   Kim, Milo   leds: add new lp8...
153
154
  static struct platform_driver lp8788_led_driver = {
  	.probe = lp8788_led_probe,
eb80411b5   Kim, Milo   leds: add new lp8...
155
156
  	.driver = {
  		.name = LP8788_DEV_KEYLED,
eb80411b5   Kim, Milo   leds: add new lp8...
157
158
159
160
161
162
163
164
  	},
  };
  module_platform_driver(lp8788_led_driver);
  
  MODULE_DESCRIPTION("Texas Instruments LP8788 Keyboard LED Driver");
  MODULE_AUTHOR("Milo Kim");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:lp8788-keyled");