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
161 changed files with 4688 additions and 2543 deletions
|
@ -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
|
65
Documentation/ABI/testing/sysfs-class-led-driver-lm3533
Normal file
65
Documentation/ABI/testing/sysfs-class-led-driver-lm3533
Normal file
|
@ -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
|
page will eventually get charged for it (once it is uncharged from
|
||||||
the cgroup that brought it in -- this will happen on memory pressure).
|
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.
|
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
|
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
|
be backed into memory in force, charges for pages are accounted against the
|
||||||
caller of swapoff rather than the users of shmem.
|
caller of swapoff rather than the users of shmem.
|
||||||
|
|
||||||
|
|
||||||
2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP)
|
2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP)
|
||||||
|
|
||||||
Swap Extension allows you to record charge for swap. A swapped-in page is
|
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
|
tasks have migrated away from it. (because we charge against pages, not
|
||||||
against tasks.)
|
against tasks.)
|
||||||
|
|
||||||
Such charges are freed or moved to their parent. At moving, both of RSS
|
We move the stats to root (if use_hierarchy==0) or parent (if
|
||||||
and CACHES are moved to parent.
|
use_hierarchy==1), and no change on the charge except uncharging
|
||||||
rmdir() may return -EBUSY if freeing/moving fails. See 5.1 also.
|
from the child.
|
||||||
|
|
||||||
Charges recorded in swap information is not updated at removal of cgroup.
|
Charges recorded in swap information is not updated at removal of cgroup.
|
||||||
Recorded information is discarded and a cgroup which uses swap (swapcache)
|
Recorded information is discarded and a cgroup which uses swap (swapcache)
|
||||||
will be charged as a new owner of it.
|
will be charged as a new owner of it.
|
||||||
|
|
||||||
|
About use_hierarchy, see Section 6.
|
||||||
|
|
||||||
5. Misc. interfaces.
|
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.
|
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
|
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
|
moved to parent(if use_hierarchy==1) or root (if use_hierarchy==0) and this
|
||||||
VM is too busy to free/move all pages immediately.
|
cgroup will be empty.
|
||||||
|
|
||||||
Typical use case of this interface is that calling this before rmdir().
|
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
|
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.
|
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
|
5.2 stat file
|
||||||
|
|
||||||
memory.stat file includes following statistics
|
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
|
hierarchical_memsw_limit - # of bytes of memory+swap limit with regard to
|
||||||
hierarchy under which memory cgroup is.
|
hierarchy under which memory cgroup is.
|
||||||
|
|
||||||
total_cache - sum of all children's "cache"
|
total_<counter> - # hierarchical version of <counter>, which in
|
||||||
total_rss - sum of all children's "rss"
|
addition to the cgroup's own value includes the
|
||||||
total_mapped_file - sum of all children's "cache"
|
sum of all hierarchical children's values of
|
||||||
total_pgpgin - sum of all children's "pgpgin"
|
<counter>, i.e. total_cache
|
||||||
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"
|
|
||||||
|
|
||||||
# The following additional stats are dependent on CONFIG_DEBUG_VM.
|
# The following additional stats are dependent on CONFIG_DEBUG_VM.
|
||||||
|
|
||||||
|
@ -622,8 +620,7 @@ memory cgroup.
|
||||||
bit | what type of charges would be moved ?
|
bit | what type of charges would be moved ?
|
||||||
-----+------------------------------------------------------------------------
|
-----+------------------------------------------------------------------------
|
||||||
0 | A charge of an anonymous page(or swap of it) used by the target task.
|
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
|
| You must enable Swap Extension(see 2.4) to enable move of swap charges.
|
||||||
| 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)
|
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
|
| and swaps of tmpfs file) mmapped by the target task. Unlike the case of
|
||||||
|
@ -636,8 +633,6 @@ memory cgroup.
|
||||||
|
|
||||||
8.3 TODO
|
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
|
- 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.
|
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.
|
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
|
2.1 Other accounting routines
|
||||||
|
|
||||||
There are more routines that may help you with common needs, like
|
There are more routines that may help you with common needs, like
|
||||||
|
|
15
Documentation/devicetree/bindings/rtc/lpc32xx-rtc.txt
Normal file
15
Documentation/devicetree/bindings/rtc/lpc32xx-rtc.txt
Normal file
|
@ -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>;
|
||||||
|
};
|
17
Documentation/devicetree/bindings/rtc/spear-rtc.txt
Normal file
17
Documentation/devicetree/bindings/rtc/spear-rtc.txt
Normal file
|
@ -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 (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||||
int (*removexattr) (struct dentry *, const char *);
|
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);
|
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
|
||||||
|
|
||||||
locking rules:
|
locking rules:
|
||||||
|
@ -87,7 +86,6 @@ setxattr: yes
|
||||||
getxattr: no
|
getxattr: no
|
||||||
listxattr: no
|
listxattr: no
|
||||||
removexattr: yes
|
removexattr: yes
|
||||||
truncate_range: yes
|
|
||||||
fiemap: no
|
fiemap: no
|
||||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||||
victim.
|
victim.
|
||||||
|
|
|
@ -743,6 +743,7 @@ Committed_AS: 100056 kB
|
||||||
VmallocTotal: 112216 kB
|
VmallocTotal: 112216 kB
|
||||||
VmallocUsed: 428 kB
|
VmallocUsed: 428 kB
|
||||||
VmallocChunk: 111088 kB
|
VmallocChunk: 111088 kB
|
||||||
|
AnonHugePages: 49152 kB
|
||||||
|
|
||||||
MemTotal: Total usable ram (i.e. physical ram minus a few reserved
|
MemTotal: Total usable ram (i.e. physical ram minus a few reserved
|
||||||
bits and the kernel binary code)
|
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
|
Dirty: Memory which is waiting to get written back to the disk
|
||||||
Writeback: Memory which is actively being 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
|
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
|
Mapped: files which have been mmaped, such as libraries
|
||||||
Slab: in-kernel data structures cache
|
Slab: in-kernel data structures cache
|
||||||
SReclaimable: Part of Slab, that might be reclaimed, such as caches
|
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 (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||||
int (*removexattr) (struct dentry *, const char *);
|
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
|
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
|
removexattr: called by the VFS to remove an extended attribute from
|
||||||
a file. This method is called by removexattr(2) system call.
|
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
|
The Address Space Object
|
||||||
========================
|
========================
|
||||||
|
@ -760,7 +756,7 @@ struct file_operations
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
This describes how the VFS can manipulate an open file. As of kernel
|
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 file_operations {
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
|
@ -790,6 +786,8 @@ struct file_operations {
|
||||||
int (*flock) (struct file *, int, struct file_lock *);
|
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_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);
|
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
|
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
|
splice_read: called by the VFS to splice data from file to a pipe. This
|
||||||
method is used by the splice(2) system call
|
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
|
Note that the file operations are implemented by the specific
|
||||||
filesystem in which the inode resides. When opening a device node
|
filesystem in which the inode resides. When opening a device node
|
||||||
(character or block special) most filesystems will call special
|
(character or block special) most filesystems will call special
|
||||||
|
|
152
Documentation/leds/ledtrig-transient.txt
Normal file
152
Documentation/leds/ledtrig-transient.txt
Normal file
|
@ -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
|
application that could have been using hugepages. This also applies to
|
||||||
the regions registered in khugepaged.
|
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 ==
|
||||||
|
|
||||||
get_user_pages and follow_page if run on a hugepage, will return the
|
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
|
F: include/linux/hrtimer.h
|
||||||
|
|
||||||
HIGH-SPEED SCC DRIVER FOR AX.25
|
HIGH-SPEED SCC DRIVER FOR AX.25
|
||||||
M: Klaus Kudielka <klaus.kudielka@ieee.org>
|
|
||||||
L: linux-hams@vger.kernel.org
|
L: linux-hams@vger.kernel.org
|
||||||
W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/
|
S: Orphan
|
||||||
S: Maintained
|
|
||||||
F: drivers/net/hamradio/dmascc.c
|
F: drivers/net/hamradio/dmascc.c
|
||||||
F: drivers/net/hamradio/scc.c
|
F: drivers/net/hamradio/scc.c
|
||||||
|
|
||||||
|
@ -4511,12 +4509,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/mmc/host/imxmmc.*
|
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
|
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
|
||||||
M: Jiri Slaby <jirislaby@gmail.com>
|
M: Jiri Slaby <jirislaby@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
|
@ -173,7 +173,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
|
||||||
CONFIG_RTC_CLASS=y
|
CONFIG_RTC_CLASS=y
|
||||||
CONFIG_RTC_DRV_PCF8563=y
|
CONFIG_RTC_DRV_PCF8563=y
|
||||||
CONFIG_RTC_DRV_IMXDI=y
|
CONFIG_RTC_DRV_IMXDI=y
|
||||||
CONFIG_RTC_MXC=y
|
CONFIG_RTC_DRV_MXC=y
|
||||||
CONFIG_DMADEVICES=y
|
CONFIG_DMADEVICES=y
|
||||||
CONFIG_IMX_SDMA=y
|
CONFIG_IMX_SDMA=y
|
||||||
CONFIG_IMX_DMA=y
|
CONFIG_IMX_DMA=y
|
||||||
|
|
|
@ -178,7 +178,7 @@ CONFIG_NEW_LEDS=y
|
||||||
CONFIG_LEDS_CLASS=y
|
CONFIG_LEDS_CLASS=y
|
||||||
CONFIG_RTC_CLASS=y
|
CONFIG_RTC_CLASS=y
|
||||||
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
|
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
|
||||||
CONFIG_RTC_MXC=y
|
CONFIG_RTC_DRV_MXC=y
|
||||||
CONFIG_DMADEVICES=y
|
CONFIG_DMADEVICES=y
|
||||||
CONFIG_IMX_SDMA=y
|
CONFIG_IMX_SDMA=y
|
||||||
CONFIG_EXT2_FS=y
|
CONFIG_EXT2_FS=y
|
||||||
|
|
|
@ -40,6 +40,7 @@ config CRIS
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
select HAVE_IDE
|
select HAVE_IDE
|
||||||
|
select GENERIC_ATOMIC64
|
||||||
select HAVE_GENERIC_HARDIRQS
|
select HAVE_GENERIC_HARDIRQS
|
||||||
select GENERIC_IRQ_SHOW
|
select GENERIC_IRQ_SHOW
|
||||||
select GENERIC_IOMAP
|
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;
|
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)
|
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||||
{
|
{
|
||||||
set_64bit((unsigned long long *)(ptep), native_pte_val(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;
|
int x = e820x->nr_map;
|
||||||
|
|
||||||
if (x >= ARRAY_SIZE(e820x->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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,19 +135,19 @@ static void __init e820_print_type(u32 type)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case E820_RAM:
|
case E820_RAM:
|
||||||
case E820_RESERVED_KERN:
|
case E820_RESERVED_KERN:
|
||||||
printk(KERN_CONT "(usable)");
|
printk(KERN_CONT "usable");
|
||||||
break;
|
break;
|
||||||
case E820_RESERVED:
|
case E820_RESERVED:
|
||||||
printk(KERN_CONT "(reserved)");
|
printk(KERN_CONT "reserved");
|
||||||
break;
|
break;
|
||||||
case E820_ACPI:
|
case E820_ACPI:
|
||||||
printk(KERN_CONT "(ACPI data)");
|
printk(KERN_CONT "ACPI data");
|
||||||
break;
|
break;
|
||||||
case E820_NVS:
|
case E820_NVS:
|
||||||
printk(KERN_CONT "(ACPI NVS)");
|
printk(KERN_CONT "ACPI NVS");
|
||||||
break;
|
break;
|
||||||
case E820_UNUSABLE:
|
case E820_UNUSABLE:
|
||||||
printk(KERN_CONT "(unusable)");
|
printk(KERN_CONT "unusable");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_CONT "type %u", type);
|
printk(KERN_CONT "type %u", type);
|
||||||
|
@ -158,10 +160,10 @@ void __init e820_print_map(char *who)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < e820.nr_map; 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,
|
||||||
(unsigned long long)
|
(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);
|
e820_print_type(e820.map[i].type);
|
||||||
printk(KERN_CONT "\n");
|
printk(KERN_CONT "\n");
|
||||||
}
|
}
|
||||||
|
@ -428,9 +430,8 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
|
||||||
size = ULLONG_MAX - start;
|
size = ULLONG_MAX - start;
|
||||||
|
|
||||||
end = start + size;
|
end = start + size;
|
||||||
printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ",
|
printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ",
|
||||||
(unsigned long long) start,
|
(unsigned long long) start, (unsigned long long) (end - 1));
|
||||||
(unsigned long long) end);
|
|
||||||
e820_print_type(old_type);
|
e820_print_type(old_type);
|
||||||
printk(KERN_CONT " ==> ");
|
printk(KERN_CONT " ==> ");
|
||||||
e820_print_type(new_type);
|
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;
|
size = ULLONG_MAX - start;
|
||||||
|
|
||||||
end = start + size;
|
end = start + size;
|
||||||
printk(KERN_DEBUG "e820 remove range: %016Lx - %016Lx ",
|
printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ",
|
||||||
(unsigned long long) start,
|
(unsigned long long) start, (unsigned long long) (end - 1));
|
||||||
(unsigned long long) end);
|
|
||||||
if (checktype)
|
if (checktype)
|
||||||
e820_print_type(old_type);
|
e820_print_type(old_type);
|
||||||
printk(KERN_CONT "\n");
|
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))
|
if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
|
||||||
return;
|
return;
|
||||||
e820.nr_map = nr_map;
|
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");
|
e820_print_map("modified");
|
||||||
}
|
}
|
||||||
static void __init update_e820_saved(void)
|
static void __init update_e820_saved(void)
|
||||||
|
@ -637,8 +637,8 @@ __init void e820_setup_gap(void)
|
||||||
if (!found) {
|
if (!found) {
|
||||||
gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
|
gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"PCI: Warning: Cannot find a gap in the 32bit address range\n"
|
"e820: cannot find a gap in the 32bit address range\n"
|
||||||
"PCI: Unassigned devices with 32bit resource registers may break!\n");
|
"e820: PCI devices with unassigned 32bit BARs may break!\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -648,8 +648,8 @@ __init void e820_setup_gap(void)
|
||||||
pci_mem_start = gapstart;
|
pci_mem_start = gapstart;
|
||||||
|
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
|
"e820: [mem %#010lx-%#010lx] available for PCI devices\n",
|
||||||
pci_mem_start, gapstart, gapsize);
|
gapstart, gapstart + gapsize - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -667,7 +667,7 @@ void __init parse_e820_ext(struct setup_data *sdata)
|
||||||
extmap = (struct e820entry *)(sdata->data);
|
extmap = (struct e820entry *)(sdata->data);
|
||||||
__append_e820_map(extmap, entries);
|
__append_e820_map(extmap, entries);
|
||||||
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
|
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");
|
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);
|
addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
|
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();
|
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)
|
if (last_pfn > max_arch_pfn)
|
||||||
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);
|
last_pfn, max_arch_pfn);
|
||||||
return last_pfn;
|
return last_pfn;
|
||||||
}
|
}
|
||||||
|
@ -888,7 +888,7 @@ void __init finish_e820_parsing(void)
|
||||||
early_panic("Invalid user supplied memory map");
|
early_panic("Invalid user supplied memory map");
|
||||||
e820.nr_map = nr;
|
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");
|
e820_print_map("user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -996,8 +996,9 @@ void __init e820_reserve_resources_late(void)
|
||||||
end = MAX_RESOURCE_SIZE;
|
end = MAX_RESOURCE_SIZE;
|
||||||
if (start >= end)
|
if (start >= end)
|
||||||
continue;
|
continue;
|
||||||
printk(KERN_DEBUG "reserve RAM buffer: %016llx - %016llx ",
|
printk(KERN_DEBUG
|
||||||
start, end);
|
"e820: reserve RAM buffer [mem %#010llx-%#010llx]\n",
|
||||||
|
start, end);
|
||||||
reserve_region_with_split(&iomem_resource, start, end,
|
reserve_region_with_split(&iomem_resource, start, end,
|
||||||
"RAM buffer");
|
"RAM buffer");
|
||||||
}
|
}
|
||||||
|
@ -1047,7 +1048,7 @@ void __init setup_memory_map(void)
|
||||||
|
|
||||||
who = x86_init.resources.memory_setup();
|
who = x86_init.resources.memory_setup();
|
||||||
memcpy(&e820_saved, &e820, sizeof(struct e820map));
|
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);
|
e820_print_map(who);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -568,8 +568,8 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
||||||
struct mpf_intel *mpf;
|
struct mpf_intel *mpf;
|
||||||
unsigned long mem;
|
unsigned long mem;
|
||||||
|
|
||||||
apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
|
apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n",
|
||||||
bp, length);
|
base, base + length - 1);
|
||||||
BUILD_BUG_ON(sizeof(*mpf) != 16);
|
BUILD_BUG_ON(sizeof(*mpf) != 16);
|
||||||
|
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
|
@ -584,8 +584,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
||||||
#endif
|
#endif
|
||||||
mpf_found = mpf;
|
mpf_found = mpf;
|
||||||
|
|
||||||
printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
|
printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
|
||||||
mpf, (u64)virt_to_phys(mpf));
|
(unsigned long long) virt_to_phys(mpf),
|
||||||
|
(unsigned long long) virt_to_phys(mpf) +
|
||||||
|
sizeof(*mpf) - 1, mpf);
|
||||||
|
|
||||||
mem = virt_to_phys(mpf);
|
mem = virt_to_phys(mpf);
|
||||||
memblock_reserve(mem, sizeof(*mpf));
|
memblock_reserve(mem, sizeof(*mpf));
|
||||||
|
|
|
@ -334,8 +334,8 @@ static void __init relocate_initrd(void)
|
||||||
memblock_reserve(ramdisk_here, area_size);
|
memblock_reserve(ramdisk_here, area_size);
|
||||||
initrd_start = ramdisk_here + PAGE_OFFSET;
|
initrd_start = ramdisk_here + PAGE_OFFSET;
|
||||||
initrd_end = initrd_start + ramdisk_size;
|
initrd_end = initrd_start + ramdisk_size;
|
||||||
printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
|
printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
|
||||||
ramdisk_here, ramdisk_here + ramdisk_size);
|
ramdisk_here, ramdisk_here + ramdisk_size - 1);
|
||||||
|
|
||||||
q = (char *)initrd_start;
|
q = (char *)initrd_start;
|
||||||
|
|
||||||
|
@ -366,8 +366,8 @@ static void __init relocate_initrd(void)
|
||||||
/* high pages is not converted by early_res_to_bootmem */
|
/* high pages is not converted by early_res_to_bootmem */
|
||||||
ramdisk_image = boot_params.hdr.ramdisk_image;
|
ramdisk_image = boot_params.hdr.ramdisk_image;
|
||||||
ramdisk_size = boot_params.hdr.ramdisk_size;
|
ramdisk_size = boot_params.hdr.ramdisk_size;
|
||||||
printk(KERN_INFO "Move RAMDISK from %016llx - %016llx to"
|
printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
|
||||||
" %08llx - %08llx\n",
|
" [mem %#010llx-%#010llx]\n",
|
||||||
ramdisk_image, ramdisk_image + ramdisk_size - 1,
|
ramdisk_image, ramdisk_image + ramdisk_size - 1,
|
||||||
ramdisk_here, ramdisk_here + 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);
|
ramdisk_size, end_of_lowmem>>1);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "RAMDISK: %08llx - %08llx\n", ramdisk_image,
|
printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
|
||||||
ramdisk_end);
|
ramdisk_end - 1);
|
||||||
|
|
||||||
|
|
||||||
if (ramdisk_end <= end_of_lowmem) {
|
if (ramdisk_end <= end_of_lowmem) {
|
||||||
|
@ -906,8 +906,8 @@ void __init setup_arch(char **cmdline_p)
|
||||||
setup_bios_corruption_check();
|
setup_bios_corruption_check();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
|
printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
|
||||||
max_pfn_mapped<<PAGE_SHIFT);
|
(max_pfn_mapped<<PAGE_SHIFT) - 1);
|
||||||
|
|
||||||
setup_trampolines();
|
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_end = pgt_buf_start;
|
||||||
pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
|
pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
|
||||||
|
|
||||||
printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
|
printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
|
||||||
end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
|
end - 1, pgt_buf_start << PAGE_SHIFT,
|
||||||
|
(pgt_buf_top << PAGE_SHIFT) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init native_pagetable_reserve(u64 start, u64 end)
|
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 nr_range, i;
|
||||||
int use_pse, use_gbpages;
|
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)
|
#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++)
|
for (i = 0; i < nr_range; i++)
|
||||||
printk(KERN_DEBUG " %010lx - %010lx page %s\n",
|
printk(KERN_DEBUG " [mem %#010lx-%#010lx] page %s\n",
|
||||||
mr[i].start, mr[i].end,
|
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_1G))?"1G":(
|
||||||
(mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
|
(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:
|
* create a kernel page fault:
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||||
printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
|
printk(KERN_INFO "debug: unmapping init [mem %#010lx-%#010lx]\n",
|
||||||
begin, end);
|
begin, end - 1);
|
||||||
set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
|
set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -141,8 +141,8 @@ static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
|
||||||
|
|
||||||
/* whine about and ignore invalid blks */
|
/* whine about and ignore invalid blks */
|
||||||
if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
|
if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
|
||||||
pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
|
pr_warning("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
|
||||||
nid, start, end);
|
nid, start, end - 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,8 +210,8 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
|
||||||
|
|
||||||
start = roundup(start, ZONE_ALIGN);
|
start = roundup(start, ZONE_ALIGN);
|
||||||
|
|
||||||
printk(KERN_INFO "Initmem setup node %d %016Lx-%016Lx\n",
|
printk(KERN_INFO "Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
|
||||||
nid, start, end);
|
nid, start, end - 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate node data. Try remap allocator first, node-local
|
* 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 */
|
/* 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)" : "");
|
nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : "");
|
||||||
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
|
||||||
if (!remapped && tnid != nid)
|
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->end > bj->start && bi->start < bj->end) {
|
||||||
if (bi->nid != bj->nid) {
|
if (bi->nid != bj->nid) {
|
||||||
pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
|
pr_err("NUMA: node %d [mem %#010Lx-%#010Lx] overlaps with node %d [mem %#010Lx-%#010Lx]\n",
|
||||||
bi->nid, bi->start, bi->end,
|
bi->nid, bi->start, bi->end - 1,
|
||||||
bj->nid, bj->start, bj->end);
|
bj->nid, bj->start, bj->end - 1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
|
pr_warning("NUMA: Warning: node %d [mem %#010Lx-%#010Lx] overlaps with itself [mem %#010Lx-%#010Lx]\n",
|
||||||
bi->nid, bi->start, bi->end,
|
bi->nid, bi->start, bi->end - 1,
|
||||||
bj->start, bj->end);
|
bj->start, bj->end - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -320,9 +320,9 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
|
||||||
}
|
}
|
||||||
if (k < mi->nr_blks)
|
if (k < mi->nr_blks)
|
||||||
continue;
|
continue;
|
||||||
printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%Lx,%Lx)\n",
|
printk(KERN_INFO "NUMA: Node %d [mem %#010Lx-%#010Lx] + [mem %#010Lx-%#010Lx] -> [mem %#010Lx-%#010Lx]\n",
|
||||||
bi->nid, bi->start, bi->end, bj->start, bj->end,
|
bi->nid, bi->start, bi->end - 1, bj->start,
|
||||||
start, end);
|
bj->end - 1, start, end - 1);
|
||||||
bi->start = start;
|
bi->start = start;
|
||||||
bi->end = end;
|
bi->end = end;
|
||||||
numa_remove_memblk_from(j--, mi);
|
numa_remove_memblk_from(j--, mi);
|
||||||
|
@ -616,8 +616,8 @@ static int __init dummy_numa_init(void)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO "%s\n",
|
printk(KERN_INFO "%s\n",
|
||||||
numa_off ? "NUMA turned off" : "No NUMA configuration found");
|
numa_off ? "NUMA turned off" : "No NUMA configuration found");
|
||||||
printk(KERN_INFO "Faking a node at %016Lx-%016Lx\n",
|
printk(KERN_INFO "Faking a node at [mem %#018Lx-%#018Lx]\n",
|
||||||
0LLU, PFN_PHYS(max_pfn));
|
0LLU, PFN_PHYS(max_pfn) - 1);
|
||||||
|
|
||||||
node_set(0, numa_nodes_parsed);
|
node_set(0, numa_nodes_parsed);
|
||||||
numa_add_memblk(0, 0, PFN_PHYS(max_pfn));
|
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);
|
numa_remove_memblk_from(phys_blk, pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
|
printk(KERN_INFO "Faking node %d at [mem %#018Lx-%#018Lx] (%LuMB)\n",
|
||||||
eb->start, eb->end, (eb->end - eb->start) >> 20);
|
nid, eb->start, eb->end - 1, (eb->end - eb->start) >> 20);
|
||||||
return 0;
|
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);
|
page = pfn_to_page(pfn);
|
||||||
type = get_page_memtype(page);
|
type = get_page_memtype(page);
|
||||||
if (type != -1) {
|
if (type != -1) {
|
||||||
printk(KERN_INFO "reserve_ram_pages_type failed "
|
printk(KERN_INFO "reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%lx, req 0x%lx\n",
|
||||||
"0x%Lx-0x%Lx, track 0x%lx, req 0x%lx\n",
|
start, end - 1, type, req_type);
|
||||||
start, end, type, req_type);
|
|
||||||
if (new_type)
|
if (new_type)
|
||||||
*new_type = 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);
|
err = rbt_memtype_check_insert(new, new_type);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
|
printk(KERN_INFO "reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
|
||||||
"track %s, req %s\n",
|
start, end - 1,
|
||||||
start, end, cattr_name(new->type), cattr_name(req_type));
|
cattr_name(new->type), cattr_name(req_type));
|
||||||
kfree(new);
|
kfree(new);
|
||||||
spin_unlock(&memtype_lock);
|
spin_unlock(&memtype_lock);
|
||||||
|
|
||||||
|
@ -325,8 +324,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
|
||||||
|
|
||||||
spin_unlock(&memtype_lock);
|
spin_unlock(&memtype_lock);
|
||||||
|
|
||||||
dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
|
dprintk("reserve_memtype added [mem %#010Lx-%#010Lx], track %s, req %s, ret %s\n",
|
||||||
start, end, cattr_name(new->type), cattr_name(req_type),
|
start, end - 1, cattr_name(new->type), cattr_name(req_type),
|
||||||
new_type ? cattr_name(*new_type) : "-");
|
new_type ? cattr_name(*new_type) : "-");
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -360,14 +359,14 @@ int free_memtype(u64 start, u64 end)
|
||||||
spin_unlock(&memtype_lock);
|
spin_unlock(&memtype_lock);
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
|
printk(KERN_INFO "%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
|
||||||
current->comm, current->pid, start, end);
|
current->comm, current->pid, start, end - 1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(entry);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -491,9 +490,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
|
||||||
|
|
||||||
while (cursor < to) {
|
while (cursor < to) {
|
||||||
if (!devmem_is_allowed(pfn)) {
|
if (!devmem_is_allowed(pfn)) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx]\n",
|
||||||
"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
|
current->comm, from, to - 1);
|
||||||
current->comm, from, to);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cursor += PAGE_SIZE;
|
cursor += PAGE_SIZE;
|
||||||
|
@ -554,12 +552,11 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
|
||||||
size;
|
size;
|
||||||
|
|
||||||
if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
|
if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO "%s:%d ioremap_change_attr failed %s "
|
||||||
"%s:%d ioremap_change_attr failed %s "
|
"for [mem %#010Lx-%#010Lx]\n",
|
||||||
"for %Lx-%Lx\n",
|
|
||||||
current->comm, current->pid,
|
current->comm, current->pid,
|
||||||
cattr_name(flags),
|
cattr_name(flags),
|
||||||
base, (unsigned long long)(base + size));
|
base, (unsigned long long)(base + size-1));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -591,12 +588,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
|
||||||
|
|
||||||
flags = lookup_memtype(paddr);
|
flags = lookup_memtype(paddr);
|
||||||
if (want_flags != flags) {
|
if (want_flags != flags) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING "%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
|
||||||
"%s:%d map pfn RAM range req %s for %Lx-%Lx, got %s\n",
|
|
||||||
current->comm, current->pid,
|
current->comm, current->pid,
|
||||||
cattr_name(want_flags),
|
cattr_name(want_flags),
|
||||||
(unsigned long long)paddr,
|
(unsigned long long)paddr,
|
||||||
(unsigned long long)(paddr + size),
|
(unsigned long long)(paddr + size - 1),
|
||||||
cattr_name(flags));
|
cattr_name(flags));
|
||||||
*vma_prot = __pgprot((pgprot_val(*vma_prot) &
|
*vma_prot = __pgprot((pgprot_val(*vma_prot) &
|
||||||
(~_PAGE_CACHE_MASK)) |
|
(~_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)) {
|
!is_new_memtype_allowed(paddr, size, want_flags, flags)) {
|
||||||
free_memtype(paddr, paddr + size);
|
free_memtype(paddr, paddr + size);
|
||||||
printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
|
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,
|
current->comm, current->pid,
|
||||||
cattr_name(want_flags),
|
cattr_name(want_flags),
|
||||||
(unsigned long long)paddr,
|
(unsigned long long)paddr,
|
||||||
(unsigned long long)(paddr + size),
|
(unsigned long long)(paddr + size - 1),
|
||||||
cattr_name(flags));
|
cattr_name(flags));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,8 +176,9 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
|
printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",
|
||||||
start, end);
|
node, pxm,
|
||||||
|
(unsigned long long) start, (unsigned long long) end - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init acpi_numa_arch_fixup(void) {}
|
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;
|
int n;
|
||||||
|
|
||||||
n = nodelist_scnprintf(buf, PAGE_SIZE, node_states[state]);
|
n = nodelist_scnprintf(buf, PAGE_SIZE-2, node_states[state]);
|
||||||
if (n > 0 && PAGE_SIZE > n + 1) {
|
buf[n++] = '\n';
|
||||||
*(buf + n++) = '\n';
|
buf[n] = '\0';
|
||||||
*(buf + n++) = '\0';
|
|
||||||
}
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,19 @@ config LEDS_LM3530
|
||||||
controlled manually or using PWM input or using ambient
|
controlled manually or using PWM input or using ambient
|
||||||
light automatically.
|
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
|
config LEDS_LOCOMO
|
||||||
tristate "LED Support for Locomo device"
|
tristate "LED Support for Locomo device"
|
||||||
depends on LEDS_CLASS
|
depends on LEDS_CLASS
|
||||||
|
@ -259,6 +272,14 @@ config LEDS_DA903X
|
||||||
This option enables support for on-chip LED drivers found
|
This option enables support for on-chip LED drivers found
|
||||||
on Dialog Semiconductor DA9030/DA9034 PMICs.
|
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
|
config LEDS_DAC124S085
|
||||||
tristate "LED Support for DAC124S085 SPI DAC"
|
tristate "LED Support for DAC124S085 SPI DAC"
|
||||||
depends on LEDS_CLASS
|
depends on LEDS_CLASS
|
||||||
|
@ -471,4 +492,12 @@ config LEDS_TRIGGER_DEFAULT_ON
|
||||||
comment "iptables trigger is under Netfilter config (LED target)"
|
comment "iptables trigger is under Netfilter config (LED target)"
|
||||||
depends on LEDS_TRIGGERS
|
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
|
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_BD2802) += leds-bd2802.o
|
||||||
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
|
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
|
||||||
obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.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_MIKROTIK_RB532) += leds-rb532.o
|
||||||
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
|
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
|
||||||
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.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_PCA955X) += leds-pca955x.o
|
||||||
obj-$(CONFIG_LEDS_PCA9633) += leds-pca9633.o
|
obj-$(CONFIG_LEDS_PCA9633) += leds-pca9633.o
|
||||||
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.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_WM831X_STATUS) += leds-wm831x-status.o
|
||||||
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
|
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
|
||||||
obj-$(CONFIG_LEDS_PWM) += leds-pwm.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_BACKLIGHT) += ledtrig-backlight.o
|
||||||
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
|
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
|
||||||
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.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 device_attribute *attr, const char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||||
|
unsigned long state;
|
||||||
ssize_t ret = -EINVAL;
|
ssize_t ret = -EINVAL;
|
||||||
char *after;
|
|
||||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
|
||||||
size_t count = after - buf;
|
|
||||||
|
|
||||||
if (isspace(*after))
|
ret = kstrtoul(buf, 10, &state);
|
||||||
count++;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (count == size) {
|
if (state == LED_OFF)
|
||||||
ret = count;
|
led_trigger_remove(led_cdev);
|
||||||
|
led_set_brightness(led_cdev, state);
|
||||||
|
|
||||||
if (state == LED_OFF)
|
return size;
|
||||||
led_trigger_remove(led_cdev);
|
|
||||||
led_set_brightness(led_cdev, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t led_max_brightness_show(struct device *dev,
|
static ssize_t led_max_brightness_show(struct device *dev,
|
||||||
|
|
214
drivers/leds/leds-da9052.c
Normal file
214
drivers/leds/leds-da9052.c
Normal file
|
@ -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;
|
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] = {
|
static const u8 lm3530_reg[LM3530_REG_MAX] = {
|
||||||
LM3530_GEN_CONFIG,
|
LM3530_GEN_CONFIG,
|
||||||
LM3530_ALS_CONFIG,
|
LM3530_ALS_CONFIG,
|
||||||
|
@ -141,29 +153,65 @@ static int lm3530_get_mode_from_str(const char *str)
|
||||||
return -1;
|
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)
|
static int lm3530_init_registers(struct lm3530_data *drvdata)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
int i;
|
||||||
u8 gen_config;
|
u8 gen_config;
|
||||||
u8 als_config = 0;
|
|
||||||
u8 brt_ramp;
|
u8 brt_ramp;
|
||||||
u8 als_imp_sel = 0;
|
|
||||||
u8 brightness;
|
u8 brightness;
|
||||||
u8 reg_val[LM3530_REG_MAX];
|
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 lm3530_platform_data *pdata = drvdata->pdata;
|
||||||
struct i2c_client *client = drvdata->client;
|
struct i2c_client *client = drvdata->client;
|
||||||
struct lm3530_pwm_data *pwm = &pdata->pwm_data;
|
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) |
|
gen_config = (pdata->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) |
|
||||||
((pdata->max_current & 7) << LM3530_MAX_CURR_SHIFT);
|
((pdata->max_current & 7) << LM3530_MAX_CURR_SHIFT);
|
||||||
|
|
||||||
switch (drvdata->mode) {
|
switch (drvdata->mode) {
|
||||||
case LM3530_BL_MODE_MANUAL:
|
case LM3530_BL_MODE_MANUAL:
|
||||||
|
gen_config |= LM3530_ENABLE_I2C;
|
||||||
|
break;
|
||||||
case LM3530_BL_MODE_ALS:
|
case LM3530_BL_MODE_ALS:
|
||||||
gen_config |= LM3530_ENABLE_I2C;
|
gen_config |= LM3530_ENABLE_I2C;
|
||||||
|
lm3530_als_configure(pdata, &als);
|
||||||
break;
|
break;
|
||||||
case LM3530_BL_MODE_PWM:
|
case LM3530_BL_MODE_PWM:
|
||||||
gen_config |= LM3530_ENABLE_PWM | LM3530_ENABLE_PWM_SIMPLE |
|
gen_config |= LM3530_ENABLE_PWM | LM3530_ENABLE_PWM_SIMPLE |
|
||||||
|
@ -171,38 +219,6 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)
|
||||||
break;
|
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) |
|
brt_ramp = (pdata->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) |
|
||||||
(pdata->brt_ramp_rise << LM3530_BRT_RAMP_RISE_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;
|
brightness = drvdata->led_dev.max_brightness;
|
||||||
|
|
||||||
reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */
|
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[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[4] = brightness; /* LM3530_BRT_CTRL_REG */
|
||||||
reg_val[5] = zones[0]; /* LM3530_ALS_ZB0_REG */
|
reg_val[5] = als.zones[0]; /* LM3530_ALS_ZB0_REG */
|
||||||
reg_val[6] = zones[1]; /* LM3530_ALS_ZB1_REG */
|
reg_val[6] = als.zones[1]; /* LM3530_ALS_ZB1_REG */
|
||||||
reg_val[7] = zones[2]; /* LM3530_ALS_ZB2_REG */
|
reg_val[7] = als.zones[2]; /* LM3530_ALS_ZB2_REG */
|
||||||
reg_val[8] = zones[3]; /* LM3530_ALS_ZB3_REG */
|
reg_val[8] = als.zones[3]; /* LM3530_ALS_ZB3_REG */
|
||||||
reg_val[9] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_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[10] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */
|
||||||
reg_val[11] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */
|
reg_val[11] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */
|
||||||
|
|
785
drivers/leds/leds-lm3533.c
Normal file
785
drivers/leds/leds-lm3533.c
Normal file
|
@ -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 */
|
/* move current engine to direct mode and remember the state */
|
||||||
ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
|
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 */
|
/* Mode change requires min 500 us delay. 1 - 2 ms with margin */
|
||||||
usleep_range(1000, 2000);
|
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 */
|
/* For loading, all the engines to load mode */
|
||||||
lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
|
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,
|
LP5521_PROG_MEM_SIZE,
|
||||||
pattern);
|
pattern);
|
||||||
|
|
||||||
ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode);
|
return lp5521_write(client, LP5521_REG_OP_MODE, mode);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr)
|
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!
|
* LP5521_REG_ENABLE register will not have any effect - strange!
|
||||||
*/
|
*/
|
||||||
ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf);
|
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");
|
dev_err(&client->dev, "error in resetting chip\n");
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
|
led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
|
||||||
if (led == NULL) {
|
if (led == NULL) {
|
||||||
dev_err(&pdev->dev, "failed to alloc memory\n");
|
dev_err(&pdev->dev, "failed to alloc memory\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -101,11 +101,16 @@ static const struct i2c_device_id pca955x_id[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, 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 pca955x_chipdef *chipdef;
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pca955x_led {
|
||||||
|
struct pca955x *pca955x;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
spinlock_t lock;
|
|
||||||
enum led_brightness brightness;
|
enum led_brightness brightness;
|
||||||
struct led_classdev led_cdev;
|
struct led_classdev led_cdev;
|
||||||
int led_num; /* 0 .. 15 potentially */
|
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)
|
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,
|
i2c_smbus_write_byte_data(client,
|
||||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
|
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)
|
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,
|
i2c_smbus_write_byte_data(client,
|
||||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
|
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)
|
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,
|
i2c_smbus_write_byte_data(client,
|
||||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
|
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)
|
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,
|
return (u8) i2c_smbus_read_byte_data(client,
|
||||||
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
|
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)
|
static void pca955x_led_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct pca955x_led *pca955x;
|
struct pca955x_led *pca955x_led;
|
||||||
|
struct pca955x *pca955x;
|
||||||
u8 ls;
|
u8 ls;
|
||||||
int chip_ls; /* which LSx to use (0-3 potentially) */
|
int chip_ls; /* which LSx to use (0-3 potentially) */
|
||||||
int ls_led; /* which set of bits within LSx to use (0-3) */
|
int ls_led; /* which set of bits within LSx to use (0-3) */
|
||||||
|
|
||||||
pca955x = container_of(work, struct pca955x_led, work);
|
pca955x_led = container_of(work, struct pca955x_led, work);
|
||||||
chip_ls = pca955x->led_num / 4;
|
pca955x = pca955x_led->pca955x;
|
||||||
ls_led = pca955x->led_num % 4;
|
|
||||||
|
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);
|
ls = pca955x_read_ls(pca955x->client, chip_ls);
|
||||||
|
|
||||||
switch (pca955x->brightness) {
|
switch (pca955x_led->brightness) {
|
||||||
case LED_FULL:
|
case LED_FULL:
|
||||||
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
|
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
|
||||||
break;
|
break;
|
||||||
|
@ -219,12 +229,15 @@ static void pca955x_led_work(struct work_struct *work)
|
||||||
* OFF, HALF, or FULL. But, this is probably better than
|
* OFF, HALF, or FULL. But, this is probably better than
|
||||||
* just turning off for all other values.
|
* 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);
|
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pca955x_write_ls(pca955x->client, chip_ls, ls);
|
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)
|
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);
|
pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
|
||||||
|
|
||||||
spin_lock(&pca955x->lock);
|
|
||||||
pca955x->brightness = value;
|
pca955x->brightness = value;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -241,14 +253,13 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
|
||||||
* can sleep.
|
* can sleep.
|
||||||
*/
|
*/
|
||||||
schedule_work(&pca955x->work);
|
schedule_work(&pca955x->work);
|
||||||
|
|
||||||
spin_unlock(&pca955x->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit pca955x_probe(struct i2c_client *client,
|
static int __devinit pca955x_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct pca955x_led *pca955x;
|
struct pca955x *pca955x;
|
||||||
|
struct pca955x_led *pca955x_led;
|
||||||
struct pca955x_chipdef *chip;
|
struct pca955x_chipdef *chip;
|
||||||
struct i2c_adapter *adapter;
|
struct i2c_adapter *adapter;
|
||||||
struct led_platform_data *pdata;
|
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)
|
if (!pca955x)
|
||||||
return -ENOMEM;
|
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);
|
i2c_set_clientdata(client, pca955x);
|
||||||
|
|
||||||
|
mutex_init(&pca955x->lock);
|
||||||
|
pca955x->client = client;
|
||||||
|
pca955x->chipdef = chip;
|
||||||
|
|
||||||
for (i = 0; i < chip->bits; i++) {
|
for (i = 0; i < chip->bits; i++) {
|
||||||
pca955x[i].chipdef = chip;
|
pca955x_led = &pca955x->leds[i];
|
||||||
pca955x[i].client = client;
|
pca955x_led->led_num = i;
|
||||||
pca955x[i].led_num = i;
|
pca955x_led->pca955x = pca955x;
|
||||||
|
|
||||||
/* Platform data can specify LED names and default triggers */
|
/* Platform data can specify LED names and default triggers */
|
||||||
if (pdata) {
|
if (pdata) {
|
||||||
if (pdata->leds[i].name)
|
if (pdata->leds[i].name)
|
||||||
snprintf(pca955x[i].name,
|
snprintf(pca955x_led->name,
|
||||||
sizeof(pca955x[i].name), "pca955x:%s",
|
sizeof(pca955x_led->name), "pca955x:%s",
|
||||||
pdata->leds[i].name);
|
pdata->leds[i].name);
|
||||||
if (pdata->leds[i].default_trigger)
|
if (pdata->leds[i].default_trigger)
|
||||||
pca955x[i].led_cdev.default_trigger =
|
pca955x_led->led_cdev.default_trigger =
|
||||||
pdata->leds[i].default_trigger;
|
pdata->leds[i].default_trigger;
|
||||||
} else {
|
} else {
|
||||||
snprintf(pca955x[i].name, sizeof(pca955x[i].name),
|
snprintf(pca955x_led->name, sizeof(pca955x_led->name),
|
||||||
"pca955x:%d", i);
|
"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;
|
INIT_WORK(&pca955x_led->work, pca955x_led_work);
|
||||||
pca955x[i].led_cdev.brightness_set = pca955x_led_set;
|
|
||||||
|
|
||||||
INIT_WORK(&pca955x[i].work, pca955x_led_work);
|
err = led_classdev_register(&client->dev,
|
||||||
|
&pca955x_led->led_cdev);
|
||||||
err = led_classdev_register(&client->dev, &pca955x[i].led_cdev);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -337,10 +357,12 @@ static int __devinit pca955x_probe(struct i2c_client *client,
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
while (i--) {
|
while (i--) {
|
||||||
led_classdev_unregister(&pca955x[i].led_cdev);
|
led_classdev_unregister(&pca955x->leds[i].led_cdev);
|
||||||
cancel_work_sync(&pca955x[i].work);
|
cancel_work_sync(&pca955x->leds[i].work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(pca955x->leds);
|
||||||
|
exit_nomem:
|
||||||
kfree(pca955x);
|
kfree(pca955x);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -348,14 +370,15 @@ exit:
|
||||||
|
|
||||||
static int __devexit pca955x_remove(struct i2c_client *client)
|
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;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < pca955x->chipdef->bits; i++) {
|
for (i = 0; i < pca955x->chipdef->bits; i++) {
|
||||||
led_classdev_unregister(&pca955x[i].led_cdev);
|
led_classdev_unregister(&pca955x->leds[i].led_cdev);
|
||||||
cancel_work_sync(&pca955x[i].work);
|
cancel_work_sync(&pca955x->leds[i].work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(pca955x->leds);
|
||||||
kfree(pca955x);
|
kfree(pca955x);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -120,6 +120,7 @@ static void bl_trig_activate(struct led_classdev *led)
|
||||||
ret = fb_register_client(&n->notifier);
|
ret = fb_register_client(&n->notifier);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(led->dev, "unable to register backlight trigger\n");
|
dev_err(led->dev, "unable to register backlight trigger\n");
|
||||||
|
led->activated = true;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -133,10 +134,11 @@ static void bl_trig_deactivate(struct led_classdev *led)
|
||||||
struct bl_trig_notifier *n =
|
struct bl_trig_notifier *n =
|
||||||
(struct bl_trig_notifier *) led->trigger_data;
|
(struct bl_trig_notifier *) led->trigger_data;
|
||||||
|
|
||||||
if (n) {
|
if (led->activated) {
|
||||||
device_remove_file(led->dev, &dev_attr_inverted);
|
device_remove_file(led->dev, &dev_attr_inverted);
|
||||||
fb_unregister_client(&n->notifier);
|
fb_unregister_client(&n->notifier);
|
||||||
kfree(n);
|
kfree(n);
|
||||||
|
led->activated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,7 @@ static void gpio_trig_activate(struct led_classdev *led)
|
||||||
gpio_data->led = led;
|
gpio_data->led = led;
|
||||||
led->trigger_data = gpio_data;
|
led->trigger_data = gpio_data;
|
||||||
INIT_WORK(&gpio_data->work, gpio_trig_work);
|
INIT_WORK(&gpio_data->work, gpio_trig_work);
|
||||||
|
led->activated = true;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -217,7 +218,7 @@ static void gpio_trig_deactivate(struct led_classdev *led)
|
||||||
{
|
{
|
||||||
struct gpio_trig_data *gpio_data = led->trigger_data;
|
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_gpio);
|
||||||
device_remove_file(led->dev, &dev_attr_inverted);
|
device_remove_file(led->dev, &dev_attr_inverted);
|
||||||
device_remove_file(led->dev, &dev_attr_desired_brightness);
|
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)
|
if (gpio_data->gpio != 0)
|
||||||
free_irq(gpio_to_irq(gpio_data->gpio), led);
|
free_irq(gpio_to_irq(gpio_data->gpio), led);
|
||||||
kfree(gpio_data);
|
kfree(gpio_data);
|
||||||
|
led->activated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
#include "leds.h"
|
#include "leds.h"
|
||||||
|
|
||||||
struct heartbeat_trig_data {
|
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);
|
led_heartbeat_function, (unsigned long) led_cdev);
|
||||||
heartbeat_data->phase = 0;
|
heartbeat_data->phase = 0;
|
||||||
led_heartbeat_function(heartbeat_data->timer.data);
|
led_heartbeat_function(heartbeat_data->timer.data);
|
||||||
|
led_cdev->activated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
|
static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
|
||||||
{
|
{
|
||||||
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
|
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
|
||||||
|
|
||||||
if (heartbeat_data) {
|
if (led_cdev->activated) {
|
||||||
del_timer_sync(&heartbeat_data->timer);
|
del_timer_sync(&heartbeat_data->timer);
|
||||||
kfree(heartbeat_data);
|
kfree(heartbeat_data);
|
||||||
|
led_cdev->activated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +104,38 @@ static struct led_trigger heartbeat_led_trigger = {
|
||||||
.deactivate = heartbeat_trig_deactivate,
|
.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)
|
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)
|
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);
|
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 device_attribute *attr, const char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||||
int ret = -EINVAL;
|
unsigned long state;
|
||||||
char *after;
|
ssize_t ret = -EINVAL;
|
||||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
|
||||||
size_t count = after - buf;
|
|
||||||
|
|
||||||
if (isspace(*after))
|
ret = kstrtoul(buf, 10, &state);
|
||||||
count++;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (count == size) {
|
led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
|
||||||
led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
|
led_cdev->blink_delay_on = state;
|
||||||
led_cdev->blink_delay_on = state;
|
|
||||||
ret = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t led_delay_off_show(struct device *dev,
|
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 device_attribute *attr, const char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||||
int ret = -EINVAL;
|
unsigned long state;
|
||||||
char *after;
|
ssize_t ret = -EINVAL;
|
||||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
|
||||||
size_t count = after - buf;
|
|
||||||
|
|
||||||
if (isspace(*after))
|
ret = kstrtoul(buf, 10, &state);
|
||||||
count++;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (count == size) {
|
led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
|
||||||
led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
|
led_cdev->blink_delay_off = state;
|
||||||
led_cdev->blink_delay_off = state;
|
|
||||||
ret = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
|
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_blink_set(led_cdev, &led_cdev->blink_delay_on,
|
||||||
&led_cdev->blink_delay_off);
|
&led_cdev->blink_delay_off);
|
||||||
|
led_cdev->activated = true;
|
||||||
led_cdev->trigger_data = (void *)1;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -106,9 +97,10 @@ err_out_delayon:
|
||||||
|
|
||||||
static void timer_trig_deactivate(struct led_classdev *led_cdev)
|
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_on);
|
||||||
device_remove_file(led_cdev->dev, &dev_attr_delay_off);
|
device_remove_file(led_cdev->dev, &dev_attr_delay_off);
|
||||||
|
led_cdev->activated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop blinking */
|
/* Stop blinking */
|
||||||
|
|
237
drivers/leds/ledtrig-transient.c
Normal file
237
drivers/leds/ledtrig-transient.c
Normal file
|
@ -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);
|
mutex_init(&dev->mutex);
|
||||||
|
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
props.type = BACKLIGHT_PLATFORM;
|
props.type = BACKLIGHT_PLATFORM;
|
||||||
props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
|
props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
|
||||||
dev->backlight_dev = backlight_device_register("toshiba",
|
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
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-msm6242.
|
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
|
config RTC_DRV_BQ4802
|
||||||
tristate "TI BQ4802"
|
tristate "TI BQ4802"
|
||||||
help
|
help
|
||||||
|
@ -738,6 +717,16 @@ config RTC_DRV_DAVINCI
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-davinci.
|
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
|
config RTC_DRV_OMAP
|
||||||
tristate "TI OMAP1"
|
tristate "TI OMAP1"
|
||||||
depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
|
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
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-ls1x.
|
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
|
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_M48T35) += rtc-m48t35.o
|
||||||
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
|
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
|
||||||
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.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_MAX6900) += rtc-max6900.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
|
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
|
obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/bcd.h>
|
#include <linux/bcd.h>
|
||||||
|
#include <linux/rtc/ds1307.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can't determine type by probing, but if we expect pre-Linux code
|
* 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_A2I 0x02
|
||||||
# define DS1337_BIT_A1I 0x01
|
# define DS1337_BIT_A1I 0x01
|
||||||
#define DS1339_REG_ALARM1_SECS 0x07
|
#define DS1339_REG_ALARM1_SECS 0x07
|
||||||
#define DS1339_REG_TRICKLE 0x10
|
|
||||||
|
#define DS13XX_TRICKLE_CHARGER_MAGIC 0xa0
|
||||||
|
|
||||||
#define RX8025_REG_CTRL1 0x0e
|
#define RX8025_REG_CTRL1 0x0e
|
||||||
# define RX8025_BIT_2412 0x20
|
# define RX8025_BIT_2412 0x20
|
||||||
|
@ -124,6 +124,7 @@ struct chip_desc {
|
||||||
unsigned alarm:1;
|
unsigned alarm:1;
|
||||||
u16 nvram_offset;
|
u16 nvram_offset;
|
||||||
u16 nvram_size;
|
u16 nvram_size;
|
||||||
|
u16 trickle_charger_reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct chip_desc chips[last_ds_type] = {
|
static const struct chip_desc chips[last_ds_type] = {
|
||||||
|
@ -140,6 +141,13 @@ static const struct chip_desc chips[last_ds_type] = {
|
||||||
},
|
},
|
||||||
[ds_1339] = {
|
[ds_1339] = {
|
||||||
.alarm = 1,
|
.alarm = 1,
|
||||||
|
.trickle_charger_reg = 0x10,
|
||||||
|
},
|
||||||
|
[ds_1340] = {
|
||||||
|
.trickle_charger_reg = 0x08,
|
||||||
|
},
|
||||||
|
[ds_1388] = {
|
||||||
|
.trickle_charger_reg = 0x0a,
|
||||||
},
|
},
|
||||||
[ds_3231] = {
|
[ds_3231] = {
|
||||||
.alarm = 1,
|
.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);
|
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||||
int want_irq = false;
|
int want_irq = false;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
struct ds1307_platform_data *pdata = client->dev.platform_data;
|
||||||
static const int bbsqi_bitpos[] = {
|
static const int bbsqi_bitpos[] = {
|
||||||
[ds_1337] = 0,
|
[ds_1337] = 0,
|
||||||
[ds_1339] = DS1339_BIT_BBSQI,
|
[ds_1339] = DS1339_BIT_BBSQI,
|
||||||
|
@ -637,7 +646,10 @@ static int __devinit ds1307_probe(struct i2c_client *client,
|
||||||
|
|
||||||
ds1307->client = client;
|
ds1307->client = client;
|
||||||
ds1307->type = id->driver_data;
|
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;
|
buf = ds1307->regs;
|
||||||
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
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,
|
.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 ep93xx_rtc *ep93xx_rtc;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
@ -174,7 +174,7 @@ exit:
|
||||||
return err;
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* work with hotplug and coldplug */
|
|
||||||
MODULE_ALIAS("platform:ep93xx-rtc");
|
|
||||||
|
|
||||||
static struct platform_driver ep93xx_rtc_driver = {
|
static struct platform_driver ep93xx_rtc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ep93xx-rtc",
|
.name = "ep93xx-rtc",
|
||||||
.owner = THIS_MODULE,
|
.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)
|
module_platform_driver(ep93xx_rtc_driver);
|
||||||
{
|
|
||||||
return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit ep93xx_rtc_exit(void)
|
|
||||||
{
|
|
||||||
platform_driver_unregister(&ep93xx_rtc_driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
|
||||||
MODULE_DESCRIPTION("EP93XX RTC driver");
|
MODULE_DESCRIPTION("EP93XX RTC driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(DRV_VERSION);
|
MODULE_VERSION(DRV_VERSION);
|
||||||
|
MODULE_ALIAS("platform:ep93xx-rtc");
|
||||||
module_init(ep93xx_rtc_init);
|
|
||||||
module_exit(ep93xx_rtc_exit);
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clock and Power control register offsets
|
* 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
|
#define LPC32XX_RTC_PM_OPS NULL
|
||||||
#endif
|
#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 = {
|
static struct platform_driver lpc32xx_rtc_driver = {
|
||||||
.probe = lpc32xx_rtc_probe,
|
.probe = lpc32xx_rtc_probe,
|
||||||
.remove = __devexit_p(lpc32xx_rtc_remove),
|
.remove = __devexit_p(lpc32xx_rtc_remove),
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = RTC_NAME,
|
.name = RTC_NAME,
|
||||||
.owner = THIS_MODULE,
|
.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)
|
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct spi_device *spi = to_spi_device(dev);
|
struct spi_device *spi = to_spi_device(dev);
|
||||||
|
int tmp;
|
||||||
u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
|
u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
|
||||||
u8 * const data = &buf[1]; /* ptr to first data byte */
|
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;
|
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_SSEC] = 0;
|
||||||
data[M41T93_REG_ST_SEC] = bin2bcd(tm->tm_sec);
|
data[M41T93_REG_ST_SEC] = bin2bcd(tm->tm_sec);
|
||||||
data[M41T93_REG_MIN] = bin2bcd(tm->tm_min);
|
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
|
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
|
registers has been disabled due to power failure. This is normal
|
||||||
case after poweron. Time is valid after resetting HT bit.
|
case after poweron. Time is valid after resetting HT bit.
|
||||||
2. oscillator fail bit (OF) is set. Oscillator has be stopped and
|
2. oscillator fail bit (OF) is set: time is invalid.
|
||||||
time is invalid:
|
|
||||||
a) OF can be immeditely reset.
|
|
||||||
b) OF cannot be immediately reset: oscillator has to be restarted.
|
|
||||||
*/
|
*/
|
||||||
tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
|
tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
|
||||||
if (tmp < 0)
|
if (tmp < 0)
|
||||||
|
@ -110,21 +132,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
|
||||||
if (tmp & M41T93_FLAG_OF) {
|
if (tmp & M41T93_FLAG_OF) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
dev_warn(&spi->dev, "OF bit is set, resetting.\n");
|
dev_warn(&spi->dev, "OF bit is set, write time to restart.\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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp & M41T93_FLAG_BL)
|
if (tmp & M41T93_FLAG_BL)
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct pcf8563 {
|
||||||
* 1970...2069.
|
* 1970...2069.
|
||||||
*/
|
*/
|
||||||
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
|
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;
|
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,
|
dev_info(&client->dev,
|
||||||
"low voltage detected, date/time is not reliable.\n");
|
"low voltage detected, date/time is not reliable.\n");
|
||||||
|
}
|
||||||
|
|
||||||
dev_dbg(&client->dev,
|
dev_dbg(&client->dev,
|
||||||
"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
|
"%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;
|
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)
|
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
return pcf8563_get_datetime(to_i2c_client(dev), 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 = {
|
static const struct rtc_class_ops pcf8563_rtc_ops = {
|
||||||
|
.ioctl = pcf8563_rtc_ioctl,
|
||||||
.read_time = pcf8563_rtc_read_time,
|
.read_time = pcf8563_rtc_read_time,
|
||||||
.set_time = pcf8563_rtc_set_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;
|
unsigned long events = 0;
|
||||||
|
|
||||||
rtcmis = readl(ldata->base + RTC_MIS);
|
rtcmis = readl(ldata->base + RTC_MIS);
|
||||||
if (rtcmis) {
|
if (rtcmis & RTC_BIT_AI) {
|
||||||
writel(rtcmis, ldata->base + RTC_ICR);
|
writel(RTC_BIT_AI, ldata->base + RTC_ICR);
|
||||||
|
events |= (RTC_AF | RTC_IRQF);
|
||||||
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);
|
|
||||||
|
|
||||||
rtc_update_irq(ldata->rtc, 1, events);
|
rtc_update_irq(ldata->rtc, 1, events);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
|
|
@ -670,6 +670,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
|
||||||
#define s3c_rtc_resume NULL
|
#define s3c_rtc_resume NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
|
static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
|
||||||
[TYPE_S3C2410] = { TYPE_S3C2410 },
|
[TYPE_S3C2410] = { TYPE_S3C2410 },
|
||||||
[TYPE_S3C2416] = { TYPE_S3C2416 },
|
[TYPE_S3C2416] = { TYPE_S3C2416 },
|
||||||
|
@ -677,7 +678,6 @@ static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
|
||||||
[TYPE_S3C64XX] = { TYPE_S3C64XX },
|
[TYPE_S3C64XX] = { TYPE_S3C64XX },
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
|
||||||
static const struct of_device_id s3c_rtc_dt_match[] = {
|
static const struct of_device_id s3c_rtc_dt_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "samsung,s3c2410-rtc",
|
.compatible = "samsung,s3c2410-rtc",
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -519,6 +520,14 @@ static void spear_rtc_shutdown(struct platform_device *pdev)
|
||||||
clk_disable(config->clk);
|
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 = {
|
static struct platform_driver spear_rtc_driver = {
|
||||||
.probe = spear_rtc_probe,
|
.probe = spear_rtc_probe,
|
||||||
.remove = __devexit_p(spear_rtc_remove),
|
.remove = __devexit_p(spear_rtc_remove),
|
||||||
|
@ -527,6 +536,7 @@ static struct platform_driver spear_rtc_driver = {
|
||||||
.shutdown = spear_rtc_shutdown,
|
.shutdown = spear_rtc_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rtc-spear",
|
.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;
|
struct resource *res;
|
||||||
int ret;
|
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)
|
if (!info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -317,29 +318,18 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
|
||||||
if (!res) {
|
if (!res) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"Unable to allocate resources for device.\n");
|
"Unable to allocate resources for device.\n");
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto err_free_info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
|
info->rtc_base = devm_request_and_ioremap(&pdev->dev, res);
|
||||||
dev_err(&pdev->dev,
|
if (!info->rtc_base) {
|
||||||
"Unable to request mem region for device.\n");
|
dev_err(&pdev->dev, "Unable to request mem region and grab IOs for device.\n");
|
||||||
ret = -EBUSY;
|
return -EBUSY;
|
||||||
goto err_free_info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
info->tegra_rtc_irq = platform_get_irq(pdev, 0);
|
info->tegra_rtc_irq = platform_get_irq(pdev, 0);
|
||||||
if (info->tegra_rtc_irq <= 0) {
|
if (info->tegra_rtc_irq <= 0)
|
||||||
ret = -EBUSY;
|
return -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set context info. */
|
/* set context info. */
|
||||||
info->pdev = pdev;
|
info->pdev = pdev;
|
||||||
|
@ -362,11 +352,12 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev)
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"Unable to register device (err=%d).\n",
|
"Unable to register device (err=%d).\n",
|
||||||
ret);
|
ret);
|
||||||
goto err_iounmap;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = request_irq(info->tegra_rtc_irq, tegra_rtc_irq_handler,
|
ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
|
||||||
IRQF_TRIGGER_HIGH, "rtc alarm", &pdev->dev);
|
tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH,
|
||||||
|
"rtc alarm", &pdev->dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"Unable to request interrupt for device (err=%d).\n",
|
"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:
|
err_dev_unreg:
|
||||||
rtc_device_unregister(info->rtc_dev);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -393,17 +378,8 @@ err_free_info:
|
||||||
static int __devexit tegra_rtc_remove(struct platform_device *pdev)
|
static int __devexit tegra_rtc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct tegra_rtc_info *info = platform_get_drvdata(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);
|
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);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/falloc.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
@ -363,11 +364,12 @@ static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
|
||||||
|
|
||||||
mutex_lock(&ashmem_mutex);
|
mutex_lock(&ashmem_mutex);
|
||||||
list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
|
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 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;
|
range->purged = ASHMEM_WAS_PURGED;
|
||||||
lru_del(range);
|
lru_del(range);
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,18 @@ config BACKLIGHT_GENERIC
|
||||||
known as the Corgi backlight driver. If you have a Sharp Zaurus
|
known as the Corgi backlight driver. If you have a Sharp Zaurus
|
||||||
SL-C7xx, SL-Cxx00 or SL-6000x say y.
|
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
|
config BACKLIGHT_LOCOMO
|
||||||
tristate "Sharp LOCOMO LCD/Backlight Driver"
|
tristate "Sharp LOCOMO LCD/Backlight Driver"
|
||||||
depends on SHARP_LOCOMO
|
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_GENERIC) += generic_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
|
obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_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_LOCOMO) += locomolcd.o
|
||||||
obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
|
obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
|
||||||
obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_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;
|
unsigned long val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = strict_strtoul(buf, 10, &val);
|
ret = kstrtoul(buf, 10, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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);
|
struct adp5520_bl *data = dev_get_drvdata(dev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
|
ret = kstrtoul(buf, 10, &data->cached_daylight_max);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,8 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
|
||||||
struct led_info *cur_led;
|
struct led_info *cur_led;
|
||||||
int ret, i;
|
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) {
|
if (led == NULL) {
|
||||||
dev_err(&client->dev, "failed to alloc memory\n");
|
dev_err(&client->dev, "failed to alloc memory\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -236,7 +237,7 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&client->dev, "failed to write\n");
|
dev_err(&client->dev, "failed to write\n");
|
||||||
goto err_free;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < pdata->num_leds; ++i) {
|
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);
|
cancel_work_sync(&led[i].work);
|
||||||
}
|
}
|
||||||
|
|
||||||
err_free:
|
|
||||||
kfree(led);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +307,6 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
|
||||||
cancel_work_sync(&data->led[i].work);
|
cancel_work_sync(&data->led[i].work);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(data->led);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -451,7 +448,7 @@ static ssize_t adp8860_store(struct device *dev, const char *buf,
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = strict_strtoul(buf, 10, &val);
|
ret = kstrtoul(buf, 10, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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 device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct adp8860_bl *data = dev_get_drvdata(dev);
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -608,7 +605,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
|
||||||
uint8_t reg_val;
|
uint8_t reg_val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = strict_strtoul(buf, 10, &val);
|
ret = kstrtoul(buf, 10, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -675,13 +672,13 @@ static int __devinit adp8860_probe(struct i2c_client *client,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = adp8860_read(client, ADP8860_MFDVID, ®_val);
|
ret = adp8860_read(client, ADP8860_MFDVID, ®_val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out2;
|
return ret;
|
||||||
|
|
||||||
switch (ADP8860_MANID(reg_val)) {
|
switch (ADP8860_MANID(reg_val)) {
|
||||||
case ADP8863_MANUFID:
|
case ADP8863_MANUFID:
|
||||||
|
@ -694,8 +691,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&client->dev, "failed to probe\n");
|
dev_err(&client->dev, "failed to probe\n");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto out2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It's confirmed that the DEVID field is actually a REVID */
|
/* 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);
|
&client->dev, data, &adp8860_bl_ops, &props);
|
||||||
if (IS_ERR(bl)) {
|
if (IS_ERR(bl)) {
|
||||||
dev_err(&client->dev, "failed to register backlight\n");
|
dev_err(&client->dev, "failed to register backlight\n");
|
||||||
ret = PTR_ERR(bl);
|
return PTR_ERR(bl);
|
||||||
goto out2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
|
bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
|
||||||
|
@ -756,8 +751,6 @@ out:
|
||||||
&adp8860_bl_attr_group);
|
&adp8860_bl_attr_group);
|
||||||
out1:
|
out1:
|
||||||
backlight_device_unregister(bl);
|
backlight_device_unregister(bl);
|
||||||
out2:
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -776,7 +769,6 @@ static int __devexit adp8860_remove(struct i2c_client *client)
|
||||||
&adp8860_bl_attr_group);
|
&adp8860_bl_attr_group);
|
||||||
|
|
||||||
backlight_device_unregister(data->bl);
|
backlight_device_unregister(data->bl);
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,8 +244,8 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
|
||||||
struct led_info *cur_led;
|
struct led_info *cur_led;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
|
led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led),
|
||||||
led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (led == NULL) {
|
if (led == NULL) {
|
||||||
dev_err(&client->dev, "failed to alloc memory\n");
|
dev_err(&client->dev, "failed to alloc memory\n");
|
||||||
return -ENOMEM;
|
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);
|
ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
return ret;
|
||||||
|
|
||||||
ret = adp8870_write(client, ADP8870_ISCT1,
|
ret = adp8870_write(client, ADP8870_ISCT1,
|
||||||
(pdata->led_on_time & 0x3) << 6);
|
(pdata->led_on_time & 0x3) << 6);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
return ret;
|
||||||
|
|
||||||
ret = adp8870_write(client, ADP8870_ISCF,
|
ret = adp8870_write(client, ADP8870_ISCF,
|
||||||
FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
|
FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
return ret;
|
||||||
|
|
||||||
for (i = 0; i < pdata->num_leds; ++i) {
|
for (i = 0; i < pdata->num_leds; ++i) {
|
||||||
cur_led = &pdata->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);
|
cancel_work_sync(&led[i].work);
|
||||||
}
|
}
|
||||||
|
|
||||||
err_free:
|
|
||||||
kfree(led);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +332,6 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
|
||||||
cancel_work_sync(&data->led[i].work);
|
cancel_work_sync(&data->led[i].work);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(data->led);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -572,7 +568,7 @@ static ssize_t adp8870_store(struct device *dev, const char *buf,
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = strict_strtoul(buf, 10, &val);
|
ret = kstrtoul(buf, 10, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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 device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct adp8870_bl *data = dev_get_drvdata(dev);
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -794,7 +790,7 @@ static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
|
||||||
uint8_t reg_val;
|
uint8_t reg_val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = strict_strtoul(buf, 10, &val);
|
ret = kstrtoul(buf, 10, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -874,7 +870,7 @@ static int __devinit adp8870_probe(struct i2c_client *client,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -894,8 +890,7 @@ static int __devinit adp8870_probe(struct i2c_client *client,
|
||||||
&client->dev, data, &adp8870_bl_ops, &props);
|
&client->dev, data, &adp8870_bl_ops, &props);
|
||||||
if (IS_ERR(bl)) {
|
if (IS_ERR(bl)) {
|
||||||
dev_err(&client->dev, "failed to register backlight\n");
|
dev_err(&client->dev, "failed to register backlight\n");
|
||||||
ret = PTR_ERR(bl);
|
return PTR_ERR(bl);
|
||||||
goto out2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data->bl = bl;
|
data->bl = bl;
|
||||||
|
@ -930,8 +925,6 @@ out:
|
||||||
&adp8870_bl_attr_group);
|
&adp8870_bl_attr_group);
|
||||||
out1:
|
out1:
|
||||||
backlight_device_unregister(bl);
|
backlight_device_unregister(bl);
|
||||||
out2:
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -950,7 +943,6 @@ static int __devexit adp8870_remove(struct i2c_client *client)
|
||||||
&adp8870_bl_attr_group);
|
&adp8870_bl_attr_group);
|
||||||
|
|
||||||
backlight_device_unregister(data->bl);
|
backlight_device_unregister(data->bl);
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,7 +482,7 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
||||||
struct backlight_device *bd = NULL;
|
struct backlight_device *bd = NULL;
|
||||||
struct backlight_properties props;
|
struct backlight_properties props;
|
||||||
|
|
||||||
lcd = kzalloc(sizeof(struct ams369fg06), GFP_KERNEL);
|
lcd = devm_kzalloc(&spi->dev, sizeof(struct ams369fg06), GFP_KERNEL);
|
||||||
if (!lcd)
|
if (!lcd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -492,7 +492,7 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
||||||
ret = spi_setup(spi);
|
ret = spi_setup(spi);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&spi->dev, "spi setup failed.\n");
|
dev_err(&spi->dev, "spi setup failed.\n");
|
||||||
goto out_free_lcd;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd->spi = spi;
|
lcd->spi = spi;
|
||||||
|
@ -501,15 +501,13 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
||||||
lcd->lcd_pd = spi->dev.platform_data;
|
lcd->lcd_pd = spi->dev.platform_data;
|
||||||
if (!lcd->lcd_pd) {
|
if (!lcd->lcd_pd) {
|
||||||
dev_err(&spi->dev, "platform data is NULL\n");
|
dev_err(&spi->dev, "platform data is NULL\n");
|
||||||
goto out_free_lcd;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
|
ld = lcd_device_register("ams369fg06", &spi->dev, lcd,
|
||||||
&ams369fg06_lcd_ops);
|
&ams369fg06_lcd_ops);
|
||||||
if (IS_ERR(ld)) {
|
if (IS_ERR(ld))
|
||||||
ret = PTR_ERR(ld);
|
return PTR_ERR(ld);
|
||||||
goto out_free_lcd;
|
|
||||||
}
|
|
||||||
|
|
||||||
lcd->ld = ld;
|
lcd->ld = ld;
|
||||||
|
|
||||||
|
@ -547,8 +545,6 @@ static int __devinit ams369fg06_probe(struct spi_device *spi)
|
||||||
|
|
||||||
out_lcd_unregister:
|
out_lcd_unregister:
|
||||||
lcd_device_unregister(ld);
|
lcd_device_unregister(ld);
|
||||||
out_free_lcd:
|
|
||||||
kfree(lcd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +555,6 @@ static int __devexit ams369fg06_remove(struct spi_device *spi)
|
||||||
ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
|
ams369fg06_power(lcd, FB_BLANK_POWERDOWN);
|
||||||
backlight_device_unregister(lcd->bd);
|
backlight_device_unregister(lcd->bd);
|
||||||
lcd_device_unregister(lcd->ld);
|
lcd_device_unregister(lcd->ld);
|
||||||
kfree(lcd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -619,7 +614,6 @@ static void ams369fg06_shutdown(struct spi_device *spi)
|
||||||
static struct spi_driver ams369fg06_driver = {
|
static struct spi_driver ams369fg06_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ams369fg06",
|
.name = "ams369fg06",
|
||||||
.bus = &spi_bus_type,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.probe = ams369fg06_probe,
|
.probe = ams369fg06_probe,
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
* get at the firmware code in order to figure out what it's actually doing.
|
* 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/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
|
#include <linux/apple_bl.h>
|
||||||
|
|
||||||
static struct backlight_device *apple_backlight_device;
|
static struct backlight_device *apple_backlight_device;
|
||||||
|
|
||||||
|
@ -39,8 +42,6 @@ struct hw_data {
|
||||||
|
|
||||||
static const struct hw_data *hw_data;
|
static const struct hw_data *hw_data;
|
||||||
|
|
||||||
#define DRIVER "apple_backlight: "
|
|
||||||
|
|
||||||
/* Module parameters. */
|
/* Module parameters. */
|
||||||
static int debug;
|
static int debug;
|
||||||
module_param_named(debug, debug, int, 0644);
|
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;
|
int intensity = bd->props.brightness;
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
|
pr_debug("setting brightness to %d\n", intensity);
|
||||||
intensity);
|
|
||||||
|
|
||||||
intel_chipset_set_brightness(intensity);
|
intel_chipset_set_brightness(intensity);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -76,8 +76,7 @@ static int intel_chipset_get_intensity(struct backlight_device *bd)
|
||||||
intensity = inb(0xb3) >> 4;
|
intensity = inb(0xb3) >> 4;
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
printk(KERN_DEBUG DRIVER "read brightness of %d\n",
|
pr_debug("read brightness of %d\n", intensity);
|
||||||
intensity);
|
|
||||||
|
|
||||||
return intensity;
|
return intensity;
|
||||||
}
|
}
|
||||||
|
@ -107,8 +106,7 @@ static int nvidia_chipset_send_intensity(struct backlight_device *bd)
|
||||||
int intensity = bd->props.brightness;
|
int intensity = bd->props.brightness;
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
|
pr_debug("setting brightness to %d\n", intensity);
|
||||||
intensity);
|
|
||||||
|
|
||||||
nvidia_chipset_set_brightness(intensity);
|
nvidia_chipset_set_brightness(intensity);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -123,8 +121,7 @@ static int nvidia_chipset_get_intensity(struct backlight_device *bd)
|
||||||
intensity = inb(0x52f) >> 4;
|
intensity = inb(0x52f) >> 4;
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
printk(KERN_DEBUG DRIVER "read brightness of %d\n",
|
pr_debug("read brightness of %d\n", intensity);
|
||||||
intensity);
|
|
||||||
|
|
||||||
return 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);
|
host = pci_get_bus_and_slot(0, 0);
|
||||||
|
|
||||||
if (!host) {
|
if (!host) {
|
||||||
printk(KERN_ERR DRIVER "unable to find PCI host\n");
|
pr_err("unable to find PCI host\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +158,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
|
||||||
pci_dev_put(host);
|
pci_dev_put(host);
|
||||||
|
|
||||||
if (!hw_data) {
|
if (!hw_data) {
|
||||||
printk(KERN_ERR DRIVER "unknown hardware\n");
|
pr_err("unknown hardware\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
@ -123,7 +125,7 @@ static ssize_t backlight_store_power(struct device *dev,
|
||||||
rc = -ENXIO;
|
rc = -ENXIO;
|
||||||
mutex_lock(&bd->ops_lock);
|
mutex_lock(&bd->ops_lock);
|
||||||
if (bd->ops) {
|
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) {
|
if (bd->props.power != power) {
|
||||||
bd->props.power = power;
|
bd->props.power = power;
|
||||||
backlight_update_status(bd);
|
backlight_update_status(bd);
|
||||||
|
@ -161,8 +163,7 @@ static ssize_t backlight_store_brightness(struct device *dev,
|
||||||
if (brightness > bd->props.max_brightness)
|
if (brightness > bd->props.max_brightness)
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
else {
|
else {
|
||||||
pr_debug("backlight: set brightness to %lu\n",
|
pr_debug("set brightness to %lu\n", brightness);
|
||||||
brightness);
|
|
||||||
bd->props.brightness = brightness;
|
bd->props.brightness = brightness;
|
||||||
backlight_update_status(bd);
|
backlight_update_status(bd);
|
||||||
rc = count;
|
rc = count;
|
||||||
|
@ -378,8 +379,8 @@ static int __init backlight_class_init(void)
|
||||||
{
|
{
|
||||||
backlight_class = class_create(THIS_MODULE, "backlight");
|
backlight_class = class_create(THIS_MODULE, "backlight");
|
||||||
if (IS_ERR(backlight_class)) {
|
if (IS_ERR(backlight_class)) {
|
||||||
printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n",
|
pr_warn("Unable to create backlight class; errno = %ld\n",
|
||||||
PTR_ERR(backlight_class));
|
PTR_ERR(backlight_class));
|
||||||
return 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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd = kzalloc(sizeof(struct corgi_lcd), GFP_KERNEL);
|
lcd = devm_kzalloc(&spi->dev, sizeof(struct corgi_lcd), GFP_KERNEL);
|
||||||
if (!lcd) {
|
if (!lcd) {
|
||||||
dev_err(&spi->dev, "failed to allocate memory\n");
|
dev_err(&spi->dev, "failed to allocate memory\n");
|
||||||
return -ENOMEM;
|
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->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
|
||||||
lcd, &corgi_lcd_ops);
|
lcd, &corgi_lcd_ops);
|
||||||
if (IS_ERR(lcd->lcd_dev)) {
|
if (IS_ERR(lcd->lcd_dev))
|
||||||
ret = PTR_ERR(lcd->lcd_dev);
|
return PTR_ERR(lcd->lcd_dev);
|
||||||
goto err_free_lcd;
|
|
||||||
}
|
|
||||||
lcd->power = FB_BLANK_POWERDOWN;
|
lcd->power = FB_BLANK_POWERDOWN;
|
||||||
lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
|
lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
|
||||||
|
|
||||||
|
@ -591,8 +590,6 @@ err_unregister_bl:
|
||||||
backlight_device_unregister(lcd->bl_dev);
|
backlight_device_unregister(lcd->bl_dev);
|
||||||
err_unregister_lcd:
|
err_unregister_lcd:
|
||||||
lcd_device_unregister(lcd->lcd_dev);
|
lcd_device_unregister(lcd->lcd_dev);
|
||||||
err_free_lcd:
|
|
||||||
kfree(lcd);
|
|
||||||
return ret;
|
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);
|
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
|
||||||
lcd_device_unregister(lcd->lcd_dev);
|
lcd_device_unregister(lcd->lcd_dev);
|
||||||
kfree(lcd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
* Alan Hourihane <alanh-at-tungstengraphics-dot-com>
|
* Alan Hourihane <alanh-at-tungstengraphics-dot-com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.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,
|
lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
|
||||||
CRVML_DEVICE_LPC, NULL);
|
CRVML_DEVICE_LPC, NULL);
|
||||||
if (!lpc_dev) {
|
if (!lpc_dev) {
|
||||||
printk("INTEL CARILLO RANCH LPC not found.\n");
|
pr_err("INTEL CARILLO RANCH LPC not found.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
|
pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en);
|
||||||
if (!(dev_en & CRVML_GPIOEN_BIT)) {
|
if (!(dev_en & CRVML_GPIOEN_BIT)) {
|
||||||
printk(KERN_ERR
|
pr_err("Carillo Ranch GPIO device was not enabled.\n");
|
||||||
"Carillo Ranch GPIO device was not enabled.\n");
|
|
||||||
pci_dev_put(lpc_dev);
|
pci_dev_put(lpc_dev);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +271,7 @@ static int __init cr_backlight_init(void)
|
||||||
return PTR_ERR(crp);
|
return PTR_ERR(crp);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("Carillo Ranch Backlight Driver Initialized.\n");
|
pr_info("Carillo Ranch Backlight Driver Initialized.\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
|
||||||
da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
|
da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
|
||||||
DA9034_WLED_ISET(pdata->output_current));
|
DA9034_WLED_ISET(pdata->output_current));
|
||||||
|
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
props.type = BACKLIGHT_RAW;
|
props.type = BACKLIGHT_RAW;
|
||||||
props.max_brightness = max_brightness;
|
props.max_brightness = max_brightness;
|
||||||
bl = backlight_device_register(pdev->name, data->da903x_dev, data,
|
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/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -106,7 +108,7 @@ static int genericbl_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
generic_backlight_device = bd;
|
generic_backlight_device = bd;
|
||||||
|
|
||||||
printk("Generic Backlight Driver Initialized.\n");
|
pr_info("Generic Backlight Driver Initialized.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +122,7 @@ static int genericbl_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
backlight_device_unregister(bd);
|
backlight_device_unregister(bd);
|
||||||
|
|
||||||
printk("Generic Backlight Driver Unloaded\n");
|
pr_info("Generic Backlight Driver Unloaded\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
|
||||||
|
|
||||||
/* allocate and initialse our state */
|
/* 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) {
|
if (ili == NULL) {
|
||||||
dev_err(dev, "no memory for device\n");
|
dev_err(dev, "no memory for device\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -240,8 +240,7 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
|
||||||
lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
|
lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
|
||||||
if (IS_ERR(lcd)) {
|
if (IS_ERR(lcd)) {
|
||||||
dev_err(dev, "failed to register lcd device\n");
|
dev_err(dev, "failed to register lcd device\n");
|
||||||
ret = PTR_ERR(lcd);
|
return PTR_ERR(lcd);
|
||||||
goto err_free;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ili->lcd = lcd;
|
ili->lcd = lcd;
|
||||||
|
@ -259,9 +258,6 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
|
||||||
err_unregister:
|
err_unregister:
|
||||||
lcd_device_unregister(lcd);
|
lcd_device_unregister(lcd);
|
||||||
|
|
||||||
err_free:
|
|
||||||
kfree(ili);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +268,6 @@ int __devexit ili9320_remove(struct ili9320 *ili)
|
||||||
ili9320_power(ili, FB_BLANK_POWERDOWN);
|
ili9320_power(ili, FB_BLANK_POWERDOWN);
|
||||||
|
|
||||||
lcd_device_unregister(ili->lcd);
|
lcd_device_unregister(ili->lcd);
|
||||||
kfree(ili);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/backlight.h>
|
#include <linux/backlight.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
|
@ -38,7 +40,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
|
||||||
ret = jornada_ssp_byte(GETBRIGHTNESS);
|
ret = jornada_ssp_byte(GETBRIGHTNESS);
|
||||||
|
|
||||||
if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
|
if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
|
||||||
printk(KERN_ERR "bl : get brightness timeout\n");
|
pr_err("get brightness timeout\n");
|
||||||
jornada_ssp_end();
|
jornada_ssp_end();
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
} else /* exchange txdummy for value */
|
} 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)) {
|
if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
|
||||||
ret = jornada_ssp_byte(BRIGHTNESSOFF);
|
ret = jornada_ssp_byte(BRIGHTNESSOFF);
|
||||||
if (ret != TXDUMMY) {
|
if (ret != TXDUMMY) {
|
||||||
printk(KERN_INFO "bl : brightness off timeout\n");
|
pr_info("brightness off timeout\n");
|
||||||
/* turn off backlight */
|
/* turn off backlight */
|
||||||
PPSR &= ~PPC_LDD1;
|
PPSR &= ~PPC_LDD1;
|
||||||
PPDR |= PPC_LDD1;
|
PPDR |= PPC_LDD1;
|
||||||
|
@ -70,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
|
||||||
|
|
||||||
/* send command to our mcu */
|
/* send command to our mcu */
|
||||||
if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
|
if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
|
||||||
printk(KERN_INFO "bl : failed to set brightness\n");
|
pr_info("failed to set brightness\n");
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
goto out;
|
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
|
but due to physical layout it is equal to 0, so we simply
|
||||||
invert the value (MAX VALUE - NEW VALUE). */
|
invert the value (MAX VALUE - NEW VALUE). */
|
||||||
if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
|
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;
|
ret = -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +115,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
if (IS_ERR(bd)) {
|
if (IS_ERR(bd)) {
|
||||||
ret = PTR_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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +127,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
|
||||||
jornada_bl_update_status(bd);
|
jornada_bl_update_status(bd);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
@ -44,7 +46,7 @@ static int jornada_lcd_get_contrast(struct lcd_device *dev)
|
||||||
jornada_ssp_start();
|
jornada_ssp_start();
|
||||||
|
|
||||||
if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
|
if (jornada_ssp_byte(GETCONTRAST) != TXDUMMY) {
|
||||||
printk(KERN_ERR "lcd: get contrast failed\n");
|
pr_err("get contrast failed\n");
|
||||||
jornada_ssp_end();
|
jornada_ssp_end();
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,7 +67,7 @@ static int jornada_lcd_set_contrast(struct lcd_device *dev, int value)
|
||||||
|
|
||||||
/* push the new value */
|
/* push the new value */
|
||||||
if (jornada_ssp_byte(value) != TXDUMMY) {
|
if (jornada_ssp_byte(value) != TXDUMMY) {
|
||||||
printk(KERN_ERR "lcd : set contrast failed\n");
|
pr_err("set contrast failed\n");
|
||||||
jornada_ssp_end();
|
jornada_ssp_end();
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,7 @@ static int jornada_lcd_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
if (IS_ERR(lcd_device)) {
|
if (IS_ERR(lcd_device)) {
|
||||||
ret = PTR_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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
@ -159,7 +161,8 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = kzalloc(sizeof(struct l4f00242t03_priv), GFP_KERNEL);
|
priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv),
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (priv == NULL) {
|
if (priv == NULL) {
|
||||||
dev_err(&spi->dev, "No memory for this device.\n");
|
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) {
|
if (ret) {
|
||||||
dev_err(&spi->dev,
|
dev_err(&spi->dev,
|
||||||
"Unable to get the lcd l4f00242t03 reset gpio.\n");
|
"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,
|
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) {
|
if (ret) {
|
||||||
dev_err(&spi->dev,
|
dev_err(&spi->dev,
|
||||||
"Unable to get the lcd l4f00242t03 data en gpio.\n");
|
"Unable to get the lcd l4f00242t03 data en gpio.\n");
|
||||||
goto err2;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->io_reg = regulator_get(&spi->dev, "vdd");
|
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);
|
ret = PTR_ERR(priv->io_reg);
|
||||||
dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
|
dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
|
||||||
__func__);
|
__func__);
|
||||||
goto err3;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->core_reg = regulator_get(&spi->dev, "vcore");
|
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);
|
ret = PTR_ERR(priv->core_reg);
|
||||||
dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
|
dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
|
||||||
__func__);
|
__func__);
|
||||||
goto err4;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->ld = lcd_device_register("l4f00242t03",
|
priv->ld = lcd_device_register("l4f00242t03",
|
||||||
&spi->dev, priv, &l4f_ops);
|
&spi->dev, priv, &l4f_ops);
|
||||||
if (IS_ERR(priv->ld)) {
|
if (IS_ERR(priv->ld)) {
|
||||||
ret = PTR_ERR(priv->ld);
|
ret = PTR_ERR(priv->ld);
|
||||||
goto err5;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init the LCD */
|
/* Init the LCD */
|
||||||
|
@ -220,16 +223,14 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err5:
|
|
||||||
regulator_put(priv->core_reg);
|
|
||||||
err4:
|
err4:
|
||||||
regulator_put(priv->io_reg);
|
regulator_put(priv->core_reg);
|
||||||
err3:
|
err3:
|
||||||
gpio_free(pdata->data_enable_gpio);
|
regulator_put(priv->io_reg);
|
||||||
err2:
|
err2:
|
||||||
gpio_free(pdata->reset_gpio);
|
gpio_free(pdata->data_enable_gpio);
|
||||||
err:
|
err:
|
||||||
kfree(priv);
|
gpio_free(pdata->reset_gpio);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -250,8 +251,6 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
|
||||||
regulator_put(priv->io_reg);
|
regulator_put(priv->io_reg);
|
||||||
regulator_put(priv->core_reg);
|
regulator_put(priv->core_reg);
|
||||||
|
|
||||||
kfree(priv);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/device.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_BLANK:
|
||||||
case FB_EVENT_MODE_CHANGE:
|
case FB_EVENT_MODE_CHANGE:
|
||||||
case FB_EVENT_MODE_CHANGE_ALL:
|
case FB_EVENT_MODE_CHANGE_ALL:
|
||||||
|
case FB_EARLY_EVENT_BLANK:
|
||||||
|
case FB_R_EARLY_EVENT_BLANK:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -46,6 +50,14 @@ static int fb_notifier_callback(struct notifier_block *self,
|
||||||
if (event == FB_EVENT_BLANK) {
|
if (event == FB_EVENT_BLANK) {
|
||||||
if (ld->ops->set_power)
|
if (ld->ops->set_power)
|
||||||
ld->ops->set_power(ld, *(int *)evdata->data);
|
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 {
|
} else {
|
||||||
if (ld->ops->set_mode)
|
if (ld->ops->set_mode)
|
||||||
ld->ops->set_mode(ld, evdata->data);
|
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);
|
mutex_lock(&ld->ops_lock);
|
||||||
if (ld->ops && ld->ops->set_power) {
|
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);
|
ld->ops->set_power(ld, power);
|
||||||
rc = count;
|
rc = count;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +154,7 @@ static ssize_t lcd_store_contrast(struct device *dev,
|
||||||
|
|
||||||
mutex_lock(&ld->ops_lock);
|
mutex_lock(&ld->ops_lock);
|
||||||
if (ld->ops && ld->ops->set_contrast) {
|
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);
|
ld->ops->set_contrast(ld, contrast);
|
||||||
rc = count;
|
rc = count;
|
||||||
}
|
}
|
||||||
|
@ -253,8 +265,8 @@ static int __init lcd_class_init(void)
|
||||||
{
|
{
|
||||||
lcd_class = class_create(THIS_MODULE, "lcd");
|
lcd_class = class_create(THIS_MODULE, "lcd");
|
||||||
if (IS_ERR(lcd_class)) {
|
if (IS_ERR(lcd_class)) {
|
||||||
printk(KERN_WARNING "Unable to create backlight class; errno = %ld\n",
|
pr_warn("Unable to create backlight class; errno = %ld\n",
|
||||||
PTR_ERR(lcd_class));
|
PTR_ERR(lcd_class));
|
||||||
return 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_device *bd = NULL;
|
||||||
struct backlight_properties props;
|
struct backlight_properties props;
|
||||||
|
|
||||||
lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
|
lcd = devm_kzalloc(&spi->dev, sizeof(struct ld9040), GFP_KERNEL);
|
||||||
if (!lcd)
|
if (!lcd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -717,7 +717,7 @@ static int ld9040_probe(struct spi_device *spi)
|
||||||
ret = spi_setup(spi);
|
ret = spi_setup(spi);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&spi->dev, "spi setup failed.\n");
|
dev_err(&spi->dev, "spi setup failed.\n");
|
||||||
goto out_free_lcd;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd->spi = spi;
|
lcd->spi = spi;
|
||||||
|
@ -726,7 +726,7 @@ static int ld9040_probe(struct spi_device *spi)
|
||||||
lcd->lcd_pd = spi->dev.platform_data;
|
lcd->lcd_pd = spi->dev.platform_data;
|
||||||
if (!lcd->lcd_pd) {
|
if (!lcd->lcd_pd) {
|
||||||
dev_err(&spi->dev, "platform data is NULL.\n");
|
dev_err(&spi->dev, "platform data is NULL.\n");
|
||||||
goto out_free_lcd;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_init(&lcd->lock);
|
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);
|
ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(lcd->dev, "Failed to get regulators: %d\n", 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);
|
ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
|
||||||
if (IS_ERR(ld)) {
|
if (IS_ERR(ld)) {
|
||||||
ret = PTR_ERR(ld);
|
ret = PTR_ERR(ld);
|
||||||
goto out_free_lcd;
|
goto out_free_regulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd->ld = ld;
|
lcd->ld = ld;
|
||||||
|
@ -782,10 +782,9 @@ static int ld9040_probe(struct spi_device *spi)
|
||||||
|
|
||||||
out_unregister_lcd:
|
out_unregister_lcd:
|
||||||
lcd_device_unregister(lcd->ld);
|
lcd_device_unregister(lcd->ld);
|
||||||
out_free_lcd:
|
out_free_regulator:
|
||||||
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
||||||
|
|
||||||
kfree(lcd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,7 +796,6 @@ static int __devexit ld9040_remove(struct spi_device *spi)
|
||||||
backlight_device_unregister(lcd->bd);
|
backlight_device_unregister(lcd->bd);
|
||||||
lcd_device_unregister(lcd->ld);
|
lcd_device_unregister(lcd->ld);
|
||||||
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
|
||||||
kfree(lcd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -846,7 +844,6 @@ static void ld9040_shutdown(struct spi_device *spi)
|
||||||
static struct spi_driver ld9040_driver = {
|
static struct spi_driver ld9040_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ld9040",
|
.name = "ld9040",
|
||||||
.bus = &spi_bus_type,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.probe = ld9040_probe,
|
.probe = ld9040_probe,
|
||||||
|
|
423
drivers/video/backlight/lm3533_bl.c
Normal file
423
drivers/video/backlight/lm3533_bl.c
Normal file
|
@ -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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
st = kzalloc(sizeof(struct lms283gf05_state), GFP_KERNEL);
|
st = devm_kzalloc(&spi->dev, sizeof(struct lms283gf05_state),
|
||||||
|
GFP_KERNEL);
|
||||||
if (st == NULL) {
|
if (st == NULL) {
|
||||||
dev_err(&spi->dev, "No memory for device state\n");
|
dev_err(&spi->dev, "No memory for device state\n");
|
||||||
ret = -ENOMEM;
|
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);
|
ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops);
|
||||||
if (IS_ERR(ld)) {
|
if (IS_ERR(ld)) {
|
||||||
ret = PTR_ERR(ld);
|
ret = PTR_ERR(ld);
|
||||||
goto err2;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
st->spi = spi;
|
st->spi = spi;
|
||||||
|
@ -193,8 +194,6 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err2:
|
|
||||||
kfree(st);
|
|
||||||
err:
|
err:
|
||||||
if (pdata != NULL)
|
if (pdata != NULL)
|
||||||
gpio_free(pdata->reset_gpio);
|
gpio_free(pdata->reset_gpio);
|
||||||
|
@ -212,8 +211,6 @@ static int __devexit lms283gf05_remove(struct spi_device *spi)
|
||||||
if (pdata != NULL)
|
if (pdata != NULL)
|
||||||
gpio_free(pdata->reset_gpio);
|
gpio_free(pdata->reset_gpio);
|
||||||
|
|
||||||
kfree(st);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,23 +232,20 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
|
||||||
struct lcd_device *ld;
|
struct lcd_device *ld;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lcd = kzalloc(sizeof(struct ltv350qv), GFP_KERNEL);
|
lcd = devm_kzalloc(&spi->dev, sizeof(struct ltv350qv), GFP_KERNEL);
|
||||||
if (!lcd)
|
if (!lcd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
lcd->spi = spi;
|
lcd->spi = spi;
|
||||||
lcd->power = FB_BLANK_POWERDOWN;
|
lcd->power = FB_BLANK_POWERDOWN;
|
||||||
lcd->buffer = kzalloc(8, GFP_KERNEL);
|
lcd->buffer = devm_kzalloc(&spi->dev, 8, GFP_KERNEL);
|
||||||
if (!lcd->buffer) {
|
if (!lcd->buffer)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out_free_lcd;
|
|
||||||
}
|
|
||||||
|
|
||||||
ld = lcd_device_register("ltv350qv", &spi->dev, lcd, <v_ops);
|
ld = lcd_device_register("ltv350qv", &spi->dev, lcd, <v_ops);
|
||||||
if (IS_ERR(ld)) {
|
if (IS_ERR(ld))
|
||||||
ret = PTR_ERR(ld);
|
return PTR_ERR(ld);
|
||||||
goto out_free_buffer;
|
|
||||||
}
|
|
||||||
lcd->ld = ld;
|
lcd->ld = ld;
|
||||||
|
|
||||||
ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK);
|
ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK);
|
||||||
|
@ -261,10 +258,6 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
|
||||||
|
|
||||||
out_unregister:
|
out_unregister:
|
||||||
lcd_device_unregister(ld);
|
lcd_device_unregister(ld);
|
||||||
out_free_buffer:
|
|
||||||
kfree(lcd->buffer);
|
|
||||||
out_free_lcd:
|
|
||||||
kfree(lcd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,8 +267,6 @@ static int __devexit ltv350qv_remove(struct spi_device *spi)
|
||||||
|
|
||||||
ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
|
ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
|
||||||
lcd_device_unregister(lcd->ld);
|
lcd_device_unregister(lcd->ld);
|
||||||
kfree(lcd->buffer);
|
|
||||||
kfree(lcd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +301,6 @@ static void ltv350qv_shutdown(struct spi_device *spi)
|
||||||
static struct spi_driver ltv350qv_driver = {
|
static struct spi_driver ltv350qv_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ltv350qv",
|
.name = "ltv350qv",
|
||||||
.bus = &spi_bus_type,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* 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/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -168,7 +170,7 @@ static int omapbl_probe(struct platform_device *pdev)
|
||||||
dev->props.brightness = pdata->default_intensity;
|
dev->props.brightness = pdata->default_intensity;
|
||||||
omapbl_update_status(dev);
|
omapbl_update_status(dev);
|
||||||
|
|
||||||
printk(KERN_INFO "OMAP LCD backlight initialised\n");
|
pr_info("OMAP LCD backlight initialised\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
|
||||||
if (!pcf_bl)
|
if (!pcf_bl)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memset(&bl_props, 0, sizeof(bl_props));
|
||||||
bl_props.type = BACKLIGHT_RAW;
|
bl_props.type = BACKLIGHT_RAW;
|
||||||
bl_props.max_brightness = 0x3f;
|
bl_props.max_brightness = 0x3f;
|
||||||
bl_props.power = FB_BLANK_UNBLANK;
|
bl_props.power = FB_BLANK_UNBLANK;
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.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);
|
pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
|
||||||
if (!pmu_dev) {
|
if (!pmu_dev) {
|
||||||
printk("ALI M7101 PMU not found.\n");
|
pr_err("ALI M7101 PMU not found.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
|
sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
|
||||||
if (!sb_dev) {
|
if (!sb_dev) {
|
||||||
printk("ALI 1533 SB not found.\n");
|
pr_err("ALI 1533 SB not found.\n");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto put_pmu;
|
goto put_pmu;
|
||||||
}
|
}
|
||||||
|
|
|
@ -741,7 +741,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
||||||
struct backlight_device *bd = NULL;
|
struct backlight_device *bd = NULL;
|
||||||
struct backlight_properties props;
|
struct backlight_properties props;
|
||||||
|
|
||||||
lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
|
lcd = devm_kzalloc(&spi->dev, sizeof(struct s6e63m0), GFP_KERNEL);
|
||||||
if (!lcd)
|
if (!lcd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -751,7 +751,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
||||||
ret = spi_setup(spi);
|
ret = spi_setup(spi);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&spi->dev, "spi setup failed.\n");
|
dev_err(&spi->dev, "spi setup failed.\n");
|
||||||
goto out_free_lcd;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd->spi = spi;
|
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;
|
lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
|
||||||
if (!lcd->lcd_pd) {
|
if (!lcd->lcd_pd) {
|
||||||
dev_err(&spi->dev, "platform data is NULL.\n");
|
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);
|
ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops);
|
||||||
if (IS_ERR(ld)) {
|
if (IS_ERR(ld))
|
||||||
ret = PTR_ERR(ld);
|
return PTR_ERR(ld);
|
||||||
goto out_free_lcd;
|
|
||||||
}
|
|
||||||
|
|
||||||
lcd->ld = ld;
|
lcd->ld = ld;
|
||||||
|
|
||||||
|
@ -824,8 +822,6 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
|
||||||
|
|
||||||
out_lcd_unregister:
|
out_lcd_unregister:
|
||||||
lcd_device_unregister(ld);
|
lcd_device_unregister(ld);
|
||||||
out_free_lcd:
|
|
||||||
kfree(lcd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,7 +834,6 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
|
||||||
device_remove_file(&spi->dev, &dev_attr_gamma_mode);
|
device_remove_file(&spi->dev, &dev_attr_gamma_mode);
|
||||||
backlight_device_unregister(lcd->bd);
|
backlight_device_unregister(lcd->bd);
|
||||||
lcd_device_unregister(lcd->ld);
|
lcd_device_unregister(lcd->ld);
|
||||||
kfree(lcd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -899,7 +894,6 @@ static void s6e63m0_shutdown(struct spi_device *spi)
|
||||||
static struct spi_driver s6e63m0_driver = {
|
static struct spi_driver s6e63m0_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "s6e63m0",
|
.name = "s6e63m0",
|
||||||
.bus = &spi_bus_type,
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.probe = s6e63m0_probe,
|
.probe = s6e63m0_probe,
|
||||||
|
|
|
@ -349,7 +349,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
lcd = kzalloc(sizeof(struct tdo24m), GFP_KERNEL);
|
lcd = devm_kzalloc(&spi->dev, sizeof(struct tdo24m), GFP_KERNEL);
|
||||||
if (!lcd)
|
if (!lcd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -357,11 +357,9 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
||||||
lcd->power = FB_BLANK_POWERDOWN;
|
lcd->power = FB_BLANK_POWERDOWN;
|
||||||
lcd->mode = MODE_VGA; /* default to VGA */
|
lcd->mode = MODE_VGA; /* default to VGA */
|
||||||
|
|
||||||
lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
|
lcd->buf = devm_kzalloc(&spi->dev, TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
|
||||||
if (lcd->buf == NULL) {
|
if (lcd->buf == NULL)
|
||||||
kfree(lcd);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
m = &lcd->msg;
|
m = &lcd->msg;
|
||||||
x = &lcd->xfer;
|
x = &lcd->xfer;
|
||||||
|
@ -383,15 +381,13 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&spi->dev, "Unsupported model");
|
dev_err(&spi->dev, "Unsupported model");
|
||||||
goto out_free;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
|
lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
|
||||||
lcd, &tdo24m_ops);
|
lcd, &tdo24m_ops);
|
||||||
if (IS_ERR(lcd->lcd_dev)) {
|
if (IS_ERR(lcd->lcd_dev))
|
||||||
err = PTR_ERR(lcd->lcd_dev);
|
return PTR_ERR(lcd->lcd_dev);
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_set_drvdata(&spi->dev, lcd);
|
dev_set_drvdata(&spi->dev, lcd);
|
||||||
err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
|
err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
|
||||||
|
@ -402,9 +398,6 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
|
||||||
|
|
||||||
out_unregister:
|
out_unregister:
|
||||||
lcd_device_unregister(lcd->lcd_dev);
|
lcd_device_unregister(lcd->lcd_dev);
|
||||||
out_free:
|
|
||||||
kfree(lcd->buf);
|
|
||||||
kfree(lcd);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,8 +407,6 @@ static int __devexit tdo24m_remove(struct spi_device *spi)
|
||||||
|
|
||||||
tdo24m_power(lcd, FB_BLANK_POWERDOWN);
|
tdo24m_power(lcd, FB_BLANK_POWERDOWN);
|
||||||
lcd_device_unregister(lcd->lcd_dev);
|
lcd_device_unregister(lcd->lcd_dev);
|
||||||
kfree(lcd->buf);
|
|
||||||
kfree(lcd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,11 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct backlight_properties props;
|
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;
|
int ret = 0;
|
||||||
|
|
||||||
|
data = devm_kzalloc(&client->dev, sizeof(struct tosa_bl_data),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -92,7 +95,7 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
|
||||||
ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight");
|
ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight");
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
|
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);
|
ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -122,8 +125,6 @@ err_reg:
|
||||||
data->bl = NULL;
|
data->bl = NULL;
|
||||||
err_gpio_dir:
|
err_gpio_dir:
|
||||||
gpio_free(TOSA_GPIO_BL_C20MA);
|
gpio_free(TOSA_GPIO_BL_C20MA);
|
||||||
err_gpio_bl:
|
|
||||||
kfree(data);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +137,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client)
|
||||||
|
|
||||||
gpio_free(TOSA_GPIO_BL_C20MA);
|
gpio_free(TOSA_GPIO_BL_C20MA);
|
||||||
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,8 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
|
||||||
int ret;
|
int ret;
|
||||||
struct tosa_lcd_data *data;
|
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)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
|
||||||
|
|
||||||
ret = spi_setup(spi);
|
ret = spi_setup(spi);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_spi;
|
return ret;
|
||||||
|
|
||||||
data->spi = spi;
|
data->spi = spi;
|
||||||
dev_set_drvdata(&spi->dev, data);
|
dev_set_drvdata(&spi->dev, data);
|
||||||
|
@ -224,8 +225,6 @@ err_gpio_dir:
|
||||||
gpio_free(TOSA_GPIO_TG_ON);
|
gpio_free(TOSA_GPIO_TG_ON);
|
||||||
err_gpio_tg:
|
err_gpio_tg:
|
||||||
dev_set_drvdata(&spi->dev, NULL);
|
dev_set_drvdata(&spi->dev, NULL);
|
||||||
err_spi:
|
|
||||||
kfree(data);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +241,6 @@ static int __devexit tosa_lcd_remove(struct spi_device *spi)
|
||||||
|
|
||||||
gpio_free(TOSA_GPIO_TG_ON);
|
gpio_free(TOSA_GPIO_TG_ON);
|
||||||
dev_set_drvdata(&spi->dev, NULL);
|
dev_set_drvdata(&spi->dev, NULL);
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
|
||||||
data->current_brightness = 0;
|
data->current_brightness = 0;
|
||||||
data->isink_reg = isink_reg;
|
data->isink_reg = isink_reg;
|
||||||
|
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
props.type = BACKLIGHT_RAW;
|
props.type = BACKLIGHT_RAW;
|
||||||
props.max_brightness = max_isel;
|
props.max_brightness = max_isel;
|
||||||
bl = backlight_device_register("wm831x", &pdev->dev, data,
|
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
|
int
|
||||||
fb_blank(struct fb_info *info, int blank)
|
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)
|
if (blank > FB_BLANK_POWERDOWN)
|
||||||
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)
|
if (info->fbops->fb_blank)
|
||||||
ret = info->fbops->fb_blank(blank, info);
|
ret = info->fbops->fb_blank(blank, info);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
struct fb_event event;
|
|
||||||
|
|
||||||
event.info = info;
|
|
||||||
event.data = ␣
|
|
||||||
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
|
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;
|
return ret;
|
||||||
|
|
|
@ -532,6 +532,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
|
||||||
|
|
||||||
/*------- Backlight control --------*/
|
/*------- Backlight control --------*/
|
||||||
|
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
props.fb_blank = FB_BLANK_UNBLANK;
|
props.fb_blank = FB_BLANK_UNBLANK;
|
||||||
props.power = FB_BLANK_UNBLANK;
|
props.power = FB_BLANK_UNBLANK;
|
||||||
props.type = BACKLIGHT_RAW;
|
props.type = BACKLIGHT_RAW;
|
||||||
|
|
|
@ -292,7 +292,6 @@ static const struct inode_operations bad_inode_ops =
|
||||||
.getxattr = bad_inode_getxattr,
|
.getxattr = bad_inode_getxattr,
|
||||||
.listxattr = bad_inode_listxattr,
|
.listxattr = bad_inode_listxattr,
|
||||||
.removexattr = bad_inode_removexattr,
|
.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)
|
static int proc_oom_score(struct task_struct *task, char *buffer)
|
||||||
{
|
{
|
||||||
|
unsigned long totalpages = totalram_pages + total_swap_pages;
|
||||||
unsigned long points = 0;
|
unsigned long points = 0;
|
||||||
|
|
||||||
read_lock(&tasklist_lock);
|
read_lock(&tasklist_lock);
|
||||||
if (pid_alive(task))
|
if (pid_alive(task))
|
||||||
points = oom_badness(task, NULL, NULL,
|
points = oom_badness(task, NULL, NULL, totalpages) *
|
||||||
totalram_pages + total_swap_pages);
|
1000 / totalpages;
|
||||||
read_unlock(&tasklist_lock);
|
read_unlock(&tasklist_lock);
|
||||||
return sprintf(buffer, "%lu\n", points);
|
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' */
|
/* find the first VMA at or above 'addr' */
|
||||||
vma = find_vma(walk->mm, 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) {
|
for (; addr != end; addr += PAGE_SIZE) {
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
|
||||||
|
|
|
@ -445,6 +445,18 @@ static inline int pmd_write(pmd_t pmd)
|
||||||
#endif /* __HAVE_ARCH_PMD_WRITE */
|
#endif /* __HAVE_ARCH_PMD_WRITE */
|
||||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
#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
|
* 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
|
* 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
|
* undefined so behaving like if the pmd was none is safe (because it
|
||||||
* can return none anyway). The compiler level barrier() is critically
|
* can return none anyway). The compiler level barrier() is critically
|
||||||
* important to compute the two checks atomically on the same pmdval.
|
* 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)
|
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_read_atomic(pmd);
|
||||||
pmd_t pmdval = *pmd;
|
|
||||||
/*
|
/*
|
||||||
* The barrier will stabilize the pmdval in a register or on
|
* The barrier will stabilize the pmdval in a register or on
|
||||||
* the stack so that it will stop changing under the code.
|
* 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 += kdev_t.h
|
||||||
header-y += kernel.h
|
header-y += kernel.h
|
||||||
header-y += kernelcapi.h
|
header-y += kernelcapi.h
|
||||||
|
header-y += kernel-page-flags.h
|
||||||
header-y += keyboard.h
|
header-y += keyboard.h
|
||||||
header-y += keyctl.h
|
header-y += keyctl.h
|
||||||
header-y += l2tp.h
|
header-y += l2tp.h
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#ifndef _LINUX_APPLE_BL_H
|
#ifndef _LINUX_APPLE_BL_H
|
||||||
#define _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 int apple_bl_register(void);
|
||||||
extern void apple_bl_unregister(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,
|
extern int reserve_bootmem_generic(unsigned long addr, unsigned long size,
|
||||||
int flags);
|
int flags);
|
||||||
|
|
||||||
extern void *alloc_bootmem_section(unsigned long size,
|
|
||||||
unsigned long section_nr);
|
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
|
#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
|
||||||
extern void *alloc_remap(int nid, unsigned long size);
|
extern void *alloc_remap(int nid, unsigned long size);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -30,6 +30,13 @@ struct pt_regs;
|
||||||
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
|
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
|
||||||
#define BUILD_BUG_ON_NULL(e) ((void *)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.
|
* BUILD_BUG_ON - break compile if a condition is true.
|
||||||
* @condition: the condition which the compiler should know is false.
|
* @condition: the condition which the compiler should know is false.
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef _LINUX_COMPACTION_H
|
#ifndef _LINUX_COMPACTION_H
|
||||||
#define _LINUX_COMPACTION_H
|
#define _LINUX_COMPACTION_H
|
||||||
|
|
||||||
|
#include <linux/node.h>
|
||||||
|
|
||||||
/* Return values for compact_zone() and try_to_compact_pages() */
|
/* 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 */
|
/* compaction didn't start as it was not possible or direct reclaim was more suitable */
|
||||||
#define COMPACT_SKIPPED 0
|
#define COMPACT_SKIPPED 0
|
||||||
|
@ -11,6 +13,23 @@
|
||||||
/* The full zone was compacted */
|
/* The full zone was compacted */
|
||||||
#define COMPACT_COMPLETE 3
|
#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
|
#ifdef CONFIG_COMPACTION
|
||||||
extern int sysctl_compact_memory;
|
extern int sysctl_compact_memory;
|
||||||
extern int sysctl_compaction_handler(struct ctl_table *table, int write,
|
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
|
#define FB_EVENT_FB_UNBIND 0x0E
|
||||||
/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */
|
/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */
|
||||||
#define FB_EVENT_REMAP_ALL_CONSOLE 0x0F
|
#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_event {
|
||||||
struct fb_info *info;
|
struct fb_info *info;
|
||||||
|
|
|
@ -1681,7 +1681,6 @@ struct inode_operations {
|
||||||
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
|
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||||
int (*removexattr) (struct dentry *, const char *);
|
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,
|
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
|
||||||
u64 len);
|
u64 len);
|
||||||
} ____cacheline_aligned;
|
} ____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_MASK HPAGE_MASK
|
||||||
#define HPAGE_PMD_SIZE HPAGE_SIZE
|
#define HPAGE_PMD_SIZE HPAGE_SIZE
|
||||||
|
|
||||||
|
extern bool is_vma_temporary_stack(struct vm_area_struct *vma);
|
||||||
|
|
||||||
#define transparent_hugepage_enabled(__vma) \
|
#define transparent_hugepage_enabled(__vma) \
|
||||||
((transparent_hugepage_flags & \
|
((transparent_hugepage_flags & \
|
||||||
(1<<TRANSPARENT_HUGEPAGE_FLAG) || \
|
(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. */
|
/* 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(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);
|
extern int sprint_backtrace(char *buffer, unsigned long address);
|
||||||
|
|
||||||
/* Look up a kernel symbol and print it to the kernel messages. */
|
/* 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;
|
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)
|
static inline int sprint_backtrace(char *buffer, unsigned long addr)
|
||||||
{
|
{
|
||||||
*buffer = '\0';
|
*buffer = '\0';
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#define KPF_KSM 21
|
#define KPF_KSM 21
|
||||||
#define KPF_THP 22
|
#define KPF_THP 22
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
/* kernel hacking assistances
|
/* kernel hacking assistances
|
||||||
* WARNING: subject to change, never rely on them!
|
* WARNING: subject to change, never rely on them!
|
||||||
*/
|
*/
|
||||||
|
@ -44,4 +46,6 @@
|
||||||
#define KPF_ARCH 38
|
#define KPF_ARCH 38
|
||||||
#define KPF_UNCACHED 39
|
#define KPF_UNCACHED 39
|
||||||
|
|
||||||
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* LINUX_KERNEL_PAGE_FLAGS_H */
|
#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
|
/* 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 */
|
power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
|
||||||
int (*get_power)(struct lcd_device *);
|
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) */
|
/* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
|
||||||
int (*set_power)(struct lcd_device *, int power);
|
int (*set_power)(struct lcd_device *, int power);
|
||||||
/* Get the current contrast setting (0-max_contrast) */
|
/* 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
|
* @als2_resistor_sel: internal resistance from ALS2 input to ground
|
||||||
* @als_vmin: als input voltage calibrated for max brightness in mV
|
* @als_vmin: als input voltage calibrated for max brightness in mV
|
||||||
* @als_vmax: als input voltage calibrated for min 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)
|
* @pwm_data: PWM control functions (only valid when the mode is PWM)
|
||||||
*/
|
*/
|
||||||
struct lm3530_platform_data {
|
struct lm3530_platform_data {
|
||||||
|
|
|
@ -73,6 +73,8 @@ struct led_classdev {
|
||||||
struct led_trigger *trigger;
|
struct led_trigger *trigger;
|
||||||
struct list_head trig_list;
|
struct list_head trig_list;
|
||||||
void *trigger_data;
|
void *trigger_data;
|
||||||
|
/* true if activated - deactivate routine uses it to do cleanup */
|
||||||
|
bool activated;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue