Merge branch 'akpm' (Andrew's patch-bomb)
Merge patches through Andrew Morton: "180 patches - err 181 - listed below: - most of MM. I held back the (large) "memcg: add hugetlb extension" series because a bunfight has recently broken out. - leds. After this, Bryan Wu will be handling drivers/leds/ - backlight - lib/ - rtc" * emailed from Andrew Morton <akpm@linux-foundation.org>: (181 patches) drivers/rtc/rtc-s3c.c: fix compiler warning drivers/rtc/rtc-tegra.c: clean up probe/remove routines drivers/rtc/rtc-pl031.c: remove RTC timer interrupt handling drivers/rtc/rtc-lpc32xx.c: add device tree support drivers/rtc/rtc-m41t93.c: don't let get_time() reset M41T93_FLAG_OF rtc: ds1307: add trickle charger support rtc: ds1307: remove superfluous initialization rtc: rename CONFIG_RTC_MXC to CONFIG_RTC_DRV_MXC drivers/rtc/Kconfig: place RTC_DRV_IMXDI and RTC_MXC under "on-CPU RTC drivers" drivers/rtc/rtc-pcf8563.c: add RTC_VL_READ/RTC_VL_CLR ioctl feature rtc: add ioctl to get/clear battery low voltage status drivers/rtc/rtc-ep93xx.c: convert to use module_platform_driver() rtc/spear: add Device Tree probing capability lib/vsprintf.c: "%#o",0 becomes '0' instead of '00' radix-tree: fix preload vector size spinlock_debug: print kallsyms name for lock vsprintf: fix %ps on non symbols when using kallsyms lib/bitmap.c: fix documentation for scnprintf() functions lib/string_helpers.c: make arrays static lib/test-kstrtox.c: mark const init data with __initconst instead of __initdata ...
This commit is contained in:
commit
7d36014b97
|
@ -0,0 +1,48 @@
|
|||
What: /sys/class/backlight/<backlight>/als_channel
|
||||
Date: May 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Get the ALS output channel used as input in
|
||||
ALS-current-control mode (0, 1), where
|
||||
|
||||
0 - out_current0 (backlight 0)
|
||||
1 - out_current1 (backlight 1)
|
||||
|
||||
What: /sys/class/backlight/<backlight>/als_en
|
||||
Date: May 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Enable ALS-current-control mode (0, 1).
|
||||
|
||||
What: /sys/class/backlight/<backlight>/id
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Get the id of this backlight (0, 1).
|
||||
|
||||
What: /sys/class/backlight/<backlight>/linear
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Set the brightness-mapping mode (0, 1), where
|
||||
|
||||
0 - exponential mode
|
||||
1 - linear mode
|
||||
|
||||
What: /sys/class/backlight/<backlight>/pwm
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Set the PWM-input control mask (5 bits), where
|
||||
|
||||
bit 5 - PWM-input enabled in Zone 4
|
||||
bit 4 - PWM-input enabled in Zone 3
|
||||
bit 3 - PWM-input enabled in Zone 2
|
||||
bit 2 - PWM-input enabled in Zone 1
|
||||
bit 1 - PWM-input enabled in Zone 0
|
||||
bit 0 - PWM-input enabled
|
|
@ -0,0 +1,65 @@
|
|||
What: /sys/class/leds/<led>/als_channel
|
||||
Date: May 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Set the ALS output channel to use as input in
|
||||
ALS-current-control mode (1, 2), where
|
||||
|
||||
1 - out_current1
|
||||
2 - out_current2
|
||||
|
||||
What: /sys/class/leds/<led>/als_en
|
||||
Date: May 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Enable ALS-current-control mode (0, 1).
|
||||
|
||||
What: /sys/class/leds/<led>/falltime
|
||||
What: /sys/class/leds/<led>/risetime
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Set the pattern generator fall and rise times (0..7), where
|
||||
|
||||
0 - 2048 us
|
||||
1 - 262 ms
|
||||
2 - 524 ms
|
||||
3 - 1.049 s
|
||||
4 - 2.097 s
|
||||
5 - 4.194 s
|
||||
6 - 8.389 s
|
||||
7 - 16.78 s
|
||||
|
||||
What: /sys/class/leds/<led>/id
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Get the id of this led (0..3).
|
||||
|
||||
What: /sys/class/leds/<led>/linear
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Set the brightness-mapping mode (0, 1), where
|
||||
|
||||
0 - exponential mode
|
||||
1 - linear mode
|
||||
|
||||
What: /sys/class/leds/<led>/pwm
|
||||
Date: April 2012
|
||||
KernelVersion: 3.5
|
||||
Contact: Johan Hovold <jhovold@gmail.com>
|
||||
Description:
|
||||
Set the PWM-input control mask (5 bits), where
|
||||
|
||||
bit 5 - PWM-input enabled in Zone 4
|
||||
bit 4 - PWM-input enabled in Zone 3
|
||||
bit 3 - PWM-input enabled in Zone 2
|
||||
bit 2 - PWM-input enabled in Zone 1
|
||||
bit 1 - PWM-input enabled in Zone 0
|
||||
bit 0 - PWM-input enabled
|
|
@ -184,12 +184,14 @@ behind this approach is that a cgroup that aggressively uses a shared
|
|||
page will eventually get charged for it (once it is uncharged from
|
||||
the cgroup that brought it in -- this will happen on memory pressure).
|
||||
|
||||
But see section 8.2: when moving a task to another cgroup, its pages may
|
||||
be recharged to the new cgroup, if move_charge_at_immigrate has been chosen.
|
||||
|
||||
Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used.
|
||||
When you do swapoff and make swapped-out pages of shmem(tmpfs) to
|
||||
be backed into memory in force, charges for pages are accounted against the
|
||||
caller of swapoff rather than the users of shmem.
|
||||
|
||||
|
||||
2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP)
|
||||
|
||||
Swap Extension allows you to record charge for swap. A swapped-in page is
|
||||
|
@ -374,14 +376,15 @@ cgroup might have some charge associated with it, even though all
|
|||
tasks have migrated away from it. (because we charge against pages, not
|
||||
against tasks.)
|
||||
|
||||
Such charges are freed or moved to their parent. At moving, both of RSS
|
||||
and CACHES are moved to parent.
|
||||
rmdir() may return -EBUSY if freeing/moving fails. See 5.1 also.
|
||||
We move the stats to root (if use_hierarchy==0) or parent (if
|
||||
use_hierarchy==1), and no change on the charge except uncharging
|
||||
from the child.
|
||||
|
||||
Charges recorded in swap information is not updated at removal of cgroup.
|
||||
Recorded information is discarded and a cgroup which uses swap (swapcache)
|
||||
will be charged as a new owner of it.
|
||||
|
||||
About use_hierarchy, see Section 6.
|
||||
|
||||
5. Misc. interfaces.
|
||||
|
||||
|
@ -394,13 +397,15 @@ will be charged as a new owner of it.
|
|||
|
||||
Almost all pages tracked by this memory cgroup will be unmapped and freed.
|
||||
Some pages cannot be freed because they are locked or in-use. Such pages are
|
||||
moved to parent and this cgroup will be empty. This may return -EBUSY if
|
||||
VM is too busy to free/move all pages immediately.
|
||||
moved to parent(if use_hierarchy==1) or root (if use_hierarchy==0) and this
|
||||
cgroup will be empty.
|
||||
|
||||
Typical use case of this interface is that calling this before rmdir().
|
||||
Because rmdir() moves all pages to parent, some out-of-use page caches can be
|
||||
moved to the parent. If you want to avoid that, force_empty will be useful.
|
||||
|
||||
About use_hierarchy, see Section 6.
|
||||
|
||||
5.2 stat file
|
||||
|
||||
memory.stat file includes following statistics
|
||||
|
@ -430,17 +435,10 @@ hierarchical_memory_limit - # of bytes of memory limit with regard to hierarchy
|
|||
hierarchical_memsw_limit - # of bytes of memory+swap limit with regard to
|
||||
hierarchy under which memory cgroup is.
|
||||
|
||||
total_cache - sum of all children's "cache"
|
||||
total_rss - sum of all children's "rss"
|
||||
total_mapped_file - sum of all children's "cache"
|
||||
total_pgpgin - sum of all children's "pgpgin"
|
||||
total_pgpgout - sum of all children's "pgpgout"
|
||||
total_swap - sum of all children's "swap"
|
||||
total_inactive_anon - sum of all children's "inactive_anon"
|
||||
total_active_anon - sum of all children's "active_anon"
|
||||
total_inactive_file - sum of all children's "inactive_file"
|
||||
total_active_file - sum of all children's "active_file"
|
||||
total_unevictable - sum of all children's "unevictable"
|
||||
total_<counter> - # hierarchical version of <counter>, which in
|
||||
addition to the cgroup's own value includes the
|
||||
sum of all hierarchical children's values of
|
||||
<counter>, i.e. total_cache
|
||||
|
||||
# The following additional stats are dependent on CONFIG_DEBUG_VM.
|
||||
|
||||
|
@ -622,8 +620,7 @@ memory cgroup.
|
|||
bit | what type of charges would be moved ?
|
||||
-----+------------------------------------------------------------------------
|
||||
0 | A charge of an anonymous page(or swap of it) used by the target task.
|
||||
| Those pages and swaps must be used only by the target task. You must
|
||||
| enable Swap Extension(see 2.4) to enable move of swap charges.
|
||||
| You must enable Swap Extension(see 2.4) to enable move of swap charges.
|
||||
-----+------------------------------------------------------------------------
|
||||
1 | A charge of file pages(normal file, tmpfs file(e.g. ipc shared memory)
|
||||
| and swaps of tmpfs file) mmapped by the target task. Unlike the case of
|
||||
|
@ -636,8 +633,6 @@ memory cgroup.
|
|||
|
||||
8.3 TODO
|
||||
|
||||
- Implement madvise(2) to let users decide the vma to be moved or not to be
|
||||
moved.
|
||||
- All of moving charge operations are done under cgroup_mutex. It's not good
|
||||
behavior to hold the mutex too long, so we may need some trick.
|
||||
|
||||
|
|
|
@ -92,6 +92,14 @@ to work with it.
|
|||
|
||||
The _locked routines imply that the res_counter->lock is taken.
|
||||
|
||||
f. void res_counter_uncharge_until
|
||||
(struct res_counter *rc, struct res_counter *top,
|
||||
unsinged long val)
|
||||
|
||||
Almost same as res_cunter_uncharge() but propagation of uncharge
|
||||
stops when rc == top. This is useful when kill a res_coutner in
|
||||
child cgroup.
|
||||
|
||||
2.1 Other accounting routines
|
||||
|
||||
There are more routines that may help you with common needs, like
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
* NXP LPC32xx SoC Real Time Clock controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "nxp,lpc3220-rtc"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: The RTC interrupt
|
||||
|
||||
Example:
|
||||
|
||||
rtc@40024000 {
|
||||
compatible = "nxp,lpc3220-rtc";
|
||||
reg = <0x40024000 0x1000>;
|
||||
interrupts = <52 0>;
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
* SPEAr RTC
|
||||
|
||||
Required properties:
|
||||
- compatible : "st,spear600-rtc"
|
||||
- reg : Address range of the rtc registers
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- interrupt: Should contain the rtc interrupt number
|
||||
|
||||
Example:
|
||||
|
||||
rtc@fc000000 {
|
||||
compatible = "st,spear600-rtc";
|
||||
reg = <0xfc000000 0x1000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <12>;
|
||||
};
|
|
@ -60,7 +60,6 @@ ata *);
|
|||
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
void (*truncate_range)(struct inode *, loff_t, loff_t);
|
||||
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
|
||||
|
||||
locking rules:
|
||||
|
@ -87,7 +86,6 @@ setxattr: yes
|
|||
getxattr: no
|
||||
listxattr: no
|
||||
removexattr: yes
|
||||
truncate_range: yes
|
||||
fiemap: no
|
||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||
victim.
|
||||
|
|
|
@ -743,6 +743,7 @@ Committed_AS: 100056 kB
|
|||
VmallocTotal: 112216 kB
|
||||
VmallocUsed: 428 kB
|
||||
VmallocChunk: 111088 kB
|
||||
AnonHugePages: 49152 kB
|
||||
|
||||
MemTotal: Total usable ram (i.e. physical ram minus a few reserved
|
||||
bits and the kernel binary code)
|
||||
|
@ -776,6 +777,7 @@ VmallocChunk: 111088 kB
|
|||
Dirty: Memory which is waiting to get written back to the disk
|
||||
Writeback: Memory which is actively being written back to the disk
|
||||
AnonPages: Non-file backed pages mapped into userspace page tables
|
||||
AnonHugePages: Non-file backed huge pages mapped into userspace page tables
|
||||
Mapped: files which have been mmaped, such as libraries
|
||||
Slab: in-kernel data structures cache
|
||||
SReclaimable: Part of Slab, that might be reclaimed, such as caches
|
||||
|
|
|
@ -363,7 +363,6 @@ struct inode_operations {
|
|||
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
void (*truncate_range)(struct inode *, loff_t, loff_t);
|
||||
};
|
||||
|
||||
Again, all methods are called without any locks being held, unless
|
||||
|
@ -472,9 +471,6 @@ otherwise noted.
|
|||
removexattr: called by the VFS to remove an extended attribute from
|
||||
a file. This method is called by removexattr(2) system call.
|
||||
|
||||
truncate_range: a method provided by the underlying filesystem to truncate a
|
||||
range of blocks , i.e. punch a hole somewhere in a file.
|
||||
|
||||
|
||||
The Address Space Object
|
||||
========================
|
||||
|
@ -760,7 +756,7 @@ struct file_operations
|
|||
----------------------
|
||||
|
||||
This describes how the VFS can manipulate an open file. As of kernel
|
||||
2.6.22, the following members are defined:
|
||||
3.5, the following members are defined:
|
||||
|
||||
struct file_operations {
|
||||
struct module *owner;
|
||||
|
@ -790,6 +786,8 @@ struct file_operations {
|
|||
int (*flock) (struct file *, int, struct file_lock *);
|
||||
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
|
||||
ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
|
||||
int (*setlease)(struct file *, long arg, struct file_lock **);
|
||||
long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len);
|
||||
};
|
||||
|
||||
Again, all methods are called without any locks being held, unless
|
||||
|
@ -858,6 +856,11 @@ otherwise noted.
|
|||
splice_read: called by the VFS to splice data from file to a pipe. This
|
||||
method is used by the splice(2) system call
|
||||
|
||||
setlease: called by the VFS to set or release a file lock lease.
|
||||
setlease has the file_lock_lock held and must not sleep.
|
||||
|
||||
fallocate: called by the VFS to preallocate blocks or punch a hole.
|
||||
|
||||
Note that the file operations are implemented by the specific
|
||||
filesystem in which the inode resides. When opening a device node
|
||||
(character or block special) most filesystems will call special
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
LED Transient Trigger
|
||||
=====================
|
||||
|
||||
The leds timer trigger does not currently have an interface to activate
|
||||
a one shot timer. The current support allows for setting two timers, one for
|
||||
specifying how long a state to be on, and the second for how long the state
|
||||
to be off. The delay_on value specifies the time period an LED should stay
|
||||
in on state, followed by a delay_off value that specifies how long the LED
|
||||
should stay in off state. The on and off cycle repeats until the trigger
|
||||
gets deactivated. There is no provision for one time activation to implement
|
||||
features that require an on or off state to be held just once and then stay in
|
||||
the original state forever.
|
||||
|
||||
Without one shot timer interface, user space can still use timer trigger to
|
||||
set a timer to hold a state, however when user space application crashes or
|
||||
goes away without deactivating the timer, the hardware will be left in that
|
||||
state permanently.
|
||||
|
||||
As a specific example of this use-case, let's look at vibrate feature on
|
||||
phones. Vibrate function on phones is implemented using PWM pins on SoC or
|
||||
PMIC. There is a need to activate one shot timer to control the vibrate
|
||||
feature, to prevent user space crashes leaving the phone in vibrate mode
|
||||
permanently causing the battery to drain.
|
||||
|
||||
Transient trigger addresses the need for one shot timer activation. The
|
||||
transient trigger can be enabled and disabled just like the other leds
|
||||
triggers.
|
||||
|
||||
When an led class device driver registers itself, it can specify all leds
|
||||
triggers it supports and a default trigger. During registration, activation
|
||||
routine for the default trigger gets called. During registration of an led
|
||||
class device, the LED state does not change.
|
||||
|
||||
When the driver unregisters, deactivation routine for the currently active
|
||||
trigger will be called, and LED state is changed to LED_OFF.
|
||||
|
||||
Driver suspend changes the LED state to LED_OFF and resume doesn't change
|
||||
the state. Please note that there is no explicit interaction between the
|
||||
suspend and resume actions and the currently enabled trigger. LED state
|
||||
changes are suspended while the driver is in suspend state. Any timers
|
||||
that are active at the time driver gets suspended, continue to run, without
|
||||
being able to actually change the LED state. Once driver is resumed, triggers
|
||||
start functioning again.
|
||||
|
||||
LED state changes are controlled using brightness which is a common led
|
||||
class device property. When brightness is set to 0 from user space via
|
||||
echo 0 > brightness, it will result in deactivating the current trigger.
|
||||
|
||||
Transient trigger uses standard register and unregister interfaces. During
|
||||
trigger registration, for each led class device that specifies this trigger
|
||||
as its default trigger, trigger activation routine will get called. During
|
||||
registration, the LED state does not change, unless there is another trigger
|
||||
active, in which case LED state changes to LED_OFF.
|
||||
|
||||
During trigger unregistration, LED state gets changed to LED_OFF.
|
||||
|
||||
Transient trigger activation routine doesn't change the LED state. It
|
||||
creates its properties and does its initialization. Transient trigger
|
||||
deactivation routine, will cancel any timer that is active before it cleans
|
||||
up and removes the properties it created. It will restore the LED state to
|
||||
non-transient state. When driver gets suspended, irrespective of the transient
|
||||
state, the LED state changes to LED_OFF.
|
||||
|
||||
Transient trigger can be enabled and disabled from user space on led class
|
||||
devices, that support this trigger as shown below:
|
||||
|
||||
echo transient > trigger
|
||||
echo none > trigger
|
||||
|
||||
NOTE: Add a new property trigger state to control the state.
|
||||
|
||||
This trigger exports three properties, activate, state, and duration. When
|
||||
transient trigger is activated these properties are set to default values.
|
||||
|
||||
- duration allows setting timer value in msecs. The initial value is 0.
|
||||
- activate allows activating and deactivating the timer specified by
|
||||
duration as needed. The initial and default value is 0. This will allow
|
||||
duration to be set after trigger activation.
|
||||
- state allows user to specify a transient state to be held for the specified
|
||||
duration.
|
||||
|
||||
activate - one shot timer activate mechanism.
|
||||
1 when activated, 0 when deactivated.
|
||||
default value is zero when transient trigger is enabled,
|
||||
to allow duration to be set.
|
||||
|
||||
activate state indicates a timer with a value of specified
|
||||
duration running.
|
||||
deactivated state indicates that there is no active timer
|
||||
running.
|
||||
|
||||
duration - one shot timer value. When activate is set, duration value
|
||||
is used to start a timer that runs once. This value doesn't
|
||||
get changed by the trigger unless user does a set via
|
||||
echo new_value > duration
|
||||
|
||||
state - transient state to be held. It has two values 0 or 1. 0 maps
|
||||
to LED_OFF and 1 maps to LED_FULL. The specified state is
|
||||
held for the duration of the one shot timer and then the
|
||||
state gets changed to the non-transient state which is the
|
||||
inverse of transient state.
|
||||
If state = LED_FULL, when the timer runs out the state will
|
||||
go back to LED_OFF.
|
||||
If state = LED_OFF, when the timer runs out the state will
|
||||
go back to LED_FULL.
|
||||
Please note that current LED state is not checked prior to
|
||||
changing the state to the specified state.
|
||||
Driver could map these values to inverted depending on the
|
||||
default states it defines for the LED in its brightness_set()
|
||||
interface which is called from the led brightness_set()
|
||||
interfaces to control the LED state.
|
||||
|
||||
When timer expires activate goes back to deactivated state, duration is left
|
||||
at the set value to be used when activate is set at a future time. This will
|
||||
allow user app to set the time once and activate it to run it once for the
|
||||
specified value as needed. When timer expires, state is restored to the
|
||||
non-transient state which is the inverse of the transient state.
|
||||
|
||||
echo 1 > activate - starts timer = duration when duration is not 0.
|
||||
echo 0 > activate - cancels currently running timer.
|
||||
echo n > duration - stores timer value to be used upon next
|
||||
activate. Currently active timer if
|
||||
any, continues to run for the specified time.
|
||||
echo 0 > duration - stores timer value to be used upon next
|
||||
activate. Currently active timer if any,
|
||||
continues to run for the specified time.
|
||||
echo 1 > state - stores desired transient state LED_FULL to be
|
||||
held for the specified duration.
|
||||
echo 0 > state - stores desired transient state LED_OFF to be
|
||||
held for the specified duration.
|
||||
|
||||
What is not supported:
|
||||
======================
|
||||
- Timer activation is one shot and extending and/or shortening the timer
|
||||
is not supported.
|
||||
|
||||
Example use-case 1:
|
||||
echo transient > trigger
|
||||
echo n > duration
|
||||
echo 1 > state
|
||||
repeat the following step as needed:
|
||||
echo 1 > activate - start timer = duration to run once
|
||||
echo 1 > activate - start timer = duration to run once
|
||||
echo none > trigger
|
||||
|
||||
This trigger is intended to be used for for the following example use cases:
|
||||
- Control of vibrate (phones, tablets etc.) hardware by user space app.
|
||||
- Use of LED by user space app as activity indicator.
|
||||
- Use of LED by user space app as a kind of watchdog indicator -- as
|
||||
long as the app is alive, it can keep the LED illuminated, if it dies
|
||||
the LED will be extinguished automatically.
|
||||
- Use by any user space app that needs a transient GPIO output.
|
|
@ -166,6 +166,68 @@ behavior. So to make them effective you need to restart any
|
|||
application that could have been using hugepages. This also applies to
|
||||
the regions registered in khugepaged.
|
||||
|
||||
== Monitoring usage ==
|
||||
|
||||
The number of transparent huge pages currently used by the system is
|
||||
available by reading the AnonHugePages field in /proc/meminfo. To
|
||||
identify what applications are using transparent huge pages, it is
|
||||
necessary to read /proc/PID/smaps and count the AnonHugePages fields
|
||||
for each mapping. Note that reading the smaps file is expensive and
|
||||
reading it frequently will incur overhead.
|
||||
|
||||
There are a number of counters in /proc/vmstat that may be used to
|
||||
monitor how successfully the system is providing huge pages for use.
|
||||
|
||||
thp_fault_alloc is incremented every time a huge page is successfully
|
||||
allocated to handle a page fault. This applies to both the
|
||||
first time a page is faulted and for COW faults.
|
||||
|
||||
thp_collapse_alloc is incremented by khugepaged when it has found
|
||||
a range of pages to collapse into one huge page and has
|
||||
successfully allocated a new huge page to store the data.
|
||||
|
||||
thp_fault_fallback is incremented if a page fault fails to allocate
|
||||
a huge page and instead falls back to using small pages.
|
||||
|
||||
thp_collapse_alloc_failed is incremented if khugepaged found a range
|
||||
of pages that should be collapsed into one huge page but failed
|
||||
the allocation.
|
||||
|
||||
thp_split is incremented every time a huge page is split into base
|
||||
pages. This can happen for a variety of reasons but a common
|
||||
reason is that a huge page is old and is being reclaimed.
|
||||
|
||||
As the system ages, allocating huge pages may be expensive as the
|
||||
system uses memory compaction to copy data around memory to free a
|
||||
huge page for use. There are some counters in /proc/vmstat to help
|
||||
monitor this overhead.
|
||||
|
||||
compact_stall is incremented every time a process stalls to run
|
||||
memory compaction so that a huge page is free for use.
|
||||
|
||||
compact_success is incremented if the system compacted memory and
|
||||
freed a huge page for use.
|
||||
|
||||
compact_fail is incremented if the system tries to compact memory
|
||||
but failed.
|
||||
|
||||
compact_pages_moved is incremented each time a page is moved. If
|
||||
this value is increasing rapidly, it implies that the system
|
||||
is copying a lot of data to satisfy the huge page allocation.
|
||||
It is possible that the cost of copying exceeds any savings
|
||||
from reduced TLB misses.
|
||||
|
||||
compact_pagemigrate_failed is incremented when the underlying mechanism
|
||||
for moving a page failed.
|
||||
|
||||
compact_blocks_moved is incremented each time memory compaction examines
|
||||
a huge page aligned range of pages.
|
||||
|
||||
It is possible to establish how long the stalls were using the function
|
||||
tracer to record how long was spent in __alloc_pages_nodemask and
|
||||
using the mm_page_alloc tracepoint to identify which allocations were
|
||||
for huge pages.
|
||||
|
||||
== get_user_pages and follow_page ==
|
||||
|
||||
get_user_pages and follow_page if run on a hugepage, will return the
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -3232,10 +3232,8 @@ F: include/linux/clockchips.h
|
|||
F: include/linux/hrtimer.h
|
||||
|
||||
HIGH-SPEED SCC DRIVER FOR AX.25
|
||||
M: Klaus Kudielka <klaus.kudielka@ieee.org>
|
||||
L: linux-hams@vger.kernel.org
|
||||
W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/net/hamradio/dmascc.c
|
||||
F: drivers/net/hamradio/scc.c
|
||||
|
||||
|
@ -4511,12 +4509,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: drivers/mmc/host/imxmmc.*
|
||||
|
||||
MOUSE AND MISC DEVICES [GENERAL]
|
||||
M: Alessandro Rubini <rubini@ipvvis.unipv.it>
|
||||
S: Maintained
|
||||
F: drivers/input/mouse/
|
||||
F: include/linux/gpio_mouse.h
|
||||
|
||||
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
|
||||
M: Jiri Slaby <jirislaby@gmail.com>
|
||||
S: Maintained
|
||||
|
|
|
@ -173,7 +173,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
|
|||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_PCF8563=y
|
||||
CONFIG_RTC_DRV_IMXDI=y
|
||||
CONFIG_RTC_MXC=y
|
||||
CONFIG_RTC_DRV_MXC=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_IMX_SDMA=y
|
||||
CONFIG_IMX_DMA=y
|
||||
|
|
|
@ -178,7 +178,7 @@ CONFIG_NEW_LEDS=y
|
|||
CONFIG_LEDS_CLASS=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
|
||||
CONFIG_RTC_MXC=y
|
||||
CONFIG_RTC_DRV_MXC=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_IMX_SDMA=y
|
||||
CONFIG_EXT2_FS=y
|
||||
|
|
|
@ -40,6 +40,7 @@ config CRIS
|
|||
bool
|
||||
default y
|
||||
select HAVE_IDE
|
||||
select GENERIC_ATOMIC64
|
||||
select HAVE_GENERIC_HARDIRQS
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_IOMAP
|
||||
|
|
|
@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
|
|||
ptep->pte_low = pte.pte_low;
|
||||
}
|
||||
|
||||
#define pmd_read_atomic pmd_read_atomic
|
||||
/*
|
||||
* pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with
|
||||
* a "*pmdp" dereference done by gcc. Problem is, in certain places
|
||||
* where pte_offset_map_lock is called, concurrent page faults are
|
||||
* allowed, if the mmap_sem is hold for reading. An example is mincore
|
||||
* vs page faults vs MADV_DONTNEED. On the page fault side
|
||||
* pmd_populate rightfully does a set_64bit, but if we're reading the
|
||||
* pmd_t with a "*pmdp" on the mincore side, a SMP race can happen
|
||||
* because gcc will not read the 64bit of the pmd atomically. To fix
|
||||
* this all places running pmd_offset_map_lock() while holding the
|
||||
* mmap_sem in read mode, shall read the pmdp pointer using this
|
||||
* function to know if the pmd is null nor not, and in turn to know if
|
||||
* they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
|
||||
* operations.
|
||||
*
|
||||
* Without THP if the mmap_sem is hold for reading, the
|
||||
* pmd can only transition from null to not null while pmd_read_atomic runs.
|
||||
* So there's no need of literally reading it atomically.
|
||||
*
|
||||
* With THP if the mmap_sem is hold for reading, the pmd can become
|
||||
* THP or null or point to a pte (and in turn become "stable") at any
|
||||
* time under pmd_read_atomic, so it's mandatory to read it atomically
|
||||
* with cmpxchg8b.
|
||||
*/
|
||||
#ifndef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
{
|
||||
pmdval_t ret;
|
||||
u32 *tmp = (u32 *)pmdp;
|
||||
|
||||
ret = (pmdval_t) (*tmp);
|
||||
if (ret) {
|
||||
/*
|
||||
* If the low part is null, we must not read the high part
|
||||
* or we can end up with a partial pmd.
|
||||
*/
|
||||
smp_rmb();
|
||||
ret |= ((pmdval_t)*(tmp + 1)) << 32;
|
||||
}
|
||||
|
||||
return (pmd_t) { ret };
|
||||
}
|
||||
#else /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
{
|
||||
return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
|
||||
}
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
|
||||
|
|
|
@ -113,7 +113,9 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
|
|||
int x = e820x->nr_map;
|
||||
|
||||
if (x >= ARRAY_SIZE(e820x->map)) {
|
||||
printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
|
||||
printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n",
|
||||
(unsigned long long) start,
|
||||
(unsigned long long) (start + size - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -133,19 +135,19 @@ static void __init e820_print_type(u32 type)
|
|||
switch (type) {
|
||||
case E820_RAM:
|
||||
case E820_RESERVED_KERN:
|
||||
printk(KERN_CONT "(usable)");
|
||||
printk(KERN_CONT "usable");
|
||||
break;
|
||||
case E820_RESERVED:
|
||||
printk(KERN_CONT "(reserved)");
|
||||
printk(KERN_CONT "reserved");
|
||||
break;
|
||||
case E820_ACPI:
|
||||
printk(KERN_CONT "(ACPI data)");
|
||||
printk(KERN_CONT "ACPI data");
|
||||
break;
|
||||
case E820_NVS:
|
||||
printk(KERN_CONT "(ACPI NVS)");
|
||||
printk(KERN_CONT "ACPI NVS");
|
||||
break;
|
||||
case E820_UNUSABLE:
|
||||
printk(KERN_CONT "(unusable)");
|
||||
printk(KERN_CONT "unusable");
|
||||
break;
|
||||
default:
|
||||
printk(KERN_CONT "type %u", type);
|
||||
|
@ -158,10 +160,10 @@ void __init e820_print_map(char *who)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < e820.nr_map; i++) {
|
||||
printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
|
||||
printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who,
|
||||
(unsigned long long) e820.map[i].addr,
|
||||
(unsigned long long)
|
||||
(e820.map[i].addr + e820.map[i].size));
|
||||
(e820.map[i].addr + e820.map[i].size - 1));
|
||||
e820_print_type(e820.map[i].type);
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
|
@ -428,9 +430,8 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
|
|||
size = ULLONG_MAX - start;
|
||||
|
||||
end = start + size;
|
||||
printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ",
|
||||
(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ",
|
||||
(unsigned long long) start, (unsigned long long) (end - 1));
|
||||
e820_print_type(old_type);
|
||||
printk(KERN_CONT " ==> ");
|
||||
e820_print_type(new_type);
|
||||
|
@ -509,9 +510,8 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
|
|||
size = ULLONG_MAX - start;
|
||||
|
||||
end = start + size;
|
||||
printk(KERN_DEBUG "e820 remove range: %016Lx - %016Lx ",
|
||||
(unsigned long long) start,
|
||||
(unsigned long long) end);
|
||||
printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ",
|
||||
(unsigned long long) start, (unsigned long long) (end - 1));
|
||||
if (checktype)
|
||||
e820_print_type(old_type);
|
||||
printk(KERN_CONT "\n");
|
||||
|
@ -567,7 +567,7 @@ void __init update_e820(void)
|
|||
if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
|
||||
return;
|
||||
e820.nr_map = nr_map;
|
||||
printk(KERN_INFO "modified physical RAM map:\n");
|
||||
printk(KERN_INFO "e820: modified physical RAM map:\n");
|
||||
e820_print_map("modified");
|
||||
}
|
||||
static void __init update_e820_saved(void)
|
||||
|
@ -637,8 +637,8 @@ __init void e820_setup_gap(void)
|
|||
if (!found) {
|
||||
gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
|
||||
printk(KERN_ERR
|
||||
"PCI: Warning: Cannot find a gap in the 32bit address range\n"
|
||||
"PCI: Unassigned devices with 32bit resource registers may break!\n");
|
||||
"e820: cannot find a gap in the 32bit address range\n"
|
||||
"e820: PCI devices with unassigned 32bit BARs may break!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -648,8 +648,8 @@ __init void e820_setup_gap(void)
|
|||
pci_mem_start = gapstart;
|
||||
|
||||
printk(KERN_INFO
|
||||
"Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
|
||||
pci_mem_start, gapstart, gapsize);
|
||||
"e820: [mem %#010lx-%#010lx] available for PCI devices\n",
|
||||
gapstart, gapstart + gapsize - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -667,7 +667,7 @@ void __init parse_e820_ext(struct setup_data *sdata)
|
|||
extmap = (struct e820entry *)(sdata->data);
|
||||
__append_e820_map(extmap, entries);
|
||||
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
|
||||
printk(KERN_INFO "extended physical RAM map:\n");
|
||||
printk(KERN_INFO "e820: extended physical RAM map:\n");
|
||||
e820_print_map("extended");
|
||||
}
|
||||
|
||||
|
@ -734,7 +734,7 @@ u64 __init early_reserve_e820(u64 size, u64 align)
|
|||
addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
|
||||
if (addr) {
|
||||
e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
|
||||
printk(KERN_INFO "update e820_saved for early_reserve_e820\n");
|
||||
printk(KERN_INFO "e820: update e820_saved for early_reserve_e820\n");
|
||||
update_e820_saved();
|
||||
}
|
||||
|
||||
|
@ -784,7 +784,7 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
|
|||
if (last_pfn > max_arch_pfn)
|
||||
last_pfn = max_arch_pfn;
|
||||
|
||||
printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
|
||||
printk(KERN_INFO "e820: last_pfn = %#lx max_arch_pfn = %#lx\n",
|
||||
last_pfn, max_arch_pfn);
|
||||
return last_pfn;
|
||||
}
|
||||
|
@ -888,7 +888,7 @@ void __init finish_e820_parsing(void)
|
|||
early_panic("Invalid user supplied memory map");
|
||||
e820.nr_map = nr;
|
||||
|
||||
printk(KERN_INFO "user-defined physical RAM map:\n");
|
||||
printk(KERN_INFO "e820: user-defined physical RAM map:\n");
|
||||
e820_print_map("user");
|
||||
}
|
||||
}
|
||||
|
@ -996,8 +996,9 @@ void __init e820_reserve_resources_late(void)
|
|||
end = MAX_RESOURCE_SIZE;
|
||||
if (start >= end)
|
||||
continue;
|
||||
printk(KERN_DEBUG "reserve RAM buffer: %016llx - %016llx ",
|
||||
start, end);
|
||||
printk(KERN_DEBUG
|
||||
"e820: reserve RAM buffer [mem %#010llx-%#010llx]\n",
|
||||
start, end);
|
||||
reserve_region_with_split(&iomem_resource, start, end,
|
||||
"RAM buffer");
|
||||
}
|
||||
|
@ -1047,7 +1048,7 @@ void __init setup_memory_map(void)
|
|||
|
||||
who = x86_init.resources.memory_setup();
|
||||
memcpy(&e820_saved, &e820, sizeof(struct e820map));
|
||||
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
|
||||
printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n");
|
||||
e820_print_map(who);
|
||||
}
|
||||
|
||||
|
|
|
@ -568,8 +568,8 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
|||
struct mpf_intel *mpf;
|
||||
unsigned long mem;
|
||||
|
||||
apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
|
||||
bp, length);
|
||||
apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n",
|
||||
base, base + length - 1);
|
||||
BUILD_BUG_ON(sizeof(*mpf) != 16);
|
||||
|
||||
while (length > 0) {
|
||||
|
@ -584,8 +584,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
|||
#endif
|
||||
mpf_found = mpf;
|
||||
|
||||
printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
|
||||
mpf, (u64)virt_to_phys(mpf));
|
||||
printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
|
||||
(unsigned long long) virt_to_phys(mpf),
|
||||
(unsigned long long) virt_to_phys(mpf) +
|
||||
sizeof(*mpf) - 1, mpf);
|
||||
|
||||
mem = virt_to_phys(mpf);
|
||||
memblock_reserve(mem, sizeof(*mpf));
|
||||
|
|
|
@ -334,8 +334,8 @@ static void __init relocate_initrd(void)
|
|||
memblock_reserve(ramdisk_here, area_size);
|
||||
initrd_start = ramdisk_here + PAGE_OFFSET;
|
||||
initrd_end = initrd_start + ramdisk_size;
|
||||
printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
|
||||
ramdisk_here, ramdisk_here + ramdisk_size);
|
||||
printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
|
||||
ramdisk_here, ramdisk_here + ramdisk_size - 1);
|
||||
|
||||
q = (char *)initrd_start;
|
||||
|
||||
|
@ -366,8 +366,8 @@ static void __init relocate_initrd(void)
|
|||
/* high pages is not converted by early_res_to_bootmem */
|
||||
ramdisk_image = boot_params.hdr.ramdisk_image;
|
||||
ramdisk_size = boot_params.hdr.ramdisk_size;
|
||||
printk(KERN_INFO "Move RAMDISK from %016llx - %016llx to"
|
||||
" %08llx - %08llx\n",
|
||||
printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
|
||||
" [mem %#010llx-%#010llx]\n",
|
||||
ramdisk_image, ramdisk_image + ramdisk_size - 1,
|
||||
ramdisk_here, ramdisk_here + ramdisk_size - 1);
|
||||
}
|
||||
|
@ -392,8 +392,8 @@ static void __init reserve_initrd(void)
|
|||
ramdisk_size, end_of_lowmem>>1);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "RAMDISK: %08llx - %08llx\n", ramdisk_image,
|
||||
ramdisk_end);
|
||||
printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
|
||||
ramdisk_end - 1);
|
||||
|
||||
|
||||
if (ramdisk_end <= end_of_lowmem) {
|
||||
|
@ -906,8 +906,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
setup_bios_corruption_check();
|
||||
#endif
|
||||
|
||||
printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
|
||||
max_pfn_mapped<<PAGE_SHIFT);
|
||||
printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
|
||||
(max_pfn_mapped<<PAGE_SHIFT) - 1);
|
||||
|
||||
setup_trampolines();
|
||||
|
||||
|
|
|
@ -84,8 +84,9 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
|
|||
pgt_buf_end = pgt_buf_start;
|
||||
pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
|
||||
|
||||
printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
|
||||
end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
|
||||
printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
|
||||
end - 1, pgt_buf_start << PAGE_SHIFT,
|
||||
(pgt_buf_top << PAGE_SHIFT) - 1);
|
||||
}
|
||||
|
||||
void __init native_pagetable_reserve(u64 start, u64 end)
|
||||
|
@ -132,7 +133,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
|
|||
int nr_range, i;
|
||||
int use_pse, use_gbpages;
|
||||
|
||||
printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
|
||||
printk(KERN_INFO "init_memory_mapping: [mem %#010lx-%#010lx]\n",
|
||||
start, end - 1);
|
||||
|
||||
#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
|
||||
/*
|
||||
|
@ -251,8 +253,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
|
|||
}
|
||||
|
||||
for (i = 0; i < nr_range; i++)
|
||||
printk(KERN_DEBUG " %010lx - %010lx page %s\n",
|
||||
mr[i].start, mr[i].end,
|
||||
printk(KERN_DEBUG " [mem %#010lx-%#010lx] page %s\n",
|
||||
mr[i].start, mr[i].end - 1,
|
||||
(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
|
||||
(mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
|
||||
|
||||
|
@ -350,8 +352,8 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
|
|||
* create a kernel page fault:
|
||||
*/
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
|
||||
begin, end);
|
||||
printk(KERN_INFO "debug: unmapping init [mem %#010lx-%#010lx]\n",
|
||||
begin, end - 1);
|
||||
set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
|
||||
#else
|
||||
/*
|
||||
|
|
|
@ -141,8 +141,8 @@ static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
|
|||
|
||||
/* whine about and ignore invalid blks */
|
||||
if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
|
||||
pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
|
||||
nid, start, end);
|
||||
pr_warning("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
|
||||
nid, start, end - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -210,8 +210,8 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
|
|||
|
||||
start = roundup(start, ZONE_ALIGN);
|
||||
|
||||
printk(KERN_INFO "Initmem setup node %d %016Lx-%016Lx\n",
|
||||
nid, start, end);
|
||||
printk(KERN_INFO "Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
|
||||
nid, start, end - 1);
|
||||
|
||||
/*
|
||||
* Allocate node data. Try remap allocator first, node-local
|
||||
|
@ -232,7 +232,7 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
|
|||
}
|
||||
|
||||
/* report and initialize */
|
||||
printk(KERN_INFO " NODE_DATA [%016Lx - %016Lx]%s\n",
|
||||
printk(KERN_INFO " NODE_DATA [mem %#010Lx-%#010Lx]%s\n",
|
||||
nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : "");
|
||||
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
||||
if (!remapped && tnid != nid)
|
||||
|
@ -291,14 +291,14 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
|
|||
*/
|
||||
if (bi->end > bj->start && bi->start < bj->end) {
|
||||
if (bi->nid != bj->nid) {
|
||||
pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
|
||||
bi->nid, bi->start, bi->end,
|
||||
bj->nid, bj->start, bj->end);
|
||||
pr_err("NUMA: node %d [mem %#010Lx-%#010Lx] overlaps with node %d [mem %#010Lx-%#010Lx]\n",
|
||||
bi->nid, bi->start, bi->end - 1,
|
||||
bj->nid, bj->start, bj->end - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
|
||||
bi->nid, bi->start, bi->end,
|
||||
bj->start, bj->end);
|
||||
pr_warning("NUMA: Warning: node %d [mem %#010Lx-%#010Lx] overlaps with itself [mem %#010Lx-%#010Lx]\n",
|
||||
bi->nid, bi->start, bi->end - 1,
|
||||
bj->start, bj->end - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -320,9 +320,9 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
|
|||
}
|
||||
if (k < mi->nr_blks)
|
||||
continue;
|
||||
printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%Lx,%Lx)\n",
|
||||
bi->nid, bi->start, bi->end, bj->start, bj->end,
|
||||
start, end);
|
||||
printk(KERN_INFO "NUMA: Node %d [mem %#010Lx-%#010Lx] + [mem %#010Lx-%#010Lx] -> [mem %#010Lx-%#010Lx]\n",
|
||||
bi->nid, bi->start, bi->end - 1, bj->start,
|
||||
bj->end - 1, start, end - 1);
|
||||
bi->start = start;
|
||||
bi->end = end;
|
||||
numa_remove_memblk_from(j--, mi);
|
||||
|
@ -616,8 +616,8 @@ static int __init dummy_numa_init(void)
|
|||
{
|
||||
printk(KERN_INFO "%s\n",
|
||||
numa_off ? "NUMA turned off" : "No NUMA configuration found");
|
||||
printk(KERN_INFO "Faking a node at %016Lx-%016Lx\n",
|
||||
0LLU, PFN_PHYS(max_pfn));
|
||||
printk(KERN_INFO "Faking a node at [mem %#018Lx-%#018Lx]\n",
|
||||
0LLU, PFN_PHYS(max_pfn) - 1);
|
||||
|
||||
node_set(0, numa_nodes_parsed);
|
||||
numa_add_memblk(0, 0, PFN_PHYS(max_pfn));
|
||||
|
|
|
@ -68,8 +68,8 @@ static int __init emu_setup_memblk(struct numa_meminfo *ei,
|
|||
numa_remove_memblk_from(phys_blk, pi);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
|
||||
eb->start, eb->end, (eb->end - eb->start) >> 20);
|
||||
printk(KERN_INFO "Faking node %d at [mem %#018Lx-%#018Lx] (%LuMB)\n",
|
||||
nid, eb->start, eb->end - 1, (eb->end - eb->start) >> 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -209,9 +209,8 @@ static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
|
|||
page = pfn_to_page(pfn);
|
||||
type = get_page_memtype(page);
|
||||
if (type != -1) {
|
||||
printk(KERN_INFO "reserve_ram_pages_type failed "
|
||||
"0x%Lx-0x%Lx, track 0x%lx, req 0x%lx\n",
|
||||
start, end, type, req_type);
|
||||
printk(KERN_INFO "reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%lx, req 0x%lx\n",
|
||||
start, end - 1, type, req_type);
|
||||
if (new_type)
|
||||
*new_type = type;
|
||||
|
||||
|
@ -314,9 +313,9 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
|
|||
|
||||
err = rbt_memtype_check_insert(new, new_type);
|
||||
if (err) {
|
||||
printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
|
||||
"track %s, req %s\n",
|
||||
start, end, cattr_name(new->type), cattr_name(req_type));
|
||||
printk(KERN_INFO "reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
|
||||
start, end - 1,
|
||||
cattr_name(new->type), cattr_name(req_type));
|
||||
kfree(new);
|
||||
spin_unlock(&memtype_lock);
|
||||
|
||||
|
@ -325,8 +324,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
|
|||
|
||||
spin_unlock(&memtype_lock);
|
||||
|
||||
dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
|
||||
start, end, cattr_name(new->type), cattr_name(req_type),
|
||||
dprintk("reserve_memtype added [mem %#010Lx-%#010Lx], track %s, req %s, ret %s\n",
|
||||
start, end - 1, cattr_name(new->type), cattr_name(req_type),
|
||||
new_type ? cattr_name(*new_type) : "-");
|
||||
|
||||
return err;
|
||||
|
@ -360,14 +359,14 @@ int free_memtype(u64 start, u64 end)
|
|||
spin_unlock(&memtype_lock);
|
||||
|
||||
if (!entry) {
|
||||
printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
|
||||
current->comm, current->pid, start, end);
|
||||
printk(KERN_INFO "%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
|
||||
current->comm, current->pid, start, end - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfree(entry);
|
||||
|
||||
dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
|
||||
dprintk("free_memtype request [mem %#010Lx-%#010Lx]\n", start, end - 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -491,9 +490,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
|||
|
||||
while (cursor < to) {
|
||||
if (!devmem_is_allowed(pfn)) {
|
||||
printk(KERN_INFO
|
||||
"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
|
||||
current->comm, from, to);
|
||||
printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx]\n",
|
||||
current->comm, from, to - 1);
|
||||
return 0;
|
||||
}
|
||||
cursor += PAGE_SIZE;
|
||||
|
@ -554,12 +552,11 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
|
|||
size;
|
||||
|
||||
if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
|
||||
printk(KERN_INFO
|
||||
"%s:%d ioremap_change_attr failed %s "
|
||||
"for %Lx-%Lx\n",
|
||||
printk(KERN_INFO "%s:%d ioremap_change_attr failed %s "
|
||||
"for [mem %#010Lx-%#010Lx]\n",
|
||||
current->comm, current->pid,
|
||||
cattr_name(flags),
|
||||
base, (unsigned long long)(base + size));
|
||||
base, (unsigned long long)(base + size-1));
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
@ -591,12 +588,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
|
|||
|
||||
flags = lookup_memtype(paddr);
|
||||
if (want_flags != flags) {
|
||||
printk(KERN_WARNING
|
||||
"%s:%d map pfn RAM range req %s for %Lx-%Lx, got %s\n",
|
||||
printk(KERN_WARNING "%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
|
||||
current->comm, current->pid,
|
||||
cattr_name(want_flags),
|
||||
(unsigned long long)paddr,
|
||||
(unsigned long long)(paddr + size),
|
||||
(unsigned long long)(paddr + size - 1),
|
||||
cattr_name(flags));
|
||||
*vma_prot = __pgprot((pgprot_val(*vma_prot) &
|
||||
(~_PAGE_CACHE_MASK)) |
|
||||
|
@ -614,11 +610,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
|
|||
!is_new_memtype_allowed(paddr, size, want_flags, flags)) {
|
||||
free_memtype(paddr, paddr + size);
|
||||
printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
|
||||
" for %Lx-%Lx, got %s\n",
|
||||
" for [mem %#010Lx-%#010Lx], got %s\n",
|
||||
current->comm, current->pid,
|
||||
cattr_name(want_flags),
|
||||
(unsigned long long)paddr,
|
||||
(unsigned long long)(paddr + size),
|
||||
(unsigned long long)(paddr + size - 1),
|
||||
cattr_name(flags));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -176,8 +176,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
|
|||
return;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
|
||||
start, end);
|
||||
printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",
|
||||
node, pxm,
|
||||
(unsigned long long) start, (unsigned long long) end - 1);
|
||||
}
|
||||
|
||||
void __init acpi_numa_arch_fixup(void) {}
|
||||
|
|
|
@ -592,11 +592,9 @@ static ssize_t print_nodes_state(enum node_states state, char *buf)
|
|||
{
|
||||
int n;
|
||||
|
||||
n = nodelist_scnprintf(buf, PAGE_SIZE, node_states[state]);
|
||||
if (n > 0 && PAGE_SIZE > n + 1) {
|
||||
*(buf + n++) = '\n';
|
||||
*(buf + n++) = '\0';
|
||||
}
|
||||
n = nodelist_scnprintf(buf, PAGE_SIZE-2, node_states[state]);
|
||||
buf[n++] = '\n';
|
||||
buf[n] = '\0';
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,19 @@ config LEDS_LM3530
|
|||
controlled manually or using PWM input or using ambient
|
||||
light automatically.
|
||||
|
||||
config LEDS_LM3533
|
||||
tristate "LED support for LM3533"
|
||||
depends on LEDS_CLASS
|
||||
depends on MFD_LM3533
|
||||
help
|
||||
This option enables support for the LEDs on National Semiconductor /
|
||||
TI LM3533 Lighting Power chips.
|
||||
|
||||
The LEDs can be controlled directly, through PWM input, or by the
|
||||
ambient-light-sensor interface. The chip supports
|
||||
hardware-accelerated blinking with maximum on and off periods of 9.8
|
||||
and 77 seconds respectively.
|
||||
|
||||
config LEDS_LOCOMO
|
||||
tristate "LED Support for Locomo device"
|
||||
depends on LEDS_CLASS
|
||||
|
@ -259,6 +272,14 @@ config LEDS_DA903X
|
|||
This option enables support for on-chip LED drivers found
|
||||
on Dialog Semiconductor DA9030/DA9034 PMICs.
|
||||
|
||||
config LEDS_DA9052
|
||||
tristate "Dialog DA9052/DA9053 LEDS"
|
||||
depends on LEDS_CLASS
|
||||
depends on PMIC_DA9052
|
||||
help
|
||||
This option enables support for on-chip LED drivers found
|
||||
on Dialog Semiconductor DA9052-BC and DA9053-AA/Bx PMICs.
|
||||
|
||||
config LEDS_DAC124S085
|
||||
tristate "LED Support for DAC124S085 SPI DAC"
|
||||
depends on LEDS_CLASS
|
||||
|
@ -471,4 +492,12 @@ config LEDS_TRIGGER_DEFAULT_ON
|
|||
comment "iptables trigger is under Netfilter config (LED target)"
|
||||
depends on LEDS_TRIGGERS
|
||||
|
||||
config LEDS_TRIGGER_TRANSIENT
|
||||
tristate "LED Transient Trigger"
|
||||
depends on LEDS_TRIGGERS
|
||||
help
|
||||
This allows one time activation of a transient state on
|
||||
GPIO/PWM based hadrware.
|
||||
If unsure, say Y.
|
||||
|
||||
endif # NEW_LEDS
|
||||
|
|
|
@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
|
|||
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
|
||||
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
|
||||
obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
|
||||
obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o
|
||||
obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
|
||||
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
|
||||
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
|
||||
|
@ -31,6 +32,7 @@ obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
|
|||
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
|
||||
obj-$(CONFIG_LEDS_PCA9633) += leds-pca9633.o
|
||||
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
|
||||
obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o
|
||||
obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
|
||||
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
|
||||
obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
|
||||
|
@ -56,3 +58,4 @@ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
|
|||
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
|
||||
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
|
||||
|
|
|
@ -44,23 +44,18 @@ static ssize_t led_brightness_store(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
unsigned long state;
|
||||
ssize_t ret = -EINVAL;
|
||||
char *after;
|
||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
||||
size_t count = after - buf;
|
||||
|
||||
if (isspace(*after))
|
||||
count++;
|
||||
ret = kstrtoul(buf, 10, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (count == size) {
|
||||
ret = count;
|
||||
if (state == LED_OFF)
|
||||
led_trigger_remove(led_cdev);
|
||||
led_set_brightness(led_cdev, state);
|
||||
|
||||
if (state == LED_OFF)
|
||||
led_trigger_remove(led_cdev);
|
||||
led_set_brightness(led_cdev, state);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t led_max_brightness_show(struct device *dev,
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* LED Driver for Dialog DA9052 PMICs.
|
||||
*
|
||||
* Copyright(c) 2012 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: David Dajun Chen <dchen@diasemi.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mfd/da9052/reg.h>
|
||||
#include <linux/mfd/da9052/da9052.h>
|
||||
#include <linux/mfd/da9052/pdata.h>
|
||||
|
||||
#define DA9052_OPENDRAIN_OUTPUT 2
|
||||
#define DA9052_SET_HIGH_LVL_OUTPUT (1 << 3)
|
||||
#define DA9052_MASK_UPPER_NIBBLE 0xF0
|
||||
#define DA9052_MASK_LOWER_NIBBLE 0x0F
|
||||
#define DA9052_NIBBLE_SHIFT 4
|
||||
#define DA9052_MAX_BRIGHTNESS 0x5f
|
||||
|
||||
struct da9052_led {
|
||||
struct led_classdev cdev;
|
||||
struct work_struct work;
|
||||
struct da9052 *da9052;
|
||||
unsigned char led_index;
|
||||
unsigned char id;
|
||||
int brightness;
|
||||
};
|
||||
|
||||
static unsigned char led_reg[] = {
|
||||
DA9052_LED_CONT_4_REG,
|
||||
DA9052_LED_CONT_5_REG,
|
||||
};
|
||||
|
||||
static int da9052_set_led_brightness(struct da9052_led *led)
|
||||
{
|
||||
u8 val;
|
||||
int error;
|
||||
|
||||
val = (led->brightness & 0x7f) | DA9052_LED_CONT_DIM;
|
||||
|
||||
error = da9052_reg_write(led->da9052, led_reg[led->led_index], val);
|
||||
if (error < 0)
|
||||
dev_err(led->da9052->dev, "Failed to set led brightness, %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void da9052_led_work(struct work_struct *work)
|
||||
{
|
||||
struct da9052_led *led = container_of(work, struct da9052_led, work);
|
||||
|
||||
da9052_set_led_brightness(led);
|
||||
}
|
||||
|
||||
static void da9052_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct da9052_led *led;
|
||||
|
||||
led = container_of(led_cdev, struct da9052_led, cdev);
|
||||
led->brightness = value;
|
||||
schedule_work(&led->work);
|
||||
}
|
||||
|
||||
static int da9052_configure_leds(struct da9052 *da9052)
|
||||
{
|
||||
int error;
|
||||
unsigned char register_value = DA9052_OPENDRAIN_OUTPUT
|
||||
| DA9052_SET_HIGH_LVL_OUTPUT;
|
||||
|
||||
error = da9052_reg_update(da9052, DA9052_GPIO_14_15_REG,
|
||||
DA9052_MASK_LOWER_NIBBLE,
|
||||
register_value);
|
||||
|
||||
if (error < 0) {
|
||||
dev_err(da9052->dev, "Failed to write GPIO 14-15 reg, %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = da9052_reg_update(da9052, DA9052_GPIO_14_15_REG,
|
||||
DA9052_MASK_UPPER_NIBBLE,
|
||||
register_value << DA9052_NIBBLE_SHIFT);
|
||||
if (error < 0)
|
||||
dev_err(da9052->dev, "Failed to write GPIO 14-15 reg, %d\n",
|
||||
error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devinit da9052_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_pdata *pdata;
|
||||
struct da9052 *da9052;
|
||||
struct led_platform_data *pled;
|
||||
struct da9052_led *led = NULL;
|
||||
int error = -ENODEV;
|
||||
int i;
|
||||
|
||||
da9052 = dev_get_drvdata(pdev->dev.parent);
|
||||
pdata = da9052->dev->platform_data;
|
||||
if (pdata == NULL) {
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
pled = pdata->pled;
|
||||
if (pled == NULL) {
|
||||
dev_err(&pdev->dev, "No platform data for LED\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
led = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct da9052_led) * pled->num_leds,
|
||||
GFP_KERNEL);
|
||||
if (led == NULL) {
|
||||
dev_err(&pdev->dev, "Failed to alloc memory\n");
|
||||
error = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < pled->num_leds; i++) {
|
||||
led[i].cdev.name = pled->leds[i].name;
|
||||
led[i].cdev.brightness_set = da9052_led_set;
|
||||
led[i].cdev.brightness = LED_OFF;
|
||||
led[i].cdev.max_brightness = DA9052_MAX_BRIGHTNESS;
|
||||
led[i].brightness = LED_OFF;
|
||||
led[i].led_index = pled->leds[i].flags;
|
||||
led[i].da9052 = dev_get_drvdata(pdev->dev.parent);
|
||||
INIT_WORK(&led[i].work, da9052_led_work);
|
||||
|
||||
error = led_classdev_register(pdev->dev.parent, &led[i].cdev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to register led %d\n",
|
||||
led[i].led_index);
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
error = da9052_set_led_brightness(&led[i]);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Unable to init led %d\n",
|
||||
led[i].led_index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
error = da9052_configure_leds(led->da9052);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to configure GPIO LED%d\n", error);
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, led);
|
||||
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
led_classdev_unregister(&led[i].cdev);
|
||||
cancel_work_sync(&led[i].work);
|
||||
}
|
||||
err:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit da9052_led_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_led *led = platform_get_drvdata(pdev);
|
||||
struct da9052_pdata *pdata;
|
||||
struct da9052 *da9052;
|
||||
struct led_platform_data *pled;
|
||||
int i;
|
||||
|
||||
da9052 = dev_get_drvdata(pdev->dev.parent);
|
||||
pdata = da9052->dev->platform_data;
|
||||
pled = pdata->pled;
|
||||
|
||||
for (i = 0; i < pled->num_leds; i++) {
|
||||
led[i].brightness = 0;
|
||||
da9052_set_led_brightness(&led[i]);
|
||||
led_classdev_unregister(&led[i].cdev);
|
||||
cancel_work_sync(&led[i].work);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9052_led_driver = {
|
||||
.driver = {
|
||||
.name = "da9052-leds",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = da9052_led_probe,
|
||||
.remove = __devexit_p(da9052_led_remove),
|
||||
};
|
||||
|
||||
module_platform_driver(da9052_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Dialog Semiconductor Ltd <dchen@diasemi.com>");
|
||||
MODULE_DESCRIPTION("LED driver for Dialog DA9052 PMIC");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -113,6 +113,18 @@ struct lm3530_data {
|
|||
bool enable;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct lm3530_als_data
|
||||
* @config : value of ALS configuration register
|
||||
* @imp_sel : value of ALS resistor select register
|
||||
* @zone : values of ALS ZB(Zone Boundary) registers
|
||||
*/
|
||||
struct lm3530_als_data {
|
||||
u8 config;
|
||||
u8 imp_sel;
|
||||
u8 zones[LM3530_ALS_ZB_MAX];
|
||||
};
|
||||
|
||||
static const u8 lm3530_reg[LM3530_REG_MAX] = {
|
||||
LM3530_GEN_CONFIG,
|
||||
LM3530_ALS_CONFIG,
|
||||
|
@ -141,29 +153,65 @@ static int lm3530_get_mode_from_str(const char *str)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void lm3530_als_configure(struct lm3530_platform_data *pdata,
|
||||
struct lm3530_als_data *als)
|
||||
{
|
||||
int i;
|
||||
u32 als_vmin, als_vmax, als_vstep;
|
||||
|
||||
if (pdata->als_vmax == 0) {
|
||||
pdata->als_vmin = 0;
|
||||
pdata->als_vmax = LM3530_ALS_WINDOW_mV;
|
||||
}
|
||||
|
||||
als_vmin = pdata->als_vmin;
|
||||
als_vmax = pdata->als_vmax;
|
||||
|
||||
if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
|
||||
pdata->als_vmax = als_vmax = als_vmin + LM3530_ALS_WINDOW_mV;
|
||||
|
||||
/* n zone boundary makes n+1 zones */
|
||||
als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
|
||||
|
||||
for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
|
||||
als->zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
|
||||
als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
|
||||
|
||||
als->config =
|
||||
(pdata->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
|
||||
(LM3530_ENABLE_ALS) |
|
||||
(pdata->als_input_mode << LM3530_ALS_SEL_SHIFT);
|
||||
|
||||
als->imp_sel =
|
||||
(pdata->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
|
||||
(pdata->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
|
||||
}
|
||||
|
||||
static int lm3530_init_registers(struct lm3530_data *drvdata)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
u8 gen_config;
|
||||
u8 als_config = 0;
|
||||
u8 brt_ramp;
|
||||
u8 als_imp_sel = 0;
|
||||
u8 brightness;
|
||||
u8 reg_val[LM3530_REG_MAX];
|
||||
u8 zones[LM3530_ALS_ZB_MAX];
|
||||
u32 als_vmin, als_vmax, als_vstep;
|
||||
struct lm3530_platform_data *pdata = drvdata->pdata;
|
||||
struct i2c_client *client = drvdata->client;
|
||||
struct lm3530_pwm_data *pwm = &pdata->pwm_data;
|
||||
struct lm3530_als_data als;
|
||||
|
||||
memset(&als, 0, sizeof(struct lm3530_als_data));
|
||||
|
||||
gen_config = (pdata->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) |
|
||||
((pdata->max_current & 7) << LM3530_MAX_CURR_SHIFT);
|
||||
|
||||
switch (drvdata->mode) {
|
||||
case LM3530_BL_MODE_MANUAL:
|
||||
gen_config |= LM3530_ENABLE_I2C;
|
||||
break;
|
||||
case LM3530_BL_MODE_ALS:
|
||||
gen_config |= LM3530_ENABLE_I2C;
|
||||
lm3530_als_configure(pdata, &als);
|
||||
break;
|
||||
case LM3530_BL_MODE_PWM:
|
||||
gen_config |= LM3530_ENABLE_PWM | LM3530_ENABLE_PWM_SIMPLE |
|
||||
|
@ -171,38 +219,6 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
|
|||
break;
|
||||
}
|
||||
|
||||
if (drvdata->mode == LM3530_BL_MODE_ALS) {
|
||||
if (pdata->als_vmax == 0) {
|
||||
pdata->als_vmin = 0;
|
||||
pdata->als_vmax = LM3530_ALS_WINDOW_mV;
|
||||
}
|
||||
|
||||
als_vmin = pdata->als_vmin;
|
||||
als_vmax = pdata->als_vmax;
|
||||
|
||||
if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV)
|
||||
pdata->als_vmax = als_vmax =
|
||||
als_vmin + LM3530_ALS_WINDOW_mV;
|
||||
|
||||
/* n zone boundary makes n+1 zones */
|
||||
als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1);
|
||||
|
||||
for (i = 0; i < LM3530_ALS_ZB_MAX; i++)
|
||||
zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) +
|
||||
als_vstep + (i * als_vstep)) * LED_FULL)
|
||||
/ 1000;
|
||||
|
||||
als_config =
|
||||
(pdata->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
|
||||
(LM3530_ENABLE_ALS) |
|
||||
(pdata->als_input_mode << LM3530_ALS_SEL_SHIFT);
|
||||
|
||||
als_imp_sel =
|
||||
(pdata->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
|
||||
(pdata->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
|
||||
|
||||
}
|
||||
|
||||
brt_ramp = (pdata->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) |
|
||||
(pdata->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT);
|
||||
|
||||
|
@ -215,14 +231,14 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
|
|||
brightness = drvdata->led_dev.max_brightness;
|
||||
|
||||
reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */
|
||||
reg_val[1] = als_config; /* LM3530_ALS_CONFIG */
|
||||
reg_val[1] = als.config; /* LM3530_ALS_CONFIG */
|
||||
reg_val[2] = brt_ramp; /* LM3530_BRT_RAMP_RATE */
|
||||
reg_val[3] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */
|
||||
reg_val[3] = als.imp_sel; /* LM3530_ALS_IMP_SELECT */
|
||||
reg_val[4] = brightness; /* LM3530_BRT_CTRL_REG */
|
||||
reg_val[5] = zones[0]; /* LM3530_ALS_ZB0_REG */
|
||||
reg_val[6] = zones[1]; /* LM3530_ALS_ZB1_REG */
|
||||
reg_val[7] = zones[2]; /* LM3530_ALS_ZB2_REG */
|
||||
reg_val[8] = zones[3]; /* LM3530_ALS_ZB3_REG */
|
||||
reg_val[5] = als.zones[0]; /* LM3530_ALS_ZB0_REG */
|
||||
reg_val[6] = als.zones[1]; /* LM3530_ALS_ZB1_REG */
|
||||
reg_val[7] = als.zones[2]; /* LM3530_ALS_ZB2_REG */
|
||||
reg_val[8] = als.zones[3]; /* LM3530_ALS_ZB3_REG */
|
||||
reg_val[9] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */
|
||||
reg_val[10] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */
|
||||
reg_val[11] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */
|
||||
|
|
|
@ -0,0 +1,785 @@
|
|||
/*
|
||||
* leds-lm3533.c -- LM3533 LED driver
|
||||
*
|
||||
* Copyright (C) 2011-2012 Texas Instruments
|
||||
*
|
||||
* Author: Johan Hovold <jhovold@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <linux/mfd/lm3533.h>
|
||||
|
||||
|
||||
#define LM3533_LVCTRLBANK_MIN 2
|
||||
#define LM3533_LVCTRLBANK_MAX 5
|
||||
#define LM3533_LVCTRLBANK_COUNT 4
|
||||
#define LM3533_RISEFALLTIME_MAX 7
|
||||
#define LM3533_ALS_CHANNEL_LV_MIN 1
|
||||
#define LM3533_ALS_CHANNEL_LV_MAX 2
|
||||
|
||||
#define LM3533_REG_CTRLBANK_BCONF_BASE 0x1b
|
||||
#define LM3533_REG_PATTERN_ENABLE 0x28
|
||||
#define LM3533_REG_PATTERN_LOW_TIME_BASE 0x71
|
||||
#define LM3533_REG_PATTERN_HIGH_TIME_BASE 0x72
|
||||
#define LM3533_REG_PATTERN_RISETIME_BASE 0x74
|
||||
#define LM3533_REG_PATTERN_FALLTIME_BASE 0x75
|
||||
|
||||
#define LM3533_REG_PATTERN_STEP 0x10
|
||||
|
||||
#define LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK 0x04
|
||||
#define LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK 0x02
|
||||
#define LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK 0x01
|
||||
|
||||
#define LM3533_LED_FLAG_PATTERN_ENABLE 1
|
||||
|
||||
|
||||
struct lm3533_led {
|
||||
struct lm3533 *lm3533;
|
||||
struct lm3533_ctrlbank cb;
|
||||
struct led_classdev cdev;
|
||||
int id;
|
||||
|
||||
struct mutex mutex;
|
||||
unsigned long flags;
|
||||
|
||||
struct work_struct work;
|
||||
u8 new_brightness;
|
||||
};
|
||||
|
||||
|
||||
static inline struct lm3533_led *to_lm3533_led(struct led_classdev *cdev)
|
||||
{
|
||||
return container_of(cdev, struct lm3533_led, cdev);
|
||||
}
|
||||
|
||||
static inline int lm3533_led_get_ctrlbank_id(struct lm3533_led *led)
|
||||
{
|
||||
return led->id + 2;
|
||||
}
|
||||
|
||||
static inline u8 lm3533_led_get_lv_reg(struct lm3533_led *led, u8 base)
|
||||
{
|
||||
return base + led->id;
|
||||
}
|
||||
|
||||
static inline u8 lm3533_led_get_pattern(struct lm3533_led *led)
|
||||
{
|
||||
return led->id;
|
||||
}
|
||||
|
||||
static inline u8 lm3533_led_get_pattern_reg(struct lm3533_led *led,
|
||||
u8 base)
|
||||
{
|
||||
return base + lm3533_led_get_pattern(led) * LM3533_REG_PATTERN_STEP;
|
||||
}
|
||||
|
||||
static int lm3533_led_pattern_enable(struct lm3533_led *led, int enable)
|
||||
{
|
||||
u8 mask;
|
||||
u8 val;
|
||||
int pattern;
|
||||
int state;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(led->cdev.dev, "%s - %d\n", __func__, enable);
|
||||
|
||||
mutex_lock(&led->mutex);
|
||||
|
||||
state = test_bit(LM3533_LED_FLAG_PATTERN_ENABLE, &led->flags);
|
||||
if ((enable && state) || (!enable && !state))
|
||||
goto out;
|
||||
|
||||
pattern = lm3533_led_get_pattern(led);
|
||||
mask = 1 << (2 * pattern);
|
||||
|
||||
if (enable)
|
||||
val = mask;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
ret = lm3533_update(led->lm3533, LM3533_REG_PATTERN_ENABLE, val, mask);
|
||||
if (ret) {
|
||||
dev_err(led->cdev.dev, "failed to enable pattern %d (%d)\n",
|
||||
pattern, enable);
|
||||
goto out;
|
||||
}
|
||||
|
||||
__change_bit(LM3533_LED_FLAG_PATTERN_ENABLE, &led->flags);
|
||||
out:
|
||||
mutex_unlock(&led->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lm3533_led_work(struct work_struct *work)
|
||||
{
|
||||
struct lm3533_led *led = container_of(work, struct lm3533_led, work);
|
||||
|
||||
dev_dbg(led->cdev.dev, "%s - %u\n", __func__, led->new_brightness);
|
||||
|
||||
if (led->new_brightness == 0)
|
||||
lm3533_led_pattern_enable(led, 0); /* disable blink */
|
||||
|
||||
lm3533_ctrlbank_set_brightness(&led->cb, led->new_brightness);
|
||||
}
|
||||
|
||||
static void lm3533_led_set(struct led_classdev *cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct lm3533_led *led = to_lm3533_led(cdev);
|
||||
|
||||
dev_dbg(led->cdev.dev, "%s - %d\n", __func__, value);
|
||||
|
||||
led->new_brightness = value;
|
||||
schedule_work(&led->work);
|
||||
}
|
||||
|
||||
static enum led_brightness lm3533_led_get(struct led_classdev *cdev)
|
||||
{
|
||||
struct lm3533_led *led = to_lm3533_led(cdev);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = lm3533_ctrlbank_get_brightness(&led->cb, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(led->cdev.dev, "%s - %u\n", __func__, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Pattern generator defines (delays in us). */
|
||||
#define LM3533_LED_DELAY1_VMIN 0x00
|
||||
#define LM3533_LED_DELAY2_VMIN 0x3d
|
||||
#define LM3533_LED_DELAY3_VMIN 0x80
|
||||
|
||||
#define LM3533_LED_DELAY1_VMAX (LM3533_LED_DELAY2_VMIN - 1)
|
||||
#define LM3533_LED_DELAY2_VMAX (LM3533_LED_DELAY3_VMIN - 1)
|
||||
#define LM3533_LED_DELAY3_VMAX 0xff
|
||||
|
||||
#define LM3533_LED_DELAY1_TMIN 16384U
|
||||
#define LM3533_LED_DELAY2_TMIN 1130496U
|
||||
#define LM3533_LED_DELAY3_TMIN 10305536U
|
||||
|
||||
#define LM3533_LED_DELAY1_TMAX 999424U
|
||||
#define LM3533_LED_DELAY2_TMAX 9781248U
|
||||
#define LM3533_LED_DELAY3_TMAX 76890112U
|
||||
|
||||
/* t_step = (t_max - t_min) / (v_max - v_min) */
|
||||
#define LM3533_LED_DELAY1_TSTEP 16384
|
||||
#define LM3533_LED_DELAY2_TSTEP 131072
|
||||
#define LM3533_LED_DELAY3_TSTEP 524288
|
||||
|
||||
/* Delay limits for hardware accelerated blinking (in ms). */
|
||||
#define LM3533_LED_DELAY_ON_MAX \
|
||||
((LM3533_LED_DELAY2_TMAX + LM3533_LED_DELAY2_TSTEP / 2) / 1000)
|
||||
#define LM3533_LED_DELAY_OFF_MAX \
|
||||
((LM3533_LED_DELAY3_TMAX + LM3533_LED_DELAY3_TSTEP / 2) / 1000)
|
||||
|
||||
/*
|
||||
* Returns linear map of *t from [t_min,t_max] to [v_min,v_max] with a step
|
||||
* size of t_step, where
|
||||
*
|
||||
* t_step = (t_max - t_min) / (v_max - v_min)
|
||||
*
|
||||
* and updates *t to reflect the mapped value.
|
||||
*/
|
||||
static u8 time_to_val(unsigned *t, unsigned t_min, unsigned t_step,
|
||||
u8 v_min, u8 v_max)
|
||||
{
|
||||
unsigned val;
|
||||
|
||||
val = (*t + t_step / 2 - t_min) / t_step + v_min;
|
||||
|
||||
*t = t_step * (val - v_min) + t_min;
|
||||
|
||||
return (u8)val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns time code corresponding to *delay (in ms) and updates *delay to
|
||||
* reflect actual hardware delay.
|
||||
*
|
||||
* Hardware supports 256 discrete delay times, divided into three groups with
|
||||
* the following ranges and step-sizes:
|
||||
*
|
||||
* [ 16, 999] [0x00, 0x3e] step 16 ms
|
||||
* [ 1130, 9781] [0x3d, 0x7f] step 131 ms
|
||||
* [10306, 76890] [0x80, 0xff] step 524 ms
|
||||
*
|
||||
* Note that delay group 3 is only available for delay_off.
|
||||
*/
|
||||
static u8 lm3533_led_get_hw_delay(unsigned *delay)
|
||||
{
|
||||
unsigned t;
|
||||
u8 val;
|
||||
|
||||
t = *delay * 1000;
|
||||
|
||||
if (t >= (LM3533_LED_DELAY2_TMAX + LM3533_LED_DELAY3_TMIN) / 2) {
|
||||
t = clamp(t, LM3533_LED_DELAY3_TMIN, LM3533_LED_DELAY3_TMAX);
|
||||
val = time_to_val(&t, LM3533_LED_DELAY3_TMIN,
|
||||
LM3533_LED_DELAY3_TSTEP,
|
||||
LM3533_LED_DELAY3_VMIN,
|
||||
LM3533_LED_DELAY3_VMAX);
|
||||
} else if (t >= (LM3533_LED_DELAY1_TMAX + LM3533_LED_DELAY2_TMIN) / 2) {
|
||||
t = clamp(t, LM3533_LED_DELAY2_TMIN, LM3533_LED_DELAY2_TMAX);
|
||||
val = time_to_val(&t, LM3533_LED_DELAY2_TMIN,
|
||||
LM3533_LED_DELAY2_TSTEP,
|
||||
LM3533_LED_DELAY2_VMIN,
|
||||
LM3533_LED_DELAY2_VMAX);
|
||||
} else {
|
||||
t = clamp(t, LM3533_LED_DELAY1_TMIN, LM3533_LED_DELAY1_TMAX);
|
||||
val = time_to_val(&t, LM3533_LED_DELAY1_TMIN,
|
||||
LM3533_LED_DELAY1_TSTEP,
|
||||
LM3533_LED_DELAY1_VMIN,
|
||||
LM3533_LED_DELAY1_VMAX);
|
||||
}
|
||||
|
||||
*delay = (t + 500) / 1000;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set delay register base to *delay (in ms) and update *delay to reflect
|
||||
* actual hardware delay used.
|
||||
*/
|
||||
static u8 lm3533_led_delay_set(struct lm3533_led *led, u8 base,
|
||||
unsigned long *delay)
|
||||
{
|
||||
unsigned t;
|
||||
u8 val;
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
t = (unsigned)*delay;
|
||||
|
||||
/* Delay group 3 is only available for low time (delay off). */
|
||||
if (base != LM3533_REG_PATTERN_LOW_TIME_BASE)
|
||||
t = min(t, LM3533_LED_DELAY2_TMAX / 1000);
|
||||
|
||||
val = lm3533_led_get_hw_delay(&t);
|
||||
|
||||
dev_dbg(led->cdev.dev, "%s - %lu: %u (0x%02x)\n", __func__,
|
||||
*delay, t, val);
|
||||
reg = lm3533_led_get_pattern_reg(led, base);
|
||||
ret = lm3533_write(led->lm3533, reg, val);
|
||||
if (ret)
|
||||
dev_err(led->cdev.dev, "failed to set delay (%02x)\n", reg);
|
||||
|
||||
*delay = t;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lm3533_led_delay_on_set(struct lm3533_led *led, unsigned long *t)
|
||||
{
|
||||
return lm3533_led_delay_set(led, LM3533_REG_PATTERN_HIGH_TIME_BASE, t);
|
||||
}
|
||||
|
||||
static int lm3533_led_delay_off_set(struct lm3533_led *led, unsigned long *t)
|
||||
{
|
||||
return lm3533_led_delay_set(led, LM3533_REG_PATTERN_LOW_TIME_BASE, t);
|
||||
}
|
||||
|
||||
static int lm3533_led_blink_set(struct led_classdev *cdev,
|
||||
unsigned long *delay_on,
|
||||
unsigned long *delay_off)
|
||||
{
|
||||
struct lm3533_led *led = to_lm3533_led(cdev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(led->cdev.dev, "%s - on = %lu, off = %lu\n", __func__,
|
||||
*delay_on, *delay_off);
|
||||
|
||||
if (*delay_on > LM3533_LED_DELAY_ON_MAX ||
|
||||
*delay_off > LM3533_LED_DELAY_OFF_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (*delay_on == 0 && *delay_off == 0) {
|
||||
*delay_on = 500;
|
||||
*delay_off = 500;
|
||||
}
|
||||
|
||||
ret = lm3533_led_delay_on_set(led, delay_on);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = lm3533_led_delay_off_set(led, delay_off);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lm3533_led_pattern_enable(led, 1);
|
||||
}
|
||||
|
||||
static ssize_t show_id(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", led->id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pattern generator rise/fall times:
|
||||
*
|
||||
* 0 - 2048 us (default)
|
||||
* 1 - 262 ms
|
||||
* 2 - 524 ms
|
||||
* 3 - 1.049 s
|
||||
* 4 - 2.097 s
|
||||
* 5 - 4.194 s
|
||||
* 6 - 8.389 s
|
||||
* 7 - 16.78 s
|
||||
*/
|
||||
static ssize_t show_risefalltime(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf, u8 base)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
ssize_t ret;
|
||||
u8 reg;
|
||||
u8 val;
|
||||
|
||||
reg = lm3533_led_get_pattern_reg(led, base);
|
||||
ret = lm3533_read(led->lm3533, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", val);
|
||||
}
|
||||
|
||||
static ssize_t show_risetime(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return show_risefalltime(dev, attr, buf,
|
||||
LM3533_REG_PATTERN_RISETIME_BASE);
|
||||
}
|
||||
|
||||
static ssize_t show_falltime(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return show_risefalltime(dev, attr, buf,
|
||||
LM3533_REG_PATTERN_FALLTIME_BASE);
|
||||
}
|
||||
|
||||
static ssize_t store_risefalltime(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len, u8 base)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
u8 val;
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
if (kstrtou8(buf, 0, &val) || val > LM3533_RISEFALLTIME_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
reg = lm3533_led_get_pattern_reg(led, base);
|
||||
ret = lm3533_write(led->lm3533, reg, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t store_risetime(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return store_risefalltime(dev, attr, buf, len,
|
||||
LM3533_REG_PATTERN_RISETIME_BASE);
|
||||
}
|
||||
|
||||
static ssize_t store_falltime(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
return store_risefalltime(dev, attr, buf, len,
|
||||
LM3533_REG_PATTERN_FALLTIME_BASE);
|
||||
}
|
||||
|
||||
static ssize_t show_als_channel(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
unsigned channel;
|
||||
u8 reg;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
|
||||
ret = lm3533_read(led->lm3533, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
channel = (val & LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK) + 1;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", channel);
|
||||
}
|
||||
|
||||
static ssize_t store_als_channel(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
unsigned channel;
|
||||
u8 reg;
|
||||
u8 val;
|
||||
u8 mask;
|
||||
int ret;
|
||||
|
||||
if (kstrtouint(buf, 0, &channel))
|
||||
return -EINVAL;
|
||||
|
||||
if (channel < LM3533_ALS_CHANNEL_LV_MIN ||
|
||||
channel > LM3533_ALS_CHANNEL_LV_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
|
||||
mask = LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK;
|
||||
val = channel - 1;
|
||||
|
||||
ret = lm3533_update(led->lm3533, reg, val, mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_als_en(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
bool enable;
|
||||
u8 reg;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
|
||||
ret = lm3533_read(led->lm3533, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
enable = val & LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", enable);
|
||||
}
|
||||
|
||||
static ssize_t store_als_en(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
unsigned enable;
|
||||
u8 reg;
|
||||
u8 mask;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (kstrtouint(buf, 0, &enable))
|
||||
return -EINVAL;
|
||||
|
||||
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
|
||||
mask = LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK;
|
||||
|
||||
if (enable)
|
||||
val = mask;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
ret = lm3533_update(led->lm3533, reg, val, mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_linear(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
u8 reg;
|
||||
u8 val;
|
||||
int linear;
|
||||
int ret;
|
||||
|
||||
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
|
||||
ret = lm3533_read(led->lm3533, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK)
|
||||
linear = 1;
|
||||
else
|
||||
linear = 0;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", linear);
|
||||
}
|
||||
|
||||
static ssize_t store_linear(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
unsigned long linear;
|
||||
u8 reg;
|
||||
u8 mask;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (kstrtoul(buf, 0, &linear))
|
||||
return -EINVAL;
|
||||
|
||||
reg = lm3533_led_get_lv_reg(led, LM3533_REG_CTRLBANK_BCONF_BASE);
|
||||
mask = LM3533_REG_CTRLBANK_BCONF_MAPPING_MASK;
|
||||
|
||||
if (linear)
|
||||
val = mask;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
ret = lm3533_update(led->lm3533, reg, val, mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = lm3533_ctrlbank_get_pwm(&led->cb, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t store_pwm(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (kstrtou8(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
ret = lm3533_ctrlbank_set_pwm(&led->cb, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static LM3533_ATTR_RW(als_channel);
|
||||
static LM3533_ATTR_RW(als_en);
|
||||
static LM3533_ATTR_RW(falltime);
|
||||
static LM3533_ATTR_RO(id);
|
||||
static LM3533_ATTR_RW(linear);
|
||||
static LM3533_ATTR_RW(pwm);
|
||||
static LM3533_ATTR_RW(risetime);
|
||||
|
||||
static struct attribute *lm3533_led_attributes[] = {
|
||||
&dev_attr_als_channel.attr,
|
||||
&dev_attr_als_en.attr,
|
||||
&dev_attr_falltime.attr,
|
||||
&dev_attr_id.attr,
|
||||
&dev_attr_linear.attr,
|
||||
&dev_attr_pwm.attr,
|
||||
&dev_attr_risetime.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t lm3533_led_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
umode_t mode = attr->mode;
|
||||
|
||||
if (attr == &dev_attr_als_channel.attr ||
|
||||
attr == &dev_attr_als_en.attr) {
|
||||
if (!led->lm3533->have_als)
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
return mode;
|
||||
};
|
||||
|
||||
static struct attribute_group lm3533_led_attribute_group = {
|
||||
.is_visible = lm3533_led_attr_is_visible,
|
||||
.attrs = lm3533_led_attributes
|
||||
};
|
||||
|
||||
static int __devinit lm3533_led_setup(struct lm3533_led *led,
|
||||
struct lm3533_led_platform_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lm3533_ctrlbank_set_max_current(&led->cb, pdata->max_current);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lm3533_ctrlbank_set_pwm(&led->cb, pdata->pwm);
|
||||
}
|
||||
|
||||
static int __devinit lm3533_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lm3533 *lm3533;
|
||||
struct lm3533_led_platform_data *pdata;
|
||||
struct lm3533_led *led;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
lm3533 = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!lm3533)
|
||||
return -EINVAL;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdev->id < 0 || pdev->id >= LM3533_LVCTRLBANK_COUNT) {
|
||||
dev_err(&pdev->dev, "illegal LED id %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
|
||||
if (!led)
|
||||
return -ENOMEM;
|
||||
|
||||
led->lm3533 = lm3533;
|
||||
led->cdev.name = pdata->name;
|
||||
led->cdev.default_trigger = pdata->default_trigger;
|
||||
led->cdev.brightness_set = lm3533_led_set;
|
||||
led->cdev.brightness_get = lm3533_led_get;
|
||||
led->cdev.blink_set = lm3533_led_blink_set;
|
||||
led->cdev.brightness = LED_OFF;
|
||||
led->id = pdev->id;
|
||||
|
||||
mutex_init(&led->mutex);
|
||||
INIT_WORK(&led->work, lm3533_led_work);
|
||||
|
||||
/* The class framework makes a callback to get brightness during
|
||||
* registration so use parent device (for error reporting) until
|
||||
* registered.
|
||||
*/
|
||||
led->cb.lm3533 = lm3533;
|
||||
led->cb.id = lm3533_led_get_ctrlbank_id(led);
|
||||
led->cb.dev = lm3533->dev;
|
||||
|
||||
platform_set_drvdata(pdev, led);
|
||||
|
||||
ret = led_classdev_register(pdev->dev.parent, &led->cdev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register LED %d\n", pdev->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
led->cb.dev = led->cdev.dev;
|
||||
|
||||
ret = sysfs_create_group(&led->cdev.dev->kobj,
|
||||
&lm3533_led_attribute_group);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to create sysfs attributes\n");
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
ret = lm3533_led_setup(led, pdata);
|
||||
if (ret)
|
||||
goto err_sysfs_remove;
|
||||
|
||||
ret = lm3533_ctrlbank_enable(&led->cb);
|
||||
if (ret)
|
||||
goto err_sysfs_remove;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sysfs_remove:
|
||||
sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
|
||||
err_unregister:
|
||||
led_classdev_unregister(&led->cdev);
|
||||
flush_work_sync(&led->work);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lm3533_led_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lm3533_led *led = platform_get_drvdata(pdev);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
lm3533_ctrlbank_disable(&led->cb);
|
||||
sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
|
||||
led_classdev_unregister(&led->cdev);
|
||||
flush_work_sync(&led->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lm3533_led_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
struct lm3533_led *led = platform_get_drvdata(pdev);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
lm3533_ctrlbank_disable(&led->cb);
|
||||
lm3533_led_set(&led->cdev, LED_OFF); /* disable blink */
|
||||
flush_work_sync(&led->work);
|
||||
}
|
||||
|
||||
static struct platform_driver lm3533_led_driver = {
|
||||
.driver = {
|
||||
.name = "lm3533-leds",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lm3533_led_probe,
|
||||
.remove = __devexit_p(lm3533_led_remove),
|
||||
.shutdown = lm3533_led_shutdown,
|
||||
};
|
||||
module_platform_driver(lm3533_led_driver);
|
||||
|
||||
MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
|
||||
MODULE_DESCRIPTION("LM3533 LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:lm3533-leds");
|
|
@ -193,9 +193,14 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
|
|||
|
||||
/* move current engine to direct mode and remember the state */
|
||||
ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Mode change requires min 500 us delay. 1 - 2 ms with margin */
|
||||
usleep_range(1000, 2000);
|
||||
ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode);
|
||||
ret = lp5521_read(client, LP5521_REG_OP_MODE, &mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* For loading, all the engines to load mode */
|
||||
lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
|
||||
|
@ -211,8 +216,7 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
|
|||
LP5521_PROG_MEM_SIZE,
|
||||
pattern);
|
||||
|
||||
ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode);
|
||||
return ret;
|
||||
return lp5521_write(client, LP5521_REG_OP_MODE, mode);
|
||||
}
|
||||
|
||||
static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr)
|
||||
|
@ -785,7 +789,7 @@ static int __devinit lp5521_probe(struct i2c_client *client,
|
|||
* LP5521_REG_ENABLE register will not have any effect - strange!
|
||||
*/
|
||||
ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
|
||||
if (buf != LP5521_REG_R_CURR_DEFAULT) {
|
||||
if (ret || buf != LP5521_REG_R_CURR_DEFAULT) {
|
||||
dev_err(&client->dev, "error in resetting chip\n");
|
||||
goto fail2;
|
||||
}
|
||||
|
|
|
@ -280,7 +280,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
|
||||
led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
|
||||
if (led == NULL) {
|
||||
dev_err(&pdev->dev, "failed to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -101,11 +101,16 @@ static const struct i2c_device_id pca955x_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pca955x_id);
|
||||
|
||||
struct pca955x_led {
|
||||
struct pca955x {
|
||||
struct mutex lock;
|
||||
struct pca955x_led *leds;
|
||||
struct pca955x_chipdef *chipdef;
|
||||
struct i2c_client *client;
|
||||
};
|
||||
|
||||
struct pca955x_led {
|
||||
struct pca955x *pca955x;
|
||||
struct work_struct work;
|
||||
spinlock_t lock;
|
||||
enum led_brightness brightness;
|
||||
struct led_classdev led_cdev;
|
||||
int led_num; /* 0 .. 15 potentially */
|
||||
|
@ -140,7 +145,7 @@ static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state)
|
|||
*/
|
||||
static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
|
||||
{
|
||||
struct pca955x_led *pca955x = i2c_get_clientdata(client);
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
|
||||
i2c_smbus_write_byte_data(client,
|
||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
|
||||
|
@ -156,7 +161,7 @@ static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
|
|||
*/
|
||||
static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
|
||||
{
|
||||
struct pca955x_led *pca955x = i2c_get_clientdata(client);
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
|
||||
i2c_smbus_write_byte_data(client,
|
||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
|
||||
|
@ -169,7 +174,7 @@ static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
|
|||
*/
|
||||
static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
|
||||
{
|
||||
struct pca955x_led *pca955x = i2c_get_clientdata(client);
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
|
||||
i2c_smbus_write_byte_data(client,
|
||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
|
||||
|
@ -182,7 +187,7 @@ static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
|
|||
*/
|
||||
static u8 pca955x_read_ls(struct i2c_client *client, int n)
|
||||
{
|
||||
struct pca955x_led *pca955x = i2c_get_clientdata(client);
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
|
||||
return (u8) i2c_smbus_read_byte_data(client,
|
||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
|
||||
|
@ -190,18 +195,23 @@ static u8 pca955x_read_ls(struct i2c_client *client, int n)
|
|||
|
||||
static void pca955x_led_work(struct work_struct *work)
|
||||
{
|
||||
struct pca955x_led *pca955x;
|
||||
struct pca955x_led *pca955x_led;
|
||||
struct pca955x *pca955x;
|
||||
u8 ls;
|
||||
int chip_ls; /* which LSx to use (0-3 potentially) */
|
||||
int ls_led; /* which set of bits within LSx to use (0-3) */
|
||||
|
||||
pca955x = container_of(work, struct pca955x_led, work);
|
||||
chip_ls = pca955x->led_num / 4;
|
||||
ls_led = pca955x->led_num % 4;
|
||||
pca955x_led = container_of(work, struct pca955x_led, work);
|
||||
pca955x = pca955x_led->pca955x;
|
||||
|
||||
chip_ls = pca955x_led->led_num / 4;
|
||||
ls_led = pca955x_led->led_num % 4;
|
||||
|
||||
mutex_lock(&pca955x->lock);
|
||||
|
||||
ls = pca955x_read_ls(pca955x->client, chip_ls);
|
||||
|
||||
switch (pca955x->brightness) {
|
||||
switch (pca955x_led->brightness) {
|
||||
case LED_FULL:
|
||||
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
|
||||
break;
|
||||
|
@ -219,12 +229,15 @@ static void pca955x_led_work(struct work_struct *work)
|
|||
* OFF, HALF, or FULL. But, this is probably better than
|
||||
* just turning off for all other values.
|
||||
*/
|
||||
pca955x_write_pwm(pca955x->client, 1, 255-pca955x->brightness);
|
||||
pca955x_write_pwm(pca955x->client, 1,
|
||||
255 - pca955x_led->brightness);
|
||||
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
|
||||
break;
|
||||
}
|
||||
|
||||
pca955x_write_ls(pca955x->client, chip_ls, ls);
|
||||
|
||||
mutex_unlock(&pca955x->lock);
|
||||
}
|
||||
|
||||
static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
|
||||
|
@ -233,7 +246,6 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
|
|||
|
||||
pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
|
||||
|
||||
spin_lock(&pca955x->lock);
|
||||
pca955x->brightness = value;
|
||||
|
||||
/*
|
||||
|
@ -241,14 +253,13 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
|
|||
* can sleep.
|
||||
*/
|
||||
schedule_work(&pca955x->work);
|
||||
|
||||
spin_unlock(&pca955x->lock);
|
||||
}
|
||||
|
||||
static int __devinit pca955x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct pca955x_led *pca955x;
|
||||
struct pca955x *pca955x;
|
||||
struct pca955x_led *pca955x_led;
|
||||
struct pca955x_chipdef *chip;
|
||||
struct i2c_adapter *adapter;
|
||||
struct led_platform_data *pdata;
|
||||
|
@ -282,39 +293,48 @@ static int __devinit pca955x_probe(struct i2c_client *client,
|
|||
}
|
||||
}
|
||||
|
||||
pca955x = kzalloc(sizeof(*pca955x) * chip->bits, GFP_KERNEL);
|
||||
pca955x = kzalloc(sizeof(*pca955x), GFP_KERNEL);
|
||||
if (!pca955x)
|
||||
return -ENOMEM;
|
||||
|
||||
pca955x->leds = kzalloc(sizeof(*pca955x_led) * chip->bits, GFP_KERNEL);
|
||||
if (!pca955x->leds) {
|
||||
err = -ENOMEM;
|
||||
goto exit_nomem;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, pca955x);
|
||||
|
||||
mutex_init(&pca955x->lock);
|
||||
pca955x->client = client;
|
||||
pca955x->chipdef = chip;
|
||||
|
||||
for (i = 0; i < chip->bits; i++) {
|
||||
pca955x[i].chipdef = chip;
|
||||
pca955x[i].client = client;
|
||||
pca955x[i].led_num = i;
|
||||
pca955x_led = &pca955x->leds[i];
|
||||
pca955x_led->led_num = i;
|
||||
pca955x_led->pca955x = pca955x;
|
||||
|
||||
/* Platform data can specify LED names and default triggers */
|
||||
if (pdata) {
|
||||
if (pdata->leds[i].name)
|
||||
snprintf(pca955x[i].name,
|
||||
sizeof(pca955x[i].name), "pca955x:%s",
|
||||
pdata->leds[i].name);
|
||||
snprintf(pca955x_led->name,
|
||||
sizeof(pca955x_led->name), "pca955x:%s",
|
||||
pdata->leds[i].name);
|
||||
if (pdata->leds[i].default_trigger)
|
||||
pca955x[i].led_cdev.default_trigger =
|
||||
pca955x_led->led_cdev.default_trigger =
|
||||
pdata->leds[i].default_trigger;
|
||||
} else {
|
||||
snprintf(pca955x[i].name, sizeof(pca955x[i].name),
|
||||
snprintf(pca955x_led->name, sizeof(pca955x_led->name),
|
||||
"pca955x:%d", i);
|
||||
}
|
||||
|
||||
spin_lock_init(&pca955x[i].lock);
|
||||
pca955x_led->led_cdev.name = pca955x_led->name;
|
||||
pca955x_led->led_cdev.brightness_set = pca955x_led_set;
|
||||
|
||||
pca955x[i].led_cdev.name = pca955x[i].name;
|
||||
pca955x[i].led_cdev.brightness_set = pca955x_led_set;
|
||||
INIT_WORK(&pca955x_led->work, pca955x_led_work);
|
||||
|
||||
INIT_WORK(&pca955x[i].work, pca955x_led_work);
|
||||
|
||||
err = led_classdev_register(&client->dev, &pca955x[i].led_cdev);
|
||||
err = led_classdev_register(&client->dev,
|
||||
&pca955x_led->led_cdev);
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
}
|
||||
|
@ -337,10 +357,12 @@ static int __devinit pca955x_probe(struct i2c_client *client,
|
|||
|
||||
exit:
|
||||
while (i--) {
|
||||
led_classdev_unregister(&pca955x[i].led_cdev);
|
||||
cancel_work_sync(&pca955x[i].work);
|
||||
led_classdev_unregister(&pca955x->leds[i].led_cdev);
|
||||
cancel_work_sync(&pca955x->leds[i].work);
|
||||
}
|
||||
|
||||
kfree(pca955x->leds);
|
||||
exit_nomem:
|
||||
kfree(pca955x);
|
||||
|
||||
return err;
|
||||
|
@ -348,14 +370,15 @@ exit:
|
|||
|
||||
static int __devexit pca955x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct pca955x_led *pca955x = i2c_get_clientdata(client);
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pca955x->chipdef->bits; i++) {
|
||||
led_classdev_unregister(&pca955x[i].led_cdev);
|
||||
cancel_work_sync(&pca955x[i].work);
|
||||
led_classdev_unregister(&pca955x->leds[i].led_cdev);
|
||||
cancel_work_sync(&pca955x->leds[i].work);
|
||||
}
|
||||
|
||||
kfree(pca955x->leds);
|
||||
kfree(pca955x);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -120,6 +120,7 @@ static void bl_trig_activate(struct led_classdev *led)
|
|||
ret = fb_register_client(&n->notifier);
|
||||
if (ret)
|
||||
dev_err(led->dev, "unable to register backlight trigger\n");
|
||||
led->activated = true;
|
||||
|
||||
return;
|
||||
|
||||
|
@ -133,10 +134,11 @@ static void bl_trig_deactivate(struct led_classdev *led)
|
|||
struct bl_trig_notifier *n =
|
||||
(struct bl_trig_notifier *) led->trigger_data;
|
||||
|
||||
if (n) {
|
||||
if (led->activated) {
|
||||
device_remove_file(led->dev, &dev_attr_inverted);
|
||||
fb_unregister_client(&n->notifier);
|
||||
kfree(n);
|
||||
led->activated = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -200,6 +200,7 @@ static void gpio_trig_activate(struct led_classdev *led)
|
|||
gpio_data->led = led;
|
||||
led->trigger_data = gpio_data;
|
||||
INIT_WORK(&gpio_data->work, gpio_trig_work);
|
||||
led->activated = true;
|
||||
|
||||
return;
|
||||
|
||||
|
@ -217,7 +218,7 @@ static void gpio_trig_deactivate(struct led_classdev *led)
|
|||
{
|
||||
struct gpio_trig_data *gpio_data = led->trigger_data;
|
||||
|
||||
if (gpio_data) {
|
||||
if (led->activated) {
|
||||
device_remove_file(led->dev, &dev_attr_gpio);
|
||||
device_remove_file(led->dev, &dev_attr_inverted);
|
||||
device_remove_file(led->dev, &dev_attr_desired_brightness);
|
||||
|
@ -225,6 +226,7 @@ static void gpio_trig_deactivate(struct led_classdev *led)
|
|||
if (gpio_data->gpio != 0)
|
||||
free_irq(gpio_to_irq(gpio_data->gpio), led);
|
||||
kfree(gpio_data);
|
||||
led->activated = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/timer.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/reboot.h>
|
||||
#include "leds.h"
|
||||
|
||||
struct heartbeat_trig_data {
|
||||
|
@ -83,15 +84,17 @@ static void heartbeat_trig_activate(struct led_classdev *led_cdev)
|
|||
led_heartbeat_function, (unsigned long) led_cdev);
|
||||
heartbeat_data->phase = 0;
|
||||
led_heartbeat_function(heartbeat_data->timer.data);
|
||||
led_cdev->activated = true;
|
||||
}
|
||||
|
||||
static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
|
||||
|
||||
if (heartbeat_data) {
|
||||
if (led_cdev->activated) {
|
||||
del_timer_sync(&heartbeat_data->timer);
|
||||
kfree(heartbeat_data);
|
||||
led_cdev->activated = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,13 +104,38 @@ static struct led_trigger heartbeat_led_trigger = {
|
|||
.deactivate = heartbeat_trig_deactivate,
|
||||
};
|
||||
|
||||
static int heartbeat_reboot_notifier(struct notifier_block *nb,
|
||||
unsigned long code, void *unused)
|
||||
{
|
||||
led_trigger_unregister(&heartbeat_led_trigger);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block heartbeat_reboot_nb = {
|
||||
.notifier_call = heartbeat_reboot_notifier,
|
||||
};
|
||||
|
||||
static struct notifier_block heartbeat_panic_nb = {
|
||||
.notifier_call = heartbeat_reboot_notifier,
|
||||
};
|
||||
|
||||
static int __init heartbeat_trig_init(void)
|
||||
{
|
||||
return led_trigger_register(&heartbeat_led_trigger);
|
||||
int rc = led_trigger_register(&heartbeat_led_trigger);
|
||||
|
||||
if (!rc) {
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&heartbeat_panic_nb);
|
||||
register_reboot_notifier(&heartbeat_reboot_nb);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit heartbeat_trig_exit(void)
|
||||
{
|
||||
unregister_reboot_notifier(&heartbeat_reboot_nb);
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list,
|
||||
&heartbeat_panic_nb);
|
||||
led_trigger_unregister(&heartbeat_led_trigger);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,21 +31,17 @@ static ssize_t led_delay_on_store(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
int ret = -EINVAL;
|
||||
char *after;
|
||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
||||
size_t count = after - buf;
|
||||
unsigned long state;
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
if (isspace(*after))
|
||||
count++;
|
||||
ret = kstrtoul(buf, 10, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (count == size) {
|
||||
led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
|
||||
led_cdev->blink_delay_on = state;
|
||||
ret = count;
|
||||
}
|
||||
led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
|
||||
led_cdev->blink_delay_on = state;
|
||||
|
||||
return ret;
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t led_delay_off_show(struct device *dev,
|
||||
|
@ -60,21 +56,17 @@ static ssize_t led_delay_off_store(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
int ret = -EINVAL;
|
||||
char *after;
|
||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
||||
size_t count = after - buf;
|
||||
unsigned long state;
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
if (isspace(*after))
|
||||
count++;
|
||||
ret = kstrtoul(buf, 10, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (count == size) {
|
||||
led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
|
||||
led_cdev->blink_delay_off = state;
|
||||
ret = count;
|
||||
}
|
||||
led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
|
||||
led_cdev->blink_delay_off = state;
|
||||
|
||||
return ret;
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
|
||||
|
@ -95,8 +87,7 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
|
|||
|
||||
led_blink_set(led_cdev, &led_cdev->blink_delay_on,
|
||||
&led_cdev->blink_delay_off);
|
||||
|
||||
led_cdev->trigger_data = (void *)1;
|
||||
led_cdev->activated = true;
|
||||
|
||||
return;
|
||||
|
||||
|
@ -106,9 +97,10 @@ err_out_delayon:
|
|||
|
||||
static void timer_trig_deactivate(struct led_classdev *led_cdev)
|
||||
{
|
||||
if (led_cdev->trigger_data) {
|
||||
if (led_cdev->activated) {
|
||||
device_remove_file(led_cdev->dev, &dev_attr_delay_on);
|
||||
device_remove_file(led_cdev->dev, &dev_attr_delay_off);
|
||||
led_cdev->activated = false;
|
||||
}
|
||||
|
||||
/* Stop blinking */
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* LED Kernel Transient Trigger
|
||||
*
|
||||
* Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
|
||||
*
|
||||
* Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
|
||||
* ledtrig-heartbeat.c
|
||||
* Design and use-case input from Jonas Bonn <jonas@southpole.se> and
|
||||
* Neil Brown <neilb@suse.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Transient trigger allows one shot timer activation. Please refer to
|
||||
* Documentation/leds/ledtrig-transient.txt for details
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/leds.h>
|
||||
#include "leds.h"
|
||||
|
||||
struct transient_trig_data {
|
||||
int activate;
|
||||
int state;
|
||||
int restore_state;
|
||||
unsigned long duration;
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
static void transient_timer_function(unsigned long data)
|
||||
{
|
||||
struct led_classdev *led_cdev = (struct led_classdev *) data;
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
|
||||
transient_data->activate = 0;
|
||||
led_set_brightness(led_cdev, transient_data->restore_state);
|
||||
}
|
||||
|
||||
static ssize_t transient_activate_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
|
||||
return sprintf(buf, "%d\n", transient_data->activate);
|
||||
}
|
||||
|
||||
static ssize_t transient_activate_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
unsigned long state;
|
||||
ssize_t ret;
|
||||
|
||||
ret = kstrtoul(buf, 10, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (state != 1 && state != 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* cancel the running timer */
|
||||
if (state == 0 && transient_data->activate == 1) {
|
||||
del_timer(&transient_data->timer);
|
||||
transient_data->activate = state;
|
||||
led_set_brightness(led_cdev, transient_data->restore_state);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* start timer if there is no active timer */
|
||||
if (state == 1 && transient_data->activate == 0 &&
|
||||
transient_data->duration != 0) {
|
||||
transient_data->activate = state;
|
||||
led_set_brightness(led_cdev, transient_data->state);
|
||||
transient_data->restore_state =
|
||||
(transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
|
||||
mod_timer(&transient_data->timer,
|
||||
jiffies + transient_data->duration);
|
||||
}
|
||||
|
||||
/* state == 0 && transient_data->activate == 0
|
||||
timer is not active - just return */
|
||||
/* state == 1 && transient_data->activate == 1
|
||||
timer is already active - just return */
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t transient_duration_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
|
||||
return sprintf(buf, "%lu\n", transient_data->duration);
|
||||
}
|
||||
|
||||
static ssize_t transient_duration_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
unsigned long state;
|
||||
ssize_t ret;
|
||||
|
||||
ret = kstrtoul(buf, 10, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
transient_data->duration = state;
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t transient_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
int state;
|
||||
|
||||
state = (transient_data->state == LED_FULL) ? 1 : 0;
|
||||
return sprintf(buf, "%d\n", state);
|
||||
}
|
||||
|
||||
static ssize_t transient_state_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
unsigned long state;
|
||||
ssize_t ret;
|
||||
|
||||
ret = kstrtoul(buf, 10, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (state != 1 && state != 0)
|
||||
return -EINVAL;
|
||||
|
||||
transient_data->state = (state == 1) ? LED_FULL : LED_OFF;
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(activate, 0644, transient_activate_show,
|
||||
transient_activate_store);
|
||||
static DEVICE_ATTR(duration, 0644, transient_duration_show,
|
||||
transient_duration_store);
|
||||
static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);
|
||||
|
||||
static void transient_trig_activate(struct led_classdev *led_cdev)
|
||||
{
|
||||
int rc;
|
||||
struct transient_trig_data *tdata;
|
||||
|
||||
tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
|
||||
if (!tdata) {
|
||||
dev_err(led_cdev->dev,
|
||||
"unable to allocate transient trigger\n");
|
||||
return;
|
||||
}
|
||||
led_cdev->trigger_data = tdata;
|
||||
|
||||
rc = device_create_file(led_cdev->dev, &dev_attr_activate);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
|
||||
rc = device_create_file(led_cdev->dev, &dev_attr_duration);
|
||||
if (rc)
|
||||
goto err_out_duration;
|
||||
|
||||
rc = device_create_file(led_cdev->dev, &dev_attr_state);
|
||||
if (rc)
|
||||
goto err_out_state;
|
||||
|
||||
setup_timer(&tdata->timer, transient_timer_function,
|
||||
(unsigned long) led_cdev);
|
||||
led_cdev->activated = true;
|
||||
|
||||
return;
|
||||
|
||||
err_out_state:
|
||||
device_remove_file(led_cdev->dev, &dev_attr_duration);
|
||||
err_out_duration:
|
||||
device_remove_file(led_cdev->dev, &dev_attr_activate);
|
||||
err_out:
|
||||
dev_err(led_cdev->dev, "unable to register transient trigger\n");
|
||||
led_cdev->trigger_data = NULL;
|
||||
kfree(tdata);
|
||||
}
|
||||
|
||||
static void transient_trig_deactivate(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct transient_trig_data *transient_data = led_cdev->trigger_data;
|
||||
|
||||
if (led_cdev->activated) {
|
||||
del_timer_sync(&transient_data->timer);
|
||||
led_set_brightness(led_cdev, transient_data->restore_state);
|
||||
device_remove_file(led_cdev->dev, &dev_attr_activate);
|
||||
device_remove_file(led_cdev->dev, &dev_attr_duration);
|
||||
device_remove_file(led_cdev->dev, &dev_attr_state);
|
||||
led_cdev->trigger_data = NULL;
|
||||
led_cdev->activated = false;
|
||||
kfree(transient_data);
|
||||
}
|
||||
}
|
||||
|
||||
static struct led_trigger transient_trigger = {
|
||||
.name = "transient",
|
||||
.activate = transient_trig_activate,
|
||||
.deactivate = transient_trig_deactivate,
|
||||
};
|
||||
|
||||
static int __init transient_trig_init(void)
|
||||
{
|
||||
return led_trigger_register(&transient_trigger);
|
||||
}
|
||||
|
||||
static void __exit transient_trig_exit(void)
|
||||
{
|
||||
led_trigger_unregister(&transient_trigger);
|
||||
}
|
||||
|
||||
module_init(transient_trig_init);
|
||||
module_exit(transient_trig_exit);
|
||||
|
||||
MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
|
||||
MODULE_DESCRIPTION("Transient LED trigger");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1104,6 +1104,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
|
|||
|
||||
mutex_init(&dev->mutex);
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
|
||||
dev->backlight_dev = backlight_device_register("toshiba",
|
||||
|
|
|
@ -620,27 +620,6 @@ config RTC_DRV_MSM6242
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-msm6242.
|
||||
|
||||
config RTC_DRV_IMXDI
|
||||
tristate "Freescale IMX DryIce Real Time Clock"
|
||||
depends on ARCH_MX25
|
||||
depends on RTC_CLASS
|
||||
help
|
||||
Support for Freescale IMX DryIce RTC
|
||||
|
||||
This driver can also be built as a module, if so, the module
|
||||
will be called "rtc-imxdi".
|
||||
|
||||
config RTC_MXC
|
||||
tristate "Freescale MXC Real Time Clock"
|
||||
depends on ARCH_MXC
|
||||
depends on RTC_CLASS
|
||||
help
|
||||
If you say yes here you get support for the Freescale MXC
|
||||
RTC module.
|
||||
|
||||
This driver can also be built as a module, if so, the module
|
||||
will be called "rtc-mxc".
|
||||
|
||||
config RTC_DRV_BQ4802
|
||||
tristate "TI BQ4802"
|
||||
help
|
||||
|
@ -738,6 +717,16 @@ config RTC_DRV_DAVINCI
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-davinci.
|
||||
|
||||
config RTC_DRV_IMXDI
|
||||
tristate "Freescale IMX DryIce Real Time Clock"
|
||||
depends on SOC_IMX25
|
||||
depends on RTC_CLASS
|
||||
help
|
||||
Support for Freescale IMX DryIce RTC
|
||||
|
||||
This driver can also be built as a module, if so, the module
|
||||
will be called "rtc-imxdi".
|
||||
|
||||
config RTC_DRV_OMAP
|
||||
tristate "TI OMAP1"
|
||||
depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
|
||||
|
@ -1087,4 +1076,15 @@ config RTC_DRV_LOONGSON1
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-ls1x.
|
||||
|
||||
config RTC_DRV_MXC
|
||||
tristate "Freescale MXC Real Time Clock"
|
||||
depends on ARCH_MXC
|
||||
depends on RTC_CLASS
|
||||
help
|
||||
If you say yes here you get support for the Freescale MXC
|
||||
RTC module.
|
||||
|
||||
This driver can also be built as a module, if so, the module
|
||||
will be called "rtc-mxc".
|
||||
|
||||
endif # RTC_CLASS
|
||||
|
|
|
@ -61,7 +61,7 @@ obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
|
|||
obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
|
||||
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
|
||||
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
|
||||
obj-$(CONFIG_RTC_MXC) += rtc-mxc.o
|
||||
obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
|
||||
obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
|
||||
|
||||
#include <linux/rtc/ds1307.h>
|
||||
|
||||
/*
|
||||
* We can't determine type by probing, but if we expect pre-Linux code
|
||||
|
@ -92,7 +91,8 @@ enum ds_type {
|
|||
# define DS1337_BIT_A2I 0x02
|
||||
# define DS1337_BIT_A1I 0x01
|
||||
#define DS1339_REG_ALARM1_SECS 0x07
|
||||
#define DS1339_REG_TRICKLE 0x10
|
||||
|
||||
#define DS13XX_TRICKLE_CHARGER_MAGIC 0xa0
|
||||
|
||||
#define RX8025_REG_CTRL1 0x0e
|
||||
# define RX8025_BIT_2412 0x20
|
||||
|
@ -124,6 +124,7 @@ struct chip_desc {
|
|||
unsigned alarm:1;
|
||||
u16 nvram_offset;
|
||||
u16 nvram_size;
|
||||
u16 trickle_charger_reg;
|
||||
};
|
||||
|
||||
static const struct chip_desc chips[last_ds_type] = {
|
||||
|
@ -140,6 +141,13 @@ static const struct chip_desc chips[last_ds_type] = {
|
|||
},
|
||||
[ds_1339] = {
|
||||
.alarm = 1,
|
||||
.trickle_charger_reg = 0x10,
|
||||
},
|
||||
[ds_1340] = {
|
||||
.trickle_charger_reg = 0x08,
|
||||
},
|
||||
[ds_1388] = {
|
||||
.trickle_charger_reg = 0x0a,
|
||||
},
|
||||
[ds_3231] = {
|
||||
.alarm = 1,
|
||||
|
@ -619,6 +627,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
|
|||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
int want_irq = false;
|
||||
unsigned char *buf;
|
||||
struct ds1307_platform_data *pdata = client->dev.platform_data;
|
||||
static const int bbsqi_bitpos[] = {
|
||||
[ds_1337] = 0,
|
||||
[ds_1339] = DS1339_BIT_BBSQI,
|
||||
|
@ -637,7 +646,10 @@ static int __devinit ds1307_probe(struct i2c_client *client,
|
|||
|
||||
ds1307->client = client;
|
||||
ds1307->type = id->driver_data;
|
||||
ds1307->offset = 0;
|
||||
|
||||
if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg)
|
||||
i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
|
||||
DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup);
|
||||
|
||||
buf = ds1307->regs;
|
||||
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
||||
|
|
|
@ -127,7 +127,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = {
|
|||
.attrs = ep93xx_rtc_attrs,
|
||||
};
|
||||
|
||||
static int __init ep93xx_rtc_probe(struct platform_device *pdev)
|
||||
static int __devinit ep93xx_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ep93xx_rtc *ep93xx_rtc;
|
||||
struct resource *res;
|
||||
|
@ -174,7 +174,7 @@ exit:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
|
||||
static int __devexit ep93xx_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev);
|
||||
|
||||
|
@ -186,31 +186,19 @@ static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:ep93xx-rtc");
|
||||
|
||||
static struct platform_driver ep93xx_rtc_driver = {
|
||||
.driver = {
|
||||
.name = "ep93xx-rtc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.remove = __exit_p(ep93xx_rtc_remove),
|
||||
.probe = ep93xx_rtc_probe,
|
||||
.remove = __devexit_p(ep93xx_rtc_remove),
|
||||
};
|
||||
|
||||
static int __init ep93xx_rtc_init(void)
|
||||
{
|
||||
return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe);
|
||||
}
|
||||
|
||||
static void __exit ep93xx_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ep93xx_rtc_driver);
|
||||
}
|
||||
module_platform_driver(ep93xx_rtc_driver);
|
||||
|
||||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
||||
MODULE_DESCRIPTION("EP93XX RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
||||
module_init(ep93xx_rtc_init);
|
||||
module_exit(ep93xx_rtc_exit);
|
||||
MODULE_ALIAS("platform:ep93xx-rtc");
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/*
|
||||
* Clock and Power control register offsets
|
||||
|
@ -386,13 +387,22 @@ static const struct dev_pm_ops lpc32xx_rtc_pm_ops = {
|
|||
#define LPC32XX_RTC_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id lpc32xx_rtc_match[] = {
|
||||
{ .compatible = "nxp,lpc3220-rtc" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lpc32xx_rtc_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver lpc32xx_rtc_driver = {
|
||||
.probe = lpc32xx_rtc_probe,
|
||||
.remove = __devexit_p(lpc32xx_rtc_remove),
|
||||
.driver = {
|
||||
.name = RTC_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = LPC32XX_RTC_PM_OPS
|
||||
.pm = LPC32XX_RTC_PM_OPS,
|
||||
.of_match_table = of_match_ptr(lpc32xx_rtc_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
|
|||
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
int tmp;
|
||||
u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
|
||||
u8 * const data = &buf[1]; /* ptr to first data byte */
|
||||
|
||||
|
@ -62,6 +63,30 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
|
||||
if (tmp < 0)
|
||||
return tmp;
|
||||
|
||||
if (tmp & M41T93_FLAG_OF) {
|
||||
dev_warn(&spi->dev, "OF bit is set, resetting.\n");
|
||||
m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
|
||||
|
||||
tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
|
||||
if (tmp < 0) {
|
||||
return tmp;
|
||||
} else if (tmp & M41T93_FLAG_OF) {
|
||||
/* OF cannot be immediately reset: oscillator has to be
|
||||
* restarted. */
|
||||
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
|
||||
|
||||
dev_warn(&spi->dev,
|
||||
"OF bit is still set, kickstarting clock.\n");
|
||||
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
|
||||
reset_osc &= ~M41T93_FLAG_ST;
|
||||
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
|
||||
}
|
||||
}
|
||||
|
||||
data[M41T93_REG_SSEC] = 0;
|
||||
data[M41T93_REG_ST_SEC] = bin2bcd(tm->tm_sec);
|
||||
data[M41T93_REG_MIN] = bin2bcd(tm->tm_min);
|
||||
|
@ -89,10 +114,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
|
|||
1. halt bit (HT) is set: the clock is running but update of readout
|
||||
registers has been disabled due to power failure. This is normal
|
||||
case after poweron. Time is valid after resetting HT bit.
|
||||
2. oscillator fail bit (OF) is set. Oscillator has be stopped and
|
||||
time is invalid:
|
||||
a) OF can be immeditely reset.
|
||||
b) OF cannot be immediately reset: oscillator has to be restarted.
|
||||
2. oscillator fail bit (OF) is set: time is invalid.
|
||||
*/
|
||||
tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
|
||||
if (tmp < 0)
|
||||
|
@ -110,21 +132,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
|
|||
|
||||
if (tmp & M41T93_FLAG_OF) {
|
||||
ret = -EINVAL;
|
||||
dev_warn(&spi->dev, "OF bit is set, resetting.\n");
|
||||
m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
|
||||
|
||||
tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
|
||||
if (tmp < 0)
|
||||
return tmp;
|
||||
else if (tmp & M41T93_FLAG_OF) {
|
||||
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
|
||||
|
||||
dev_warn(&spi->dev,
|
||||
"OF bit is still set, kickstarting clock.\n");
|
||||
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
|
||||
reset_osc &= ~M41T93_FLAG_ST;
|
||||
m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
|
||||
}
|
||||
dev_warn(&spi->dev, "OF bit is set, write time to restart.\n");
|
||||
}
|
||||
|
||||
if (tmp & M41T93_FLAG_BL)
|
||||
|
|
|
@ -64,6 +64,7 @@ struct pcf8563 {
|
|||
* 1970...2069.
|
||||
*/
|
||||
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
|
||||
int voltage_low; /* incicates if a low_voltage was detected */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -86,9 +87,11 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
|
||||
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
|
||||
pcf8563->voltage_low = 1;
|
||||
dev_info(&client->dev,
|
||||
"low voltage detected, date/time is not reliable.\n");
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
|
||||
|
@ -173,6 +176,44 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTC_INTF_DEV
|
||||
static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct rtc_time tm;
|
||||
|
||||
switch (cmd) {
|
||||
case RTC_VL_READ:
|
||||
if (pcf8563->voltage_low)
|
||||
dev_info(dev, "low voltage detected, date/time is not reliable.\n");
|
||||
|
||||
if (copy_to_user((void __user *)arg, &pcf8563->voltage_low,
|
||||
sizeof(int)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
case RTC_VL_CLR:
|
||||
/*
|
||||
* Clear the VL bit in the seconds register in case
|
||||
* the time has not been set already (which would
|
||||
* have cleared it). This does not really matter
|
||||
* because of the cached voltage_low value but do it
|
||||
* anyway for consistency.
|
||||
*/
|
||||
if (pcf8563_get_datetime(to_i2c_client(dev), &tm))
|
||||
pcf8563_set_datetime(to_i2c_client(dev), &tm);
|
||||
|
||||
/* Clear the cached value. */
|
||||
pcf8563->voltage_low = 0;
|
||||
|
||||
return 0;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define pcf8563_rtc_ioctl NULL
|
||||
#endif
|
||||
|
||||
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
return pcf8563_get_datetime(to_i2c_client(dev), tm);
|
||||
|
@ -184,6 +225,7 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
}
|
||||
|
||||
static const struct rtc_class_ops pcf8563_rtc_ops = {
|
||||
.ioctl = pcf8563_rtc_ioctl,
|
||||
.read_time = pcf8563_rtc_read_time,
|
||||
.set_time = pcf8563_rtc_set_time,
|
||||
};
|
||||
|
|
|
@ -220,17 +220,9 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id)
|
|||
unsigned long events = 0;
|
||||
|
||||
rtcmis = readl(ldata->base + RTC_MIS);
|
||||
if (rtcmis) {
|
||||
writel(rtcmis, ldata->base + RTC_ICR);
|
||||
|
||||
if (rtcmis & RTC_BIT_AI)
|
||||
events |= (RTC_AF | RTC_IRQF);
|
||||
|
||||
/* Timer interrupt is only available in ST variants */
|
||||
if ((rtcmis & RTC_BIT_PI) &&
|
||||
(ldata->hw_designer == AMBA_VENDOR_ST))
|
||||
events |= (RTC_PF | RTC_IRQF);
|
||||
|
||||
if (rtcmis & RTC_BIT_AI) {
|
||||
writel(RTC_BIT_AI, ldata->base + RTC_ICR);
|
||||
events |= (RTC_AF | RTC_IRQF);
|
||||
rtc_update_irq(ldata->rtc, 1, events);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
|
@ -670,6 +670,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
|
|||
#define s3c_rtc_resume NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
|
||||
[TYPE_S3C2410] = { TYPE_S3C2410 },
|
||||
[TYPE_S3C2416] = { TYPE_S3C2416 },
|
||||
|
@ -677,7 +678,6 @@ static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
|
|||
[TYPE_S3C64XX] = { TYPE_S3C64XX },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id s3c_rtc_dt_match[] = {
|
||||
{
|
||||
.compatible = "samsung,s3c2410-rtc",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -519,6 +520,14 @@ static void spear_rtc_shutdown(struct platform_device *pdev)
|
|||
clk_disable(config->clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id spear_rtc_id_table[] = {
|
||||
{ .compatible = "st,spear600-rtc" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, spear_rtc_id_table);
|
||||
#endif
|
||||
|
||||
static struct platform_driver spear_rtc_driver = {
|
||||
.probe = spear_rtc_probe,
|
||||
.remove = __devexit_p(spear_rtc_remove),
|
||||
|
@ -527,6 +536,7 @@ static struct platform_driver spear_rtc_driver = {
|
|||
.shutdown = spear_rtc_shutdown,
|
||||
.driver = {
|
||||
.name = "rtc-spear",
|
||||
.of_match_table = of_match_ptr(spear_rtc_id_table),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -309,7 +309,8 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
info = kzalloc(sizeof(struct tegra_rtc_info), GFP_KERNEL);
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(struct tegra_rtc_info),
|
||||
GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -317,29 +318,18 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
|
|||
if (!res) {
|
||||
dev_err(&pdev->dev,
|
||||
"Unable to allocate resources for device.\n");
|
||||
ret = -EBUSY;
|
||||
goto err_free_info;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Unable to request mem region for device.\n");
|
||||
ret = -EBUSY;
|
||||
goto err_free_info;
|
||||
info->rtc_base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!info->rtc_base) {
|
||||
dev_err(&pdev->dev, "Unable to request mem region and grab IOs for device.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
info->tegra_rtc_irq = platform_get_irq(pdev, 0);
|
||||
if (info->tegra_rtc_irq <= 0) {
|
||||
ret = -EBUSY;
|
||||
goto err_release_mem_region;
|
||||
}
|
||||
|
||||
info->rtc_base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!info->rtc_base) {
|
||||
dev_err(&pdev->dev, "Unable to grab IOs for device.\n");
|
||||
ret = -EBUSY;
|
||||
goto err_release_mem_region;
|
||||
}
|
||||
if (info->tegra_rtc_irq <= 0)
|
||||
return -EBUSY;
|
||||
|
||||
/* set context info. */
|
||||
info->pdev = pdev;
|
||||
|
@ -362,11 +352,12 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev,
|
||||
"Unable to register device (err=%d).\n",
|
||||
ret);
|
||||
goto err_iounmap;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = request_irq(info->tegra_rtc_irq, tegra_rtc_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, "rtc alarm", &pdev->dev);
|
||||
ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
|
||||
tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH,
|
||||
"rtc alarm", &pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Unable to request interrupt for device (err=%d).\n",
|
||||
|
@ -380,12 +371,6 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
|
|||
|
||||
err_dev_unreg:
|
||||
rtc_device_unregister(info->rtc_dev);
|
||||
err_iounmap:
|
||||
iounmap(info->rtc_base);
|
||||
err_release_mem_region:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_free_info:
|
||||
kfree(info);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -393,17 +378,8 @@ err_free_info:
|
|||
static int __devexit tegra_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_rtc_info *info = platform_get_drvdata(pdev);
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EBUSY;
|
||||
|
||||
free_irq(info->tegra_rtc_irq, &pdev->dev);
|
||||
rtc_device_unregister(info->rtc_dev);
|
||||
iounmap(info->rtc_base);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
kfree(info);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/mm.h>
|
||||
|
@ -363,11 +364,12 @@ static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
|
|||
|
||||
mutex_lock(&ashmem_mutex);
|
||||
list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
|
||||
struct inode *inode = range->asma->file->f_dentry->d_inode;
|
||||
loff_t start = range->pgstart * PAGE_SIZE;
|
||||
loff_t end = (range->pgend + 1) * PAGE_SIZE - 1;
|
||||
loff_t end = (range->pgend + 1) * PAGE_SIZE;
|
||||
|
||||
vmtruncate_range(inode, start, end);
|
||||
do_fallocate(range->asma->file,
|
||||
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
start, end - start);
|
||||
range->purged = ASHMEM_WAS_PURGED;
|
||||
lru_del(range);
|
||||
|
||||
|
|
|
@ -184,6 +184,18 @@ config BACKLIGHT_GENERIC
|
|||
known as the Corgi backlight driver. If you have a Sharp Zaurus
|
||||
SL-C7xx, SL-Cxx00 or SL-6000x say y.
|
||||
|
||||
config BACKLIGHT_LM3533
|
||||
tristate "Backlight Driver for LM3533"
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
depends on MFD_LM3533
|
||||
help
|
||||
Say Y to enable the backlight driver for National Semiconductor / TI
|
||||
LM3533 Lighting Power chips.
|
||||
|
||||
The backlights can be controlled directly, through PWM input, or by
|
||||
the ambient-light-sensor interface. The chip supports 256 brightness
|
||||
levels.
|
||||
|
||||
config BACKLIGHT_LOCOMO
|
||||
tristate "Sharp LOCOMO LCD/Backlight Driver"
|
||||
depends on SHARP_LOCOMO
|
||||
|
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o
|
|||
obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
|
||||
obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
|
||||
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
|
||||
|
|
|
@ -160,7 +160,7 @@ static ssize_t adp5520_store(struct device *dev, const char *buf,
|
|||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -214,7 +214,7 @@ static ssize_t adp5520_bl_daylight_max_store(struct device *dev,
|
|||
struct adp5520_bl *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
|
||||
ret = kstrtoul(buf, 10, &data->cached_daylight_max);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -222,7 +222,8 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
|
|||
struct led_info *cur_led;
|
||||
int ret, i;
|
||||
|
||||
led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
|
||||
led = devm_kzalloc(&client->dev, sizeof(*led) * pdata->num_leds,
|
||||
GFP_KERNEL);
|
||||
if (led == NULL) {
|
||||
dev_err(&client->dev, "failed to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
|
@ -236,7 +237,7 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
|
|||
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed to write\n");
|
||||
goto err_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < pdata->num_leds; ++i) {
|
||||
|
@ -291,9 +292,6 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
|
|||
cancel_work_sync(&led[i].work);
|
||||
}
|
||||
|
||||
err_free:
|
||||
kfree(led);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -309,7 +307,6 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
|
|||
cancel_work_sync(&data->led[i].work);
|
||||
}
|
||||
|
||||
kfree(data->led);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -451,7 +448,7 @@ static ssize_t adp8860_store(struct device *dev, const char *buf,
|
|||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -501,7 +498,7 @@ static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct adp8860_bl *data = dev_get_drvdata(dev);
|
||||
int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
|
||||
int ret = kstrtoul(buf, 10, &data->cached_daylight_max);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -608,7 +605,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
|
|||
uint8_t reg_val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -675,13 +672,13 @@ static int __devinit adp8860_probe(struct i2c_client *client,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = adp8860_read(client, ADP8860_MFDVID, ®_val);
|
||||
if (ret < 0)
|
||||
goto out2;
|
||||
return ret;
|
||||
|
||||
switch (ADP8860_MANID(reg_val)) {
|
||||
case ADP8863_MANUFID:
|
||||
|
@ -694,8 +691,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
|
|||
break;
|
||||
default:
|
||||
dev_err(&client->dev, "failed to probe\n");
|
||||
ret = -ENODEV;
|
||||
goto out2;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* It's confirmed that the DEVID field is actually a REVID */
|
||||
|
@ -717,8 +713,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
|
|||
&client->dev, data, &adp8860_bl_ops, &props);
|
||||
if (IS_ERR(bl)) {
|
||||
dev_err(&client->dev, "failed to register backlight\n");
|
||||
ret = PTR_ERR(bl);
|
||||
goto out2;
|
||||
return PTR_ERR(bl);
|
||||
}
|
||||
|
||||
bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
|
||||
|
@ -756,8 +751,6 @@ out:
|
|||
&adp8860_bl_attr_group);
|
||||
out1:
|
||||
backlight_device_unregister(bl);
|
||||
out2:
|
||||
kfree(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -776,7 +769,6 @@ static int __devexit adp8860_remove(struct i2c_client *client)
|
|||
&adp8860_bl_attr_group);
|
||||
|
||||
backlight_device_unregister(data->bl);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -244,8 +244,8 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
|
|||
struct led_info *cur_led;
|
||||
int ret, i;
|
||||
|
||||
|
||||
led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
|
||||
led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led),
|
||||
GFP_KERNEL);
|
||||
if (led == NULL) {
|
||||
dev_err(&client->dev, "failed to alloc memory\n");
|
||||
return -ENOMEM;
|
||||
|
@ -253,17 +253,17 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
|
|||
|
||||
ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
return ret;
|
||||
|
||||
ret = adp8870_write(client, ADP8870_ISCT1,
|
||||
(pdata->led_on_time & 0x3) << 6);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
return ret;
|
||||
|
||||
ret = adp8870_write(client, ADP8870_ISCF,
|
||||
FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
|
||||
if (ret)
|
||||
goto err_free;
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < pdata->num_leds; ++i) {
|
||||
cur_led = &pdata->leds[i];
|
||||
|
@ -317,9 +317,6 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
|
|||
cancel_work_sync(&led[i].work);
|
||||
}
|
||||
|
||||
err_free:
|
||||
kfree(led);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -335,7 +332,6 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
|
|||
cancel_work_sync(&data->led[i].work);
|
||||
}
|
||||
|
||||
kfree(data->led);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -572,7 +568,7 @@ static ssize_t adp8870_store(struct device *dev, const char *buf,
|
|||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -652,7 +648,7 @@ static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct adp8870_bl *data = dev_get_drvdata(dev);
|
||||
int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
|
||||
int ret = kstrtoul(buf, 10, &data->cached_daylight_max);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -794,7 +790,7 @@ static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
|
|||
uint8_t reg_val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -874,7 +870,7 @@ static int __devinit adp8870_probe(struct i2c_client *client,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -894,8 +890,7 @@ static int __devinit adp8870_probe(struct i2c_client *client,
|
|||
&client->dev, data, &adp8870_bl_ops, &props);
|
||||
if (IS_ERR(bl)) {
|
||||
dev_err(&client->dev, "failed to register backlight\n");
|
||||
ret = PTR_ERR(bl);
|
||||
goto out2;
|
||||
return PTR_ERR(bl);
|
||||
}
|
||||
|
||||
data->bl = bl;
|
||||
|
@ -930,8 +925,6 @@ out:
|
|||
&adp8870_bl_attr_group);
|
||||
out1:
|
||||
backlight_device_unregister(bl);
|
||||
out2:
|
||||
kfree(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -950,7 +943,6 @@ static int __devexit adp8870_remove(struct i2c_client *client)
|
|||
&adp8870_bl_attr_group);
|
||||
|
||||
backlight_device_unregister(data->bl);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -482,7 +482,7 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
|||
struct backlight_device *bd = NULL;
|
||||
struct backlight_properties props;
|
||||
|
||||
lcd = kzalloc(sizeof(struct ams369fg06), GFP_KERNEL);
|
||||
lcd = devm_kzalloc(&spi->dev, sizeof(struct ams369fg06), GFP_KERNEL);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -492,7 +492,7 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
|||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "spi setup failed.\n");
|
||||
goto out_free_lcd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
lcd->spi = spi;
|
||||
|
@ -501,15 +501,13 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
|||
lcd->lcd_pd = spi->dev.platform_data;
|
||||
if (!lcd->lcd_pd) {
|
||||
dev_err(&spi->dev, "platform data is NULL\n");
|
||||
goto out_free_lcd;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
|
||||
&ams369fg06_lcd_ops);
|
||||
if (IS_ERR(ld)) {
|
||||
ret = PTR_ERR(ld);
|
||||
goto out_free_lcd;
|
||||
}
|
||||
if (IS_ERR(ld))
|
||||
return PTR_ERR(ld);
|
||||
|
||||
lcd->ld = ld;
|
||||
|
||||
|
@ -547,8 +545,6 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
|||
|
||||
out_lcd_unregister:
|
||||
lcd_device_unregister(ld);
|
||||
out_free_lcd:
|
||||
kfree(lcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -559,7 +555,6 @@ static int __devexit ams369fg06_remove(struct spi_device *spi)
|
|||
ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
|
||||
backlight_device_unregister(lcd->bd);
|
||||
lcd_device_unregister(lcd->ld);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -619,7 +614,6 @@ static void ams369fg06_shutdown(struct spi_device *spi)
|
|||
static struct spi_driver ams369fg06_driver = {
|
||||
.driver = {
|
||||
.name = "ams369fg06",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ams369fg06_probe,
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* get at the firmware code in order to figure out what it's actually doing.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -25,6 +27,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/apple_bl.h>
|
||||
|
||||
static struct backlight_device *apple_backlight_device;
|
||||
|
||||
|
@ -39,8 +42,6 @@ struct hw_data {
|
|||
|
||||
static const struct hw_data *hw_data;
|
||||
|
||||
#define DRIVER "apple_backlight: "
|
||||
|
||||
/* Module parameters. */
|
||||
static int debug;
|
||||
module_param_named(debug, debug, int, 0644);
|
||||
|
@ -60,8 +61,7 @@ static int intel_chipset_send_intensity(struct backlight_device *bd)
|
|||
int intensity = bd->props.brightness;
|
||||
|
||||
if (debug)
|
||||
printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
|
||||
intensity);
|
||||
pr_debug("setting brightness to %d\n", intensity);
|
||||
|
||||
intel_chipset_set_brightness(intensity);
|
||||
return 0;
|
||||
|
@ -76,8 +76,7 @@ static int intel_chipset_get_intensity(struct backlight_device *bd)
|
|||
intensity = inb(0xb3) >> 4;
|
||||
|
||||
if (debug)
|
||||
printk(KERN_DEBUG DRIVER "read brightness of %d\n",
|
||||
intensity);
|
||||
pr_debug("read brightness of %d\n", intensity);
|
||||
|
||||
return intensity;
|
||||
}
|
||||
|
@ -107,8 +106,7 @@ static int nvidia_chipset_send_intensity(struct backlight_device *bd)
|
|||
int intensity = bd->props.brightness;
|
||||
|
||||
if (debug)
|
||||
printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
|
||||
intensity);
|
||||
pr_debug("setting brightness to %d\n", intensity);
|
||||
|
||||
nvidia_chipset_set_brightness(intensity);
|
||||
return 0;
|
||||
|
@ -123,8 +121,7 @@ static int nvidia_chipset_get_intensity(struct backlight_device *bd)
|
|||
intensity = inb(0x52f) >> 4;
|
||||
|
||||
if (debug)
|
||||
printk(KERN_DEBUG DRIVER "read brightness of %d\n",
|
||||
intensity);
|
||||
pr_debug("read brightness of %d\n", intensity);
|
||||
|
||||
return intensity;
|
||||
}
|
||||
|
@ -149,7 +146,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
|
|||
host = pci_get_bus_and_slot(0, 0);
|
||||
|
||||
if (!host) {
|
||||
printk(KERN_ERR DRIVER "unable to find PCI host\n");
|
||||
pr_err("unable to find PCI host\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -161,7 +158,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
|
|||
pci_dev_put(host);
|
||||
|
||||
if (!hw_data) {
|
||||
printk(KERN_ERR DRIVER "unknown hardware\n");
|
||||
pr_err("unknown hardware\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -123,7 +125,7 @@ static ssize_t backlight_store_power(struct device *dev,
|
|||
rc = -ENXIO;
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops) {
|
||||
pr_debug("backlight: set power to %lu\n", power);
|
||||
pr_debug("set power to %lu\n", power);
|
||||
if (bd->props.power != power) {
|
||||
bd->props.power = power;
|
||||
backlight_update_status(bd);
|
||||
|
@ -161,8 +163,7 @@ static ssize_t backlight_store_brightness(struct device *dev,
|
|||
if (brightness > bd->props.max_brightness)
|
||||
rc = -EINVAL;
|
||||
else {
|
||||
pr_debug("backlight: set brightness to %lu\n",
|
||||
brightness);
|
||||
pr_debug("set brightness to %lu\n", brightness);
|
||||
bd->props.brightness = brightness;
|
||||
backlight_update_status(bd);
|
||||
rc = count;
|
||||
|
@ -378,8 +379,8 @@ static int __init backlight_class_init(void)
|
|||
{
|
||||
backlight_class = class_create(THIS_MODULE, "backlight");
|
||||
if (IS_ERR(backlight_class)) {
|
||||
printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n",
|
||||
PTR_ERR(backlight_class));
|
||||
pr_warn("Unable to create backlight class; errno = %ld\n",
|
||||
PTR_ERR(backlight_class));
|
||||
return PTR_ERR(backlight_class);
|
||||
}
|
||||
|
||||
|
|
|
@ -544,7 +544,7 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
lcd = kzalloc(sizeof(struct corgi_lcd), GFP_KERNEL);
|
||||
lcd = devm_kzalloc(&spi->dev, sizeof(struct corgi_lcd), GFP_KERNEL);
|
||||
if (!lcd) {
|
||||
dev_err(&spi->dev, "failed to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
|
@ -554,10 +554,9 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
|
|||
|
||||
lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
|
||||
lcd, &corgi_lcd_ops);
|
||||
if (IS_ERR(lcd->lcd_dev)) {
|
||||
ret = PTR_ERR(lcd->lcd_dev);
|
||||
goto err_free_lcd;
|
||||
}
|
||||
if (IS_ERR(lcd->lcd_dev))
|
||||
return PTR_ERR(lcd->lcd_dev);
|
||||
|
||||
lcd->power = FB_BLANK_POWERDOWN;
|
||||
lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
|
||||
|
||||
|
@ -591,8 +590,6 @@ err_unregister_bl:
|
|||
backlight_device_unregister(lcd->bl_dev);
|
||||
err_unregister_lcd:
|
||||
lcd_device_unregister(lcd->lcd_dev);
|
||||
err_free_lcd:
|
||||
kfree(lcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -613,7 +610,6 @@ static int __devexit corgi_lcd_remove(struct spi_device *spi)
|
|||
|
||||
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
|
||||
lcd_device_unregister(lcd->lcd_dev);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
* Alan Hourihane <alanh-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -180,14 +182,13 @@ static int cr_backlight_probe(struct platform_device *pdev)
|
|||
lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
|
||||
CRVML_DEVICE_LPC, NULL);
|
||||
if (!lpc_dev) {
|
||||
printk("INTEL CARILLO RANCH LPC not found.\n");
|
||||
pr_err("INTEL CARILLO RANCH LPC not found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
|
||||
if (!(dev_en & CRVML_GPIOEN_BIT)) {
|
||||
printk(KERN_ERR
|
||||
"Carillo Ranch GPIO device was not enabled.\n");
|
||||
pr_err("Carillo Ranch GPIO device was not enabled.\n");
|
||||
pci_dev_put(lpc_dev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -270,7 +271,7 @@ static int __init cr_backlight_init(void)
|
|||
return PTR_ERR(crp);
|
||||
}
|
||||
|
||||
printk("Carillo Ranch Backlight Driver Initialized.\n");
|
||||
pr_info("Carillo Ranch Backlight Driver Initialized.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
|
|||
da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
|
||||
DA9034_WLED_ISET(pdata->output_current));
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = max_brightness;
|
||||
bl = backlight_device_register(pdev->name, data->da903x_dev, data,
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -106,7 +108,7 @@ static int genericbl_probe(struct platform_device *pdev)
|
|||
|
||||
generic_backlight_device = bd;
|
||||
|
||||
printk("Generic Backlight Driver Initialized.\n");
|
||||
pr_info("Generic Backlight Driver Initialized.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -120,7 +122,7 @@ static int genericbl_remove(struct platform_device *pdev)
|
|||
|
||||
backlight_device_unregister(bd);
|
||||
|
||||
printk("Generic Backlight Driver Unloaded\n");
|
||||
pr_info("Generic Backlight Driver Unloaded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
|
|||
|
||||
/* allocate and initialse our state */
|
||||
|
||||
ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
|
||||
ili = devm_kzalloc(&spi->dev, sizeof(struct ili9320), GFP_KERNEL);
|
||||
if (ili == NULL) {
|
||||
dev_err(dev, "no memory for device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -240,8 +240,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
|
|||
lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
|
||||
if (IS_ERR(lcd)) {
|
||||
dev_err(dev, "failed to register lcd device\n");
|
||||
ret = PTR_ERR(lcd);
|
||||
goto err_free;
|
||||
return PTR_ERR(lcd);
|
||||
}
|
||||
|
||||
ili->lcd = lcd;
|
||||
|
@ -259,9 +258,6 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
|
|||
err_unregister:
|
||||
lcd_device_unregister(lcd);
|
||||
|
||||
err_free:
|
||||
kfree(ili);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -272,7 +268,6 @@ int __devexit ili9320_remove(struct ili9320 *ili)
|
|||
ili9320_power(ili, FB_BLANK_POWERDOWN);
|
||||
|
||||
lcd_device_unregister(ili->lcd);
|
||||
kfree(ili);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fb.h>
|
||||
|
@ -38,7 +40,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
|
|||
ret = jornada_ssp_byte(GETBRIGHTNESS);
|
||||
|
||||
if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
|
||||
printk(KERN_ERR "bl : get brightness timeout\n");
|
||||
pr_err("get brightness timeout\n");
|
||||
jornada_ssp_end();
|
||||
return -ETIMEDOUT;
|
||||
} else /* exchange txdummy for value */
|
||||
|
@ -59,7 +61,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
|
|||
if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
|
||||
ret = jornada_ssp_byte(BRIGHTNESSOFF);
|
||||
if (ret != TXDUMMY) {
|
||||
printk(KERN_INFO "bl : brightness off timeout\n");
|
||||
pr_info("brightness off timeout\n");
|
||||
/* turn off backlight */
|
||||
PPSR &= ~PPC_LDD1;
|
||||
PPDR |= PPC_LDD1;
|
||||
|
@ -70,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
|
|||
|
||||
/* send command to our mcu */
|
||||
if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
|
||||
printk(KERN_INFO "bl : failed to set brightness\n");
|
||||
pr_info("failed to set brightness\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
@ -81,7 +83,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
|
|||
but due to physical layout it is equal to 0, so we simply
|
||||
invert the value (MAX VALUE - NEW VALUE). */
|
||||
if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
|
||||
printk(KERN_ERR "bl : set brightness failed\n");
|
||||
pr_err("set brightness failed\n");
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -113,7 +115,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
|
|||
|
||||
if (IS_ERR(bd)) {
|
||||
ret = PTR_ERR(bd);
|
||||
printk(KERN_ERR "bl : failed to register device, err=%x\n", ret);
|
||||
pr_err("failed to register device, err=%x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -125,7 +127,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
|
|||
jornada_bl_update_status(bd);
|
||||
|
||||
platform_set_drvdata(pdev, bd);
|
||||
printk(KERN_INFO "HP Jornada 700 series backlight driver\n");
|
||||
pr_info("HP Jornada 700 series backlight driver\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -44,7 +46,7 @@ static int jornada_lcd_get_contrast(struct lcd_device *dev)
|
|||
jornada_ssp_start();
|
||||
|
||||
if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
|
||||
printk(KERN_ERR "lcd: get contrast failed\n");
|
||||
pr_err("get contrast failed\n");
|
||||
jornada_ssp_end();
|
||||
return -ETIMEDOUT;
|
||||
} else {
|
||||
|
@ -65,7 +67,7 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
|
|||
|
||||
/* push the new value */
|
||||
if (jornada_ssp_byte(value) != TXDUMMY) {
|
||||
printk(KERN_ERR "lcd : set contrast failed\n");
|
||||
pr_err("set contrast failed\n");
|
||||
jornada_ssp_end();
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -103,7 +105,7 @@ static int jornada_lcd_probe(struct platform_device *pdev)
|
|||
|
||||
if (IS_ERR(lcd_device)) {
|
||||
ret = PTR_ERR(lcd_device);
|
||||
printk(KERN_ERR "lcd : failed to register device\n");
|
||||
pr_err("failed to register device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -159,7 +161,8 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(struct l4f00242t03_priv), GFP_KERNEL);
|
||||
priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (priv == NULL) {
|
||||
dev_err(&spi->dev, "No memory for this device.\n");
|
||||
|
@ -177,7 +180,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
|||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"Unable to get the lcd l4f00242t03 reset gpio.\n");
|
||||
goto err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_request_one(pdata->data_enable_gpio, GPIOF_OUT_INIT_LOW,
|
||||
|
@ -185,7 +188,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
|||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"Unable to get the lcd l4f00242t03 data en gpio.\n");
|
||||
goto err2;
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->io_reg = regulator_get(&spi->dev, "vdd");
|
||||
|
@ -193,7 +196,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
|||
ret = PTR_ERR(priv->io_reg);
|
||||
dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
|
||||
__func__);
|
||||
goto err3;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
priv->core_reg = regulator_get(&spi->dev, "vcore");
|
||||
|
@ -201,14 +204,14 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
|||
ret = PTR_ERR(priv->core_reg);
|
||||
dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
|
||||
__func__);
|
||||
goto err4;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
priv->ld = lcd_device_register("l4f00242t03",
|
||||
&spi->dev, priv, &l4f_ops);
|
||||
if (IS_ERR(priv->ld)) {
|
||||
ret = PTR_ERR(priv->ld);
|
||||
goto err5;
|
||||
goto err4;
|
||||
}
|
||||
|
||||
/* Init the LCD */
|
||||
|
@ -220,16 +223,14 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
|||
|
||||
return 0;
|
||||
|
||||
err5:
|
||||
regulator_put(priv->core_reg);
|
||||
err4:
|
||||
regulator_put(priv->io_reg);
|
||||
regulator_put(priv->core_reg);
|
||||
err3:
|
||||
gpio_free(pdata->data_enable_gpio);
|
||||
regulator_put(priv->io_reg);
|
||||
err2:
|
||||
gpio_free(pdata->reset_gpio);
|
||||
gpio_free(pdata->data_enable_gpio);
|
||||
err:
|
||||
kfree(priv);
|
||||
gpio_free(pdata->reset_gpio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -250,8 +251,6 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
|
|||
regulator_put(priv->io_reg);
|
||||
regulator_put(priv->core_reg);
|
||||
|
||||
kfree(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
@ -32,6 +34,8 @@ static int fb_notifier_callback(struct notifier_block *self,
|
|||
case FB_EVENT_BLANK:
|
||||
case FB_EVENT_MODE_CHANGE:
|
||||
case FB_EVENT_MODE_CHANGE_ALL:
|
||||
case FB_EARLY_EVENT_BLANK:
|
||||
case FB_R_EARLY_EVENT_BLANK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -46,6 +50,14 @@ static int fb_notifier_callback(struct notifier_block *self,
|
|||
if (event == FB_EVENT_BLANK) {
|
||||
if (ld->ops->set_power)
|
||||
ld->ops->set_power(ld, *(int *)evdata->data);
|
||||
} else if (event == FB_EARLY_EVENT_BLANK) {
|
||||
if (ld->ops->early_set_power)
|
||||
ld->ops->early_set_power(ld,
|
||||
*(int *)evdata->data);
|
||||
} else if (event == FB_R_EARLY_EVENT_BLANK) {
|
||||
if (ld->ops->r_early_set_power)
|
||||
ld->ops->r_early_set_power(ld,
|
||||
*(int *)evdata->data);
|
||||
} else {
|
||||
if (ld->ops->set_mode)
|
||||
ld->ops->set_mode(ld, evdata->data);
|
||||
|
@ -106,7 +118,7 @@ static ssize_t lcd_store_power(struct device *dev,
|
|||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->set_power) {
|
||||
pr_debug("lcd: set power to %lu\n", power);
|
||||
pr_debug("set power to %lu\n", power);
|
||||
ld->ops->set_power(ld, power);
|
||||
rc = count;
|
||||
}
|
||||
|
@ -142,7 +154,7 @@ static ssize_t lcd_store_contrast(struct device *dev,
|
|||
|
||||
mutex_lock(&ld->ops_lock);
|
||||
if (ld->ops && ld->ops->set_contrast) {
|
||||
pr_debug("lcd: set contrast to %lu\n", contrast);
|
||||
pr_debug("set contrast to %lu\n", contrast);
|
||||
ld->ops->set_contrast(ld, contrast);
|
||||
rc = count;
|
||||
}
|
||||
|
@ -253,8 +265,8 @@ static int __init lcd_class_init(void)
|
|||
{
|
||||
lcd_class = class_create(THIS_MODULE, "lcd");
|
||||
if (IS_ERR(lcd_class)) {
|
||||
printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n",
|
||||
PTR_ERR(lcd_class));
|
||||
pr_warn("Unable to create backlight class; errno = %ld\n",
|
||||
PTR_ERR(lcd_class));
|
||||
return PTR_ERR(lcd_class);
|
||||
}
|
||||
|
||||
|
|
|
@ -707,7 +707,7 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
struct backlight_device *bd = NULL;
|
||||
struct backlight_properties props;
|
||||
|
||||
lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
|
||||
lcd = devm_kzalloc(&spi->dev, sizeof(struct ld9040), GFP_KERNEL);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -717,7 +717,7 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "spi setup failed.\n");
|
||||
goto out_free_lcd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
lcd->spi = spi;
|
||||
|
@ -726,7 +726,7 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
lcd->lcd_pd = spi->dev.platform_data;
|
||||
if (!lcd->lcd_pd) {
|
||||
dev_err(&spi->dev, "platform data is NULL.\n");
|
||||
goto out_free_lcd;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
mutex_init(&lcd->lock);
|
||||
|
@ -734,13 +734,13 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
|
||||
if (ret) {
|
||||
dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
|
||||
goto out_free_lcd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
|
||||
if (IS_ERR(ld)) {
|
||||
ret = PTR_ERR(ld);
|
||||
goto out_free_lcd;
|
||||
goto out_free_regulator;
|
||||
}
|
||||
|
||||
lcd->ld = ld;
|
||||
|
@ -782,10 +782,9 @@ static int ld9040_probe(struct spi_device *spi)
|
|||
|
||||
out_unregister_lcd:
|
||||
lcd_device_unregister(lcd->ld);
|
||||
out_free_lcd:
|
||||
out_free_regulator:
|
||||
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
||||
|
||||
kfree(lcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -797,7 +796,6 @@ static int __devexit ld9040_remove(struct spi_device *spi)
|
|||
backlight_device_unregister(lcd->bd);
|
||||
lcd_device_unregister(lcd->ld);
|
||||
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -846,7 +844,6 @@ static void ld9040_shutdown(struct spi_device *spi)
|
|||
static struct spi_driver ld9040_driver = {
|
||||
.driver = {
|
||||
.name = "ld9040",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ld9040_probe,
|
||||
|
|
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
* lm3533-bl.c -- LM3533 Backlight driver
|
||||
*
|
||||
* Copyright (C) 2011-2012 Texas Instruments
|
||||
*
|
||||
* Author: Johan Hovold <jhovold@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mfd/lm3533.h>
|
||||
|
||||
|
||||
#define LM3533_HVCTRLBANK_COUNT 2
|
||||
#define LM3533_BL_MAX_BRIGHTNESS 255
|
||||
|
||||
#define LM3533_REG_CTRLBANK_AB_BCONF 0x1a
|
||||
|
||||
|
||||
struct lm3533_bl {
|
||||
struct lm3533 *lm3533;
|
||||
struct lm3533_ctrlbank cb;
|
||||
struct backlight_device *bd;
|
||||
int id;
|
||||
};
|
||||
|
||||
|
||||
static inline int lm3533_bl_get_ctrlbank_id(struct lm3533_bl *bl)
|
||||
{
|
||||
return bl->id;
|
||||
}
|
||||
|
||||
static int lm3533_bl_update_status(struct backlight_device *bd)
|
||||
{
|
||||
struct lm3533_bl *bl = bl_get_data(bd);
|
||||
int brightness = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK)
|
||||
brightness = 0;
|
||||
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
brightness = 0;
|
||||
|
||||
return lm3533_ctrlbank_set_brightness(&bl->cb, (u8)brightness);
|
||||
}
|
||||
|
||||
static int lm3533_bl_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct lm3533_bl *bl = bl_get_data(bd);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = lm3533_ctrlbank_get_brightness(&bl->cb, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static const struct backlight_ops lm3533_bl_ops = {
|
||||
.get_brightness = lm3533_bl_get_brightness,
|
||||
.update_status = lm3533_bl_update_status,
|
||||
};
|
||||
|
||||
static ssize_t show_id(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", bl->id);
|
||||
}
|
||||
|
||||
static ssize_t show_als_channel(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
unsigned channel = lm3533_bl_get_ctrlbank_id(bl);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", channel);
|
||||
}
|
||||
|
||||
static ssize_t show_als_en(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
|
||||
u8 val;
|
||||
u8 mask;
|
||||
bool enable;
|
||||
int ret;
|
||||
|
||||
ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mask = 1 << (2 * ctrlbank);
|
||||
enable = val & mask;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", enable);
|
||||
}
|
||||
|
||||
static ssize_t store_als_en(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
|
||||
int enable;
|
||||
u8 val;
|
||||
u8 mask;
|
||||
int ret;
|
||||
|
||||
if (kstrtoint(buf, 0, &enable))
|
||||
return -EINVAL;
|
||||
|
||||
mask = 1 << (2 * ctrlbank);
|
||||
|
||||
if (enable)
|
||||
val = mask;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
|
||||
mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_linear(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
u8 val;
|
||||
u8 mask;
|
||||
int linear;
|
||||
int ret;
|
||||
|
||||
ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
|
||||
|
||||
if (val & mask)
|
||||
linear = 1;
|
||||
else
|
||||
linear = 0;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", linear);
|
||||
}
|
||||
|
||||
static ssize_t store_linear(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
unsigned long linear;
|
||||
u8 mask;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (kstrtoul(buf, 0, &linear))
|
||||
return -EINVAL;
|
||||
|
||||
mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
|
||||
|
||||
if (linear)
|
||||
val = mask;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
|
||||
mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = lm3533_ctrlbank_get_pwm(&bl->cb, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t store_pwm(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (kstrtou8(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
ret = lm3533_ctrlbank_set_pwm(&bl->cb, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static LM3533_ATTR_RO(als_channel);
|
||||
static LM3533_ATTR_RW(als_en);
|
||||
static LM3533_ATTR_RO(id);
|
||||
static LM3533_ATTR_RW(linear);
|
||||
static LM3533_ATTR_RW(pwm);
|
||||
|
||||
static struct attribute *lm3533_bl_attributes[] = {
|
||||
&dev_attr_als_channel.attr,
|
||||
&dev_attr_als_en.attr,
|
||||
&dev_attr_id.attr,
|
||||
&dev_attr_linear.attr,
|
||||
&dev_attr_pwm.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t lm3533_bl_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct lm3533_bl *bl = dev_get_drvdata(dev);
|
||||
umode_t mode = attr->mode;
|
||||
|
||||
if (attr == &dev_attr_als_channel.attr ||
|
||||
attr == &dev_attr_als_en.attr) {
|
||||
if (!bl->lm3533->have_als)
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
return mode;
|
||||
};
|
||||
|
||||
static struct attribute_group lm3533_bl_attribute_group = {
|
||||
.is_visible = lm3533_bl_attr_is_visible,
|
||||
.attrs = lm3533_bl_attributes
|
||||
};
|
||||
|
||||
static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
|
||||
struct lm3533_bl_platform_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lm3533_ctrlbank_set_max_current(&bl->cb, pdata->max_current);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
|
||||
}
|
||||
|
||||
static int __devinit lm3533_bl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lm3533 *lm3533;
|
||||
struct lm3533_bl_platform_data *pdata;
|
||||
struct lm3533_bl *bl;
|
||||
struct backlight_device *bd;
|
||||
struct backlight_properties props;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
lm3533 = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!lm3533)
|
||||
return -EINVAL;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdev->id < 0 || pdev->id >= LM3533_HVCTRLBANK_COUNT) {
|
||||
dev_err(&pdev->dev, "illegal backlight id %d\n", pdev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bl = kzalloc(sizeof(*bl), GFP_KERNEL);
|
||||
if (!bl) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to allocate memory for backlight\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bl->lm3533 = lm3533;
|
||||
bl->id = pdev->id;
|
||||
|
||||
bl->cb.lm3533 = lm3533;
|
||||
bl->cb.id = lm3533_bl_get_ctrlbank_id(bl);
|
||||
bl->cb.dev = NULL; /* until registered */
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = LM3533_BL_MAX_BRIGHTNESS;
|
||||
props.brightness = pdata->default_brightness;
|
||||
bd = backlight_device_register(pdata->name, pdev->dev.parent, bl,
|
||||
&lm3533_bl_ops, &props);
|
||||
if (IS_ERR(bd)) {
|
||||
dev_err(&pdev->dev, "failed to register backlight device\n");
|
||||
ret = PTR_ERR(bd);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
bl->bd = bd;
|
||||
bl->cb.dev = &bl->bd->dev;
|
||||
|
||||
platform_set_drvdata(pdev, bl);
|
||||
|
||||
ret = sysfs_create_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to create sysfs attributes\n");
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
backlight_update_status(bd);
|
||||
|
||||
ret = lm3533_bl_setup(bl, pdata);
|
||||
if (ret)
|
||||
goto err_sysfs_remove;
|
||||
|
||||
ret = lm3533_ctrlbank_enable(&bl->cb);
|
||||
if (ret)
|
||||
goto err_sysfs_remove;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sysfs_remove:
|
||||
sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
|
||||
err_unregister:
|
||||
backlight_device_unregister(bd);
|
||||
err_free:
|
||||
kfree(bl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lm3533_bl_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lm3533_bl *bl = platform_get_drvdata(pdev);
|
||||
struct backlight_device *bd = bl->bd;
|
||||
|
||||
dev_dbg(&bd->dev, "%s\n", __func__);
|
||||
|
||||
bd->props.power = FB_BLANK_POWERDOWN;
|
||||
bd->props.brightness = 0;
|
||||
|
||||
lm3533_ctrlbank_disable(&bl->cb);
|
||||
sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
|
||||
backlight_device_unregister(bd);
|
||||
kfree(bl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int lm3533_bl_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct lm3533_bl *bl = platform_get_drvdata(pdev);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
return lm3533_ctrlbank_disable(&bl->cb);
|
||||
}
|
||||
|
||||
static int lm3533_bl_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct lm3533_bl *bl = platform_get_drvdata(pdev);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
return lm3533_ctrlbank_enable(&bl->cb);
|
||||
}
|
||||
#else
|
||||
#define lm3533_bl_suspend NULL
|
||||
#define lm3533_bl_resume NULL
|
||||
#endif
|
||||
|
||||
static void lm3533_bl_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct lm3533_bl *bl = platform_get_drvdata(pdev);
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
lm3533_ctrlbank_disable(&bl->cb);
|
||||
}
|
||||
|
||||
static struct platform_driver lm3533_bl_driver = {
|
||||
.driver = {
|
||||
.name = "lm3533-backlight",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lm3533_bl_probe,
|
||||
.remove = __devexit_p(lm3533_bl_remove),
|
||||
.shutdown = lm3533_bl_shutdown,
|
||||
.suspend = lm3533_bl_suspend,
|
||||
.resume = lm3533_bl_resume,
|
||||
};
|
||||
module_platform_driver(lm3533_bl_driver);
|
||||
|
||||
MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
|
||||
MODULE_DESCRIPTION("LM3533 Backlight driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:lm3533-backlight");
|
|
@ -168,7 +168,8 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
|
|||
goto err;
|
||||
}
|
||||
|
||||
st = kzalloc(sizeof(struct lms283gf05_state), GFP_KERNEL);
|
||||
st = devm_kzalloc(&spi->dev, sizeof(struct lms283gf05_state),
|
||||
GFP_KERNEL);
|
||||
if (st == NULL) {
|
||||
dev_err(&spi->dev, "No memory for device state\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -178,7 +179,7 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
|
|||
ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops);
|
||||
if (IS_ERR(ld)) {
|
||||
ret = PTR_ERR(ld);
|
||||
goto err2;
|
||||
goto err;
|
||||
}
|
||||
|
||||
st->spi = spi;
|
||||
|
@ -193,8 +194,6 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
|
|||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
kfree(st);
|
||||
err:
|
||||
if (pdata != NULL)
|
||||
gpio_free(pdata->reset_gpio);
|
||||
|
@ -212,8 +211,6 @@ static int __devexit lms283gf05_remove(struct spi_device *spi)
|
|||
if (pdata != NULL)
|
||||
gpio_free(pdata->reset_gpio);
|
||||
|
||||
kfree(st);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -232,23 +232,20 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
|
|||
struct lcd_device *ld;
|
||||
int ret;
|
||||
|
||||
lcd = kzalloc(sizeof(struct ltv350qv), GFP_KERNEL);
|
||||
lcd = devm_kzalloc(&spi->dev, sizeof(struct ltv350qv), GFP_KERNEL);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
lcd->spi = spi;
|
||||
lcd->power = FB_BLANK_POWERDOWN;
|
||||
lcd->buffer = kzalloc(8, GFP_KERNEL);
|
||||
if (!lcd->buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_lcd;
|
||||
}
|
||||
lcd->buffer = devm_kzalloc(&spi->dev, 8, GFP_KERNEL);
|
||||
if (!lcd->buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
ld = lcd_device_register("ltv350qv", &spi->dev, lcd, <v_ops);
|
||||
if (IS_ERR(ld)) {
|
||||
ret = PTR_ERR(ld);
|
||||
goto out_free_buffer;
|
||||
}
|
||||
if (IS_ERR(ld))
|
||||
return PTR_ERR(ld);
|
||||
|
||||
lcd->ld = ld;
|
||||
|
||||
ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK);
|
||||
|
@ -261,10 +258,6 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
|
|||
|
||||
out_unregister:
|
||||
lcd_device_unregister(ld);
|
||||
out_free_buffer:
|
||||
kfree(lcd->buffer);
|
||||
out_free_lcd:
|
||||
kfree(lcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -274,8 +267,6 @@ static int __devexit ltv350qv_remove(struct spi_device *spi)
|
|||
|
||||
ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
|
||||
lcd_device_unregister(lcd->ld);
|
||||
kfree(lcd->buffer);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -310,7 +301,6 @@ static void ltv350qv_shutdown(struct spi_device *spi)
|
|||
static struct spi_driver ltv350qv_driver = {
|
||||
.driver = {
|
||||
.name = "ltv350qv",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -168,7 +170,7 @@ static int omapbl_probe(struct platform_device *pdev)
|
|||
dev->props.brightness = pdata->default_intensity;
|
||||
omapbl_update_status(dev);
|
||||
|
||||
printk(KERN_INFO "OMAP LCD backlight initialised\n");
|
||||
pr_info("OMAP LCD backlight initialised\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
|
|||
if (!pcf_bl)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&bl_props, 0, sizeof(bl_props));
|
||||
bl_props.type = BACKLIGHT_RAW;
|
||||
bl_props.max_brightness = 0x3f;
|
||||
bl_props.power = FB_BLANK_UNBLANK;
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -68,13 +70,13 @@ static int progearbl_probe(struct platform_device *pdev)
|
|||
|
||||
pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
|
||||
if (!pmu_dev) {
|
||||
printk("ALI M7101 PMU not found.\n");
|
||||
pr_err("ALI M7101 PMU not found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
|
||||
if (!sb_dev) {
|
||||
printk("ALI 1533 SB not found.\n");
|
||||
pr_err("ALI 1533 SB not found.\n");
|
||||
ret = -ENODEV;
|
||||
goto put_pmu;
|
||||
}
|
||||
|
|
|
@ -741,7 +741,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
|||
struct backlight_device *bd = NULL;
|
||||
struct backlight_properties props;
|
||||
|
||||
lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
|
||||
lcd = devm_kzalloc(&spi->dev, sizeof(struct s6e63m0), GFP_KERNEL);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -751,7 +751,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
|||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "spi setup failed.\n");
|
||||
goto out_free_lcd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
lcd->spi = spi;
|
||||
|
@ -760,14 +760,12 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
|||
lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
|
||||
if (!lcd->lcd_pd) {
|
||||
dev_err(&spi->dev, "platform data is NULL.\n");
|
||||
goto out_free_lcd;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops);
|
||||
if (IS_ERR(ld)) {
|
||||
ret = PTR_ERR(ld);
|
||||
goto out_free_lcd;
|
||||
}
|
||||
if (IS_ERR(ld))
|
||||
return PTR_ERR(ld);
|
||||
|
||||
lcd->ld = ld;
|
||||
|
||||
|
@ -824,8 +822,6 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
|||
|
||||
out_lcd_unregister:
|
||||
lcd_device_unregister(ld);
|
||||
out_free_lcd:
|
||||
kfree(lcd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -838,7 +834,6 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
|
|||
device_remove_file(&spi->dev, &dev_attr_gamma_mode);
|
||||
backlight_device_unregister(lcd->bd);
|
||||
lcd_device_unregister(lcd->ld);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -899,7 +894,6 @@ static void s6e63m0_shutdown(struct spi_device *spi)
|
|||
static struct spi_driver s6e63m0_driver = {
|
||||
.driver = {
|
||||
.name = "s6e63m0",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = s6e63m0_probe,
|
||||
|
|
|
@ -349,7 +349,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
lcd = kzalloc(sizeof(struct tdo24m), GFP_KERNEL);
|
||||
lcd = devm_kzalloc(&spi->dev, sizeof(struct tdo24m), GFP_KERNEL);
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -357,11 +357,9 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
|||
lcd->power = FB_BLANK_POWERDOWN;
|
||||
lcd->mode = MODE_VGA; /* default to VGA */
|
||||
|
||||
lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
|
||||
if (lcd->buf == NULL) {
|
||||
kfree(lcd);
|
||||
lcd->buf = devm_kzalloc(&spi->dev, TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
|
||||
if (lcd->buf == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
m = &lcd->msg;
|
||||
x = &lcd->xfer;
|
||||
|
@ -383,15 +381,13 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
|||
break;
|
||||
default:
|
||||
dev_err(&spi->dev, "Unsupported model");
|
||||
goto out_free;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
|
||||
lcd, &tdo24m_ops);
|
||||
if (IS_ERR(lcd->lcd_dev)) {
|
||||
err = PTR_ERR(lcd->lcd_dev);
|
||||
goto out_free;
|
||||
}
|
||||
if (IS_ERR(lcd->lcd_dev))
|
||||
return PTR_ERR(lcd->lcd_dev);
|
||||
|
||||
dev_set_drvdata(&spi->dev, lcd);
|
||||
err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
|
||||
|
@ -402,9 +398,6 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
|||
|
||||
out_unregister:
|
||||
lcd_device_unregister(lcd->lcd_dev);
|
||||
out_free:
|
||||
kfree(lcd->buf);
|
||||
kfree(lcd);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -414,8 +407,6 @@ static int __devexit tdo24m_remove(struct spi_device *spi)
|
|||
|
||||
tdo24m_power(lcd, FB_BLANK_POWERDOWN);
|
||||
lcd_device_unregister(lcd->lcd_dev);
|
||||
kfree(lcd->buf);
|
||||
kfree(lcd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -82,8 +82,11 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct tosa_bl_data *data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL);
|
||||
struct tosa_bl_data *data;
|
||||
int ret = 0;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct tosa_bl_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -92,7 +95,7 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
|
|||
ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight");
|
||||
if (ret) {
|
||||
dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
|
||||
goto err_gpio_bl;
|
||||
return ret;
|
||||
}
|
||||
ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
|
||||
if (ret)
|
||||
|
@ -122,8 +125,6 @@ err_reg:
|
|||
data->bl = NULL;
|
||||
err_gpio_dir:
|
||||
gpio_free(TOSA_GPIO_BL_C20MA);
|
||||
err_gpio_bl:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -136,8 +137,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client)
|
|||
|
||||
gpio_free(TOSA_GPIO_BL_C20MA);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,8 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
|
|||
int ret;
|
||||
struct tosa_lcd_data *data;
|
||||
|
||||
data = kzalloc(sizeof(struct tosa_lcd_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&spi->dev, sizeof(struct tosa_lcd_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -187,7 +188,7 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
|
|||
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0)
|
||||
goto err_spi;
|
||||
return ret;
|
||||
|
||||
data->spi = spi;
|
||||
dev_set_drvdata(&spi->dev, data);
|
||||
|
@ -224,8 +225,6 @@ err_gpio_dir:
|
|||
gpio_free(TOSA_GPIO_TG_ON);
|
||||
err_gpio_tg:
|
||||
dev_set_drvdata(&spi->dev, NULL);
|
||||
err_spi:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -242,7 +241,6 @@ static int __devexit tosa_lcd_remove(struct spi_device *spi)
|
|||
|
||||
gpio_free(TOSA_GPIO_TG_ON);
|
||||
dev_set_drvdata(&spi->dev, NULL);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -194,6 +194,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
|
|||
data->current_brightness = 0;
|
||||
data->isink_reg = isink_reg;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = max_isel;
|
||||
bl = backlight_device_register("wm831x", &pdev->dev, data,
|
||||
|
|
|
@ -1046,20 +1046,29 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
|
|||
int
|
||||
fb_blank(struct fb_info *info, int blank)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct fb_event event;
|
||||
int ret = -EINVAL, early_ret;
|
||||
|
||||
if (blank > FB_BLANK_POWERDOWN)
|
||||
blank = FB_BLANK_POWERDOWN;
|
||||
|
||||
event.info = info;
|
||||
event.data = ␣
|
||||
|
||||
early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
|
||||
|
||||
if (info->fbops->fb_blank)
|
||||
ret = info->fbops->fb_blank(blank, info);
|
||||
|
||||
if (!ret) {
|
||||
struct fb_event event;
|
||||
|
||||
event.info = info;
|
||||
event.data = ␣
|
||||
if (!ret)
|
||||
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
|
||||
else {
|
||||
/*
|
||||
* if fb_blank is failed then revert effects of
|
||||
* the early blank event.
|
||||
*/
|
||||
if (!early_ret)
|
||||
fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -532,6 +532,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
|
|||
|
||||
/*------- Backlight control --------*/
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.fb_blank = FB_BLANK_UNBLANK;
|
||||
props.power = FB_BLANK_UNBLANK;
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
|
|
@ -292,7 +292,6 @@ static const struct inode_operations bad_inode_ops =
|
|||
.getxattr = bad_inode_getxattr,
|
||||
.listxattr = bad_inode_listxattr,
|
||||
.removexattr = bad_inode_removexattr,
|
||||
/* truncate_range returns void */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -411,12 +411,13 @@ static const struct file_operations proc_lstats_operations = {
|
|||
|
||||
static int proc_oom_score(struct task_struct *task, char *buffer)
|
||||
{
|
||||
unsigned long totalpages = totalram_pages + total_swap_pages;
|
||||
unsigned long points = 0;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
if (pid_alive(task))
|
||||
points = oom_badness(task, NULL, NULL,
|
||||
totalram_pages + total_swap_pages);
|
||||
points = oom_badness(task, NULL, NULL, totalpages) *
|
||||
1000 / totalpages;
|
||||
read_unlock(&tasklist_lock);
|
||||
return sprintf(buffer, "%lu\n", points);
|
||||
}
|
||||
|
|
|
@ -784,7 +784,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
|
|||
|
||||
/* find the first VMA at or above 'addr' */
|
||||
vma = find_vma(walk->mm, addr);
|
||||
if (pmd_trans_huge_lock(pmd, vma) == 1) {
|
||||
if (vma && pmd_trans_huge_lock(pmd, vma) == 1) {
|
||||
for (; addr != end; addr += PAGE_SIZE) {
|
||||
unsigned long offset;
|
||||
|
||||
|
|
|
@ -445,6 +445,18 @@ static inline int pmd_write(pmd_t pmd)
|
|||
#endif /* __HAVE_ARCH_PMD_WRITE */
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
#ifndef pmd_read_atomic
|
||||
static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
|
||||
{
|
||||
/*
|
||||
* Depend on compiler for an atomic pmd read. NOTE: this is
|
||||
* only going to work, if the pmdval_t isn't larger than
|
||||
* an unsigned long.
|
||||
*/
|
||||
return *pmdp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is meant to be used by sites walking pagetables with
|
||||
* the mmap_sem hold in read mode to protect against MADV_DONTNEED and
|
||||
|
@ -458,11 +470,17 @@ static inline int pmd_write(pmd_t pmd)
|
|||
* undefined so behaving like if the pmd was none is safe (because it
|
||||
* can return none anyway). The compiler level barrier() is critically
|
||||
* important to compute the two checks atomically on the same pmdval.
|
||||
*
|
||||
* For 32bit kernels with a 64bit large pmd_t this automatically takes
|
||||
* care of reading the pmd atomically to avoid SMP race conditions
|
||||
* against pmd_populate() when the mmap_sem is hold for reading by the
|
||||
* caller (a special atomic read not done by "gcc" as in the generic
|
||||
* version above, is also needed when THP is disabled because the page
|
||||
* fault can populate the pmd from under us).
|
||||
*/
|
||||
static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
|
||||
{
|
||||
/* depend on compiler for an atomic pmd read */
|
||||
pmd_t pmdval = *pmd;
|
||||
pmd_t pmdval = pmd_read_atomic(pmd);
|
||||
/*
|
||||
* The barrier will stabilize the pmdval in a register or on
|
||||
* the stack so that it will stop changing under the code.
|
||||
|
|
|
@ -225,6 +225,7 @@ header-y += kd.h
|
|||
header-y += kdev_t.h
|
||||
header-y += kernel.h
|
||||
header-y += kernelcapi.h
|
||||
header-y += kernel-page-flags.h
|
||||
header-y += keyboard.h
|
||||
header-y += keyctl.h
|
||||
header-y += l2tp.h
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef _LINUX_APPLE_BL_H
|
||||
#define _LINUX_APPLE_BL_H
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_APPLE
|
||||
#if defined(CONFIG_BACKLIGHT_APPLE) || defined(CONFIG_BACKLIGHT_APPLE_MODULE)
|
||||
|
||||
extern int apple_bl_register(void);
|
||||
extern void apple_bl_unregister(void);
|
||||
|
|
|
@ -135,9 +135,6 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
|
|||
extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
|
||||
int flags);
|
||||
|
||||
extern void *alloc_bootmem_section(unsigned long size,
|
||||
unsigned long section_nr);
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
|
||||
extern void *alloc_remap(int nid, unsigned long size);
|
||||
#else
|
||||
|
|
|
@ -30,6 +30,13 @@ struct pt_regs;
|
|||
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
|
||||
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
|
||||
|
||||
/*
|
||||
* BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the
|
||||
* expression but avoids the generation of any code, even if that expression
|
||||
* has side-effects.
|
||||
*/
|
||||
#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
|
||||
|
||||
/**
|
||||
* BUILD_BUG_ON - break compile if a condition is true.
|
||||
* @condition: the condition which the compiler should know is false.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _LINUX_COMPACTION_H
|
||||
#define _LINUX_COMPACTION_H
|
||||
|
||||
#include <linux/node.h>
|
||||
|
||||
/* Return values for compact_zone() and try_to_compact_pages() */
|
||||
/* compaction didn't start as it was not possible or direct reclaim was more suitable */
|
||||
#define COMPACT_SKIPPED 0
|
||||
|
@ -11,6 +13,23 @@
|
|||
/* The full zone was compacted */
|
||||
#define COMPACT_COMPLETE 3
|
||||
|
||||
/*
|
||||
* compaction supports three modes
|
||||
*
|
||||
* COMPACT_ASYNC_MOVABLE uses asynchronous migration and only scans
|
||||
* MIGRATE_MOVABLE pageblocks as migration sources and targets.
|
||||
* COMPACT_ASYNC_UNMOVABLE uses asynchronous migration and only scans
|
||||
* MIGRATE_MOVABLE pageblocks as migration sources.
|
||||
* MIGRATE_UNMOVABLE pageblocks are scanned as potential migration
|
||||
* targets and convers them to MIGRATE_MOVABLE if possible
|
||||
* COMPACT_SYNC uses synchronous migration and scans all pageblocks
|
||||
*/
|
||||
enum compact_mode {
|
||||
COMPACT_ASYNC_MOVABLE,
|
||||
COMPACT_ASYNC_UNMOVABLE,
|
||||
COMPACT_SYNC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMPACTION
|
||||
extern int sysctl_compact_memory;
|
||||
extern int sysctl_compaction_handler(struct ctl_table *table, int write,
|
||||
|
|
|
@ -554,6 +554,10 @@ struct fb_cursor_user {
|
|||
#define FB_EVENT_FB_UNBIND 0x0E
|
||||
/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */
|
||||
#define FB_EVENT_REMAP_ALL_CONSOLE 0x0F
|
||||
/* A hardware display blank early change occured */
|
||||
#define FB_EARLY_EVENT_BLANK 0x10
|
||||
/* A hardware display blank revert early change occured */
|
||||
#define FB_R_EARLY_EVENT_BLANK 0x11
|
||||
|
||||
struct fb_event {
|
||||
struct fb_info *info;
|
||||
|
|
|
@ -1681,7 +1681,6 @@ struct inode_operations {
|
|||
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
void (*truncate_range)(struct inode *, loff_t, loff_t);
|
||||
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
|
||||
u64 len);
|
||||
} ____cacheline_aligned;
|
||||
|
|
|
@ -59,6 +59,8 @@ extern pmd_t *page_check_address_pmd(struct page *page,
|
|||
#define HPAGE_PMD_MASK HPAGE_MASK
|
||||
#define HPAGE_PMD_SIZE HPAGE_SIZE
|
||||
|
||||
extern bool is_vma_temporary_stack(struct vm_area_struct *vma);
|
||||
|
||||
#define transparent_hugepage_enabled(__vma) \
|
||||
((transparent_hugepage_flags & \
|
||||
(1<<TRANSPARENT_HUGEPAGE_FLAG) || \
|
||||
|
|
|
@ -36,6 +36,7 @@ const char *kallsyms_lookup(unsigned long addr,
|
|||
|
||||
/* Look up a kernel symbol and return it in a text buffer. */
|
||||
extern int sprint_symbol(char *buffer, unsigned long address);
|
||||
extern int sprint_symbol_no_offset(char *buffer, unsigned long address);
|
||||
extern int sprint_backtrace(char *buffer, unsigned long address);
|
||||
|
||||
/* Look up a kernel symbol and print it to the kernel messages. */
|
||||
|
@ -80,6 +81,12 @@ static inline int sprint_symbol(char *buffer, unsigned long addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int sprint_symbol_no_offset(char *buffer, unsigned long addr)
|
||||
{
|
||||
*buffer = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sprint_backtrace(char *buffer, unsigned long addr)
|
||||
{
|
||||
*buffer = '\0';
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#define KPF_KSM 21
|
||||
#define KPF_THP 22
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* kernel hacking assistances
|
||||
* WARNING: subject to change, never rely on them!
|
||||
*/
|
||||
|
@ -44,4 +46,6 @@
|
|||
#define KPF_ARCH 38
|
||||
#define KPF_UNCACHED 39
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* LINUX_KERNEL_PAGE_FLAGS_H */
|
||||
|
|
|
@ -40,6 +40,16 @@ struct lcd_ops {
|
|||
/* Get the LCD panel power status (0: full on, 1..3: controller
|
||||
power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
|
||||
int (*get_power)(struct lcd_device *);
|
||||
/*
|
||||
* Enable or disable power to the LCD(0: on; 4: off, see FB_BLANK_XXX)
|
||||
* and this callback would be called proir to fb driver's callback.
|
||||
*
|
||||
* P.S. note that if early_set_power is not NULL then early fb notifier
|
||||
* would be registered.
|
||||
*/
|
||||
int (*early_set_power)(struct lcd_device *, int power);
|
||||
/* revert the effects of the early blank event. */
|
||||
int (*r_early_set_power)(struct lcd_device *, int power);
|
||||
/* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
|
||||
int (*set_power)(struct lcd_device *, int power);
|
||||
/* Get the current contrast setting (0-max_contrast) */
|
||||
|
|
|
@ -92,7 +92,7 @@ struct lm3530_pwm_data {
|
|||
* @als2_resistor_sel: internal resistance from ALS2 input to ground
|
||||
* @als_vmin: als input voltage calibrated for max brightness in mV
|
||||
* @als_vmax: als input voltage calibrated for min brightness in mV
|
||||
* @brt_val: brightness value (0-255)
|
||||
* @brt_val: brightness value (0-127)
|
||||
* @pwm_data: PWM control functions (only valid when the mode is PWM)
|
||||
*/
|
||||
struct lm3530_platform_data {
|
||||
|
|
|
@ -73,6 +73,8 @@ struct led_classdev {
|
|||
struct led_trigger *trigger;
|
||||
struct list_head trig_list;
|
||||
void *trigger_data;
|
||||
/* true if activated - deactivate routine uses it to do cleanup */
|
||||
bool activated;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue