Merge commit 'v2.6.37' into perf/core

Merge reason: Add the final .37 tree.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Ingo Molnar 2011-01-05 14:22:08 +01:00
commit aef1b9cef7
78 changed files with 725 additions and 754 deletions

View File

@ -18,7 +18,6 @@ prototypes:
char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
locking rules: locking rules:
none have BKL
dcache_lock rename_lock ->d_lock may block dcache_lock rename_lock ->d_lock may block
d_revalidate: no no no yes d_revalidate: no no no yes
d_hash no no no yes d_hash no no no yes
@ -42,18 +41,23 @@ ata *);
int (*rename) (struct inode *, struct dentry *, int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *); struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char __user *,int); int (*readlink) (struct dentry *, char __user *,int);
int (*follow_link) (struct dentry *, struct nameidata *); void * (*follow_link) (struct dentry *, struct nameidata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *); void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *); int (*permission) (struct inode *, int, struct nameidata *);
int (*check_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *); int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *); int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
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);
long (*fallocate)(struct inode *inode, int mode, loff_t offset, loff_t len);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
locking rules: locking rules:
all may block, none have BKL all may block
i_mutex(inode) i_mutex(inode)
lookup: yes lookup: yes
create: yes create: yes
@ -66,19 +70,24 @@ rmdir: yes (both) (see below)
rename: yes (all) (see below) rename: yes (all) (see below)
readlink: no readlink: no
follow_link: no follow_link: no
put_link: no
truncate: yes (see below) truncate: yes (see below)
setattr: yes setattr: yes
permission: no permission: no
check_acl: no
getattr: no getattr: no
setxattr: yes setxattr: yes
getxattr: no getxattr: no
listxattr: no listxattr: no
removexattr: yes removexattr: yes
truncate_range: yes
fallocate: no
fiemap: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim. victim.
cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
->truncate() is never called directly - it's a callback, not a ->truncate() is never called directly - it's a callback, not a
method. It's called by vmtruncate() - library function normally used by method. It's called by vmtruncate() - deprecated library function used by
->setattr(). Locking information above applies to that call (i.e. is ->setattr(). Locking information above applies to that call (i.e. is
inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been
passed). passed).
@ -91,7 +100,7 @@ prototypes:
struct inode *(*alloc_inode)(struct super_block *sb); struct inode *(*alloc_inode)(struct super_block *sb);
void (*destroy_inode)(struct inode *); void (*destroy_inode)(struct inode *);
void (*dirty_inode) (struct inode *); void (*dirty_inode) (struct inode *);
int (*write_inode) (struct inode *, int); int (*write_inode) (struct inode *, struct writeback_control *wbc);
int (*drop_inode) (struct inode *); int (*drop_inode) (struct inode *);
void (*evict_inode) (struct inode *); void (*evict_inode) (struct inode *);
void (*put_super) (struct super_block *); void (*put_super) (struct super_block *);
@ -105,10 +114,10 @@ prototypes:
int (*show_options)(struct seq_file *, struct vfsmount *); int (*show_options)(struct seq_file *, struct vfsmount *);
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
locking rules: locking rules:
All may block [not true, see below] All may block [not true, see below]
None have BKL
s_umount s_umount
alloc_inode: alloc_inode:
destroy_inode: destroy_inode:
@ -127,6 +136,7 @@ umount_begin: no
show_options: no (namespace_sem) show_options: no (namespace_sem)
quota_read: no (see below) quota_read: no (see below)
quota_write: no (see below) quota_write: no (see below)
bdev_try_to_free_page: no (see below)
->statfs() has s_umount (shared) when called by ustat(2) (native or ->statfs() has s_umount (shared) when called by ustat(2) (native or
compat), but that's an accident of bad API; s_umount is used to pin compat), but that's an accident of bad API; s_umount is used to pin
@ -139,19 +149,25 @@ be the only ones operating on the quota file by the quota code (via
dqio_sem) (unless an admin really wants to screw up something and dqio_sem) (unless an admin really wants to screw up something and
writes to quota files with quotas on). For other details about locking writes to quota files with quotas on). For other details about locking
see also dquot_operations section. see also dquot_operations section.
->bdev_try_to_free_page is called from the ->releasepage handler of
the block device inode. See there for more details.
--------------------------- file_system_type --------------------------- --------------------------- file_system_type ---------------------------
prototypes: prototypes:
int (*get_sb) (struct file_system_type *, int, int (*get_sb) (struct file_system_type *, int,
const char *, void *, struct vfsmount *); const char *, void *, struct vfsmount *);
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
void (*kill_sb) (struct super_block *); void (*kill_sb) (struct super_block *);
locking rules: locking rules:
may block BKL may block
get_sb yes no get_sb yes
kill_sb yes no mount yes
kill_sb yes
->get_sb() returns error or 0 with locked superblock attached to the vfsmount ->get_sb() returns error or 0 with locked superblock attached to the vfsmount
(exclusive on ->s_umount). (exclusive on ->s_umount).
->mount() returns ERR_PTR or the root dentry.
->kill_sb() takes a write-locked superblock, does all shutdown work on it, ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
unlocks and drops the reference. unlocks and drops the reference.
@ -176,27 +192,35 @@ prototypes:
void (*freepage)(struct page *); void (*freepage)(struct page *);
int (*direct_IO)(int, struct kiocb *, const struct iovec *iov, int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs); loff_t offset, unsigned long nr_segs);
int (*launder_page) (struct page *); int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
unsigned long *);
int (*migratepage)(struct address_space *, struct page *, struct page *);
int (*launder_page)(struct page *);
int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long);
int (*error_remove_page)(struct address_space *, struct page *);
locking rules: locking rules:
All except set_page_dirty and freepage may block All except set_page_dirty and freepage may block
BKL PageLocked(page) i_mutex PageLocked(page) i_mutex
writepage: no yes, unlocks (see below) writepage: yes, unlocks (see below)
readpage: no yes, unlocks readpage: yes, unlocks
sync_page: no maybe sync_page: maybe
writepages: no writepages:
set_page_dirty no no set_page_dirty no
readpages: no readpages:
write_begin: no locks the page yes write_begin: locks the page yes
write_end: no yes, unlocks yes write_end: yes, unlocks yes
perform_write: no n/a yes bmap:
bmap: no invalidatepage: yes
invalidatepage: no yes releasepage: yes
releasepage: no yes freepage: yes
freepage: no yes direct_IO:
direct_IO: no get_xip_mem: maybe
launder_page: no yes migratepage: yes (both)
launder_page: yes
is_partially_uptodate: yes
error_remove_page: yes
->write_begin(), ->write_end(), ->sync_page() and ->readpage() ->write_begin(), ->write_end(), ->sync_page() and ->readpage()
may be called from the request handler (/dev/loop). may be called from the request handler (/dev/loop).
@ -276,9 +300,8 @@ under spinlock (it cannot block) and is sometimes called with the page
not locked. not locked.
->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
filesystems and by the swapper. The latter will eventually go away. All filesystems and by the swapper. The latter will eventually go away. Please,
instances do not actually need the BKL. Please, keep it that way and don't keep it that way and don't breed new callers.
breed new callers.
->invalidatepage() is called when the filesystem must attempt to drop ->invalidatepage() is called when the filesystem must attempt to drop
some or all of the buffers from the page when it is being truncated. It some or all of the buffers from the page when it is being truncated. It
@ -299,47 +322,37 @@ cleaned, or an error value if not. Note that in order to prevent the page
getting mapped back in and redirtied, it needs to be kept locked getting mapped back in and redirtied, it needs to be kept locked
across the entire operation. across the entire operation.
Note: currently almost all instances of address_space methods are
using BKL for internal serialization and that's one of the worst sources
of contention. Normally they are calling library functions (in fs/buffer.c)
and pass foo_get_block() as a callback (on local block-based filesystems,
indeed). BKL is not needed for library stuff and is usually taken by
foo_get_block(). It's an overkill, since block bitmaps can be protected by
internal fs locking and real critical areas are much smaller than the areas
filesystems protect now.
----------------------- file_lock_operations ------------------------------ ----------------------- file_lock_operations ------------------------------
prototypes: prototypes:
void (*fl_insert)(struct file_lock *); /* lock insertion callback */
void (*fl_remove)(struct file_lock *); /* lock removal callback */
void (*fl_copy_lock)(struct file_lock *, struct file_lock *); void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
void (*fl_release_private)(struct file_lock *); void (*fl_release_private)(struct file_lock *);
locking rules: locking rules:
BKL may block file_lock_lock may block
fl_insert: yes no
fl_remove: yes no
fl_copy_lock: yes no fl_copy_lock: yes no
fl_release_private: yes yes fl_release_private: maybe no
----------------------- lock_manager_operations --------------------------- ----------------------- lock_manager_operations ---------------------------
prototypes: prototypes:
int (*fl_compare_owner)(struct file_lock *, struct file_lock *); int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
void (*fl_notify)(struct file_lock *); /* unblock callback */ void (*fl_notify)(struct file_lock *); /* unblock callback */
int (*fl_grant)(struct file_lock *, struct file_lock *, int);
void (*fl_release_private)(struct file_lock *); void (*fl_release_private)(struct file_lock *);
void (*fl_break)(struct file_lock *); /* break_lease callback */ void (*fl_break)(struct file_lock *); /* break_lease callback */
int (*fl_mylease)(struct file_lock *, struct file_lock *);
int (*fl_change)(struct file_lock **, int);
locking rules: locking rules:
BKL may block file_lock_lock may block
fl_compare_owner: yes no fl_compare_owner: yes no
fl_notify: yes no fl_notify: yes no
fl_release_private: yes yes fl_grant: no no
fl_release_private: maybe no
fl_break: yes no fl_break: yes no
fl_mylease: yes no
fl_change yes no
Currently only NFSD and NLM provide instances of this class. None of the
them block. If you have out-of-tree instances - please, show up. Locking
in that area will change.
--------------------------- buffer_head ----------------------------------- --------------------------- buffer_head -----------------------------------
prototypes: prototypes:
void (*b_end_io)(struct buffer_head *bh, int uptodate); void (*b_end_io)(struct buffer_head *bh, int uptodate);
@ -364,17 +377,17 @@ prototypes:
void (*swap_slot_free_notify) (struct block_device *, unsigned long); void (*swap_slot_free_notify) (struct block_device *, unsigned long);
locking rules: locking rules:
BKL bd_mutex bd_mutex
open: no yes open: yes
release: no yes release: yes
ioctl: no no ioctl: no
compat_ioctl: no no compat_ioctl: no
direct_access: no no direct_access: no
media_changed: no no media_changed: no
unlock_native_capacity: no no unlock_native_capacity: no
revalidate_disk: no no revalidate_disk: no
getgeo: no no getgeo: no
swap_slot_free_notify: no no (see below) swap_slot_free_notify: no (see below)
media_changed, unlock_native_capacity and revalidate_disk are called only from media_changed, unlock_native_capacity and revalidate_disk are called only from
check_disk_change(). check_disk_change().
@ -413,34 +426,21 @@ prototypes:
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long (*get_unmapped_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long); unsigned long, unsigned long, unsigned long);
int (*check_flags)(int); int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
}; };
locking rules: locking rules:
All may block. All may block except for ->setlease.
BKL No VFS locks held on entry except for ->fsync and ->setlease.
llseek: no (see below)
read: no ->fsync() has i_mutex on inode.
aio_read: no
write: no ->setlease has the file_list_lock held and must not sleep.
aio_write: no
readdir: no
poll: no
unlocked_ioctl: no
compat_ioctl: no
mmap: no
open: no
flush: no
release: no
fsync: no (see below)
aio_fsync: no
fasync: no
lock: yes
readv: no
writev: no
sendfile: no
sendpage: no
get_unmapped_area: no
check_flags: no
->llseek() locking has moved from llseek to the individual llseek ->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you implementations. If your fs is not using generic_file_llseek, you
@ -450,17 +450,10 @@ mutex or just to use i_size_read() instead.
Note: this does not protect the file->f_pos against concurrent modifications Note: this does not protect the file->f_pos against concurrent modifications
since this is something the userspace has to take care about. since this is something the userspace has to take care about.
Note: ext2_release() was *the* source of contention on fs-intensive ->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
loads and dropping BKL on ->release() helps to get rid of that (we still Most instances call fasync_helper(), which does that maintenance, so it's
grab BKL for cases when we close a file that had been opened r/w, but that not normally something one needs to worry about. Return values > 0 will be
can and should be done using the internal locking with smaller critical areas). mapped to zero in the VFS layer.
Current worst offender is ext2_get_block()...
->fasync() is called without BKL protection, and is responsible for
maintaining the FASYNC bit in filp->f_flags. Most instances call
fasync_helper(), which does that maintenance, so it's not normally
something one needs to worry about. Return values > 0 will be mapped to
zero in the VFS layer.
->readdir() and ->ioctl() on directories must be changed. Ideally we would ->readdir() and ->ioctl() on directories must be changed. Ideally we would
move ->readdir() to inode_operations and use a separate method for directory move ->readdir() to inode_operations and use a separate method for directory
@ -471,8 +464,6 @@ components. And there are other reasons why the current interface is a mess...
->read on directories probably must go away - we should just enforce -EISDIR ->read on directories probably must go away - we should just enforce -EISDIR
in sys_read() and friends. in sys_read() and friends.
->fsync() has i_mutex on inode.
--------------------------- dquot_operations ------------------------------- --------------------------- dquot_operations -------------------------------
prototypes: prototypes:
int (*write_dquot) (struct dquot *); int (*write_dquot) (struct dquot *);
@ -507,12 +498,12 @@ prototypes:
int (*access)(struct vm_area_struct *, unsigned long, void*, int, int); int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
locking rules: locking rules:
BKL mmap_sem PageLocked(page) mmap_sem PageLocked(page)
open: no yes open: yes
close: no yes close: yes
fault: no yes can return with page locked fault: yes can return with page locked
page_mkwrite: no yes can return with page locked page_mkwrite: yes can return with page locked
access: no yes access: yes
->fault() is called when a previously not present pte is about ->fault() is called when a previously not present pte is about
to be faulted in. The filesystem must find and return the page associated to be faulted in. The filesystem must find and return the page associated
@ -539,6 +530,3 @@ VM_IO | VM_PFNMAP VMAs.
(if you break something or notice that it is broken and do not fix it yourself (if you break something or notice that it is broken and do not fix it yourself
- at least put it here) - at least put it here)
ipc/shm.c::shm_delete() - may need BKL.
->read() and ->write() in many drivers are (probably) missing BKL.

View File

@ -1751,7 +1751,7 @@ and is between 256 and 4096 characters. It is defined in the file
nousb [USB] Disable the USB subsystem nousb [USB] Disable the USB subsystem
nowatchdog [KNL] Disable the lockup detector. nowatchdog [KNL] Disable the lockup detector (NMI watchdog).
nowb [ARM] nowb [ARM]

View File

@ -792,11 +792,14 @@ S: Maintained
ARM/NOMADIK ARCHITECTURE ARM/NOMADIK ARCHITECTURE
M: Alessandro Rubini <rubini@unipv.it> M: Alessandro Rubini <rubini@unipv.it>
M: Linus Walleij <linus.walleij@stericsson.com>
M: STEricsson <STEricsson_nomadik_linux@list.st.com> M: STEricsson <STEricsson_nomadik_linux@list.st.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-nomadik/ F: arch/arm/mach-nomadik/
F: arch/arm/plat-nomadik/ F: arch/arm/plat-nomadik/
F: drivers/i2c/busses/i2c-nomadik.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
M: Nelson Castillo <arhuaco@freaks-unidos.net> M: Nelson Castillo <arhuaco@freaks-unidos.net>
@ -998,12 +1001,24 @@ F: drivers/i2c/busses/i2c-stu300.c
F: drivers/rtc/rtc-coh901331.c F: drivers/rtc/rtc-coh901331.c
F: drivers/watchdog/coh901327_wdt.c F: drivers/watchdog/coh901327_wdt.c
F: drivers/dma/coh901318* F: drivers/dma/coh901318*
F: drivers/mfd/ab3100*
F: drivers/rtc/rtc-ab3100.c
F: drivers/rtc/rtc-coh901331.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
ARM/U8500 ARM ARCHITECTURE ARM/Ux500 ARM ARCHITECTURE
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
M: Linus Walleij <linus.walleij@stericsson.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-ux500/ F: arch/arm/mach-ux500/
F: drivers/dma/ste_dma40*
F: drivers/mfd/ab3550*
F: drivers/mfd/abx500*
F: drivers/mfd/ab8500*
F: drivers/mfd/stmpe*
F: drivers/rtc/rtc-ab8500.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
ARM/VFP SUPPORT ARM/VFP SUPPORT
M: Russell King <linux@arm.linux.org.uk> M: Russell King <linux@arm.linux.org.uk>

View File

@ -1,7 +1,7 @@
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 37 SUBLEVEL = 37
EXTRAVERSION = -rc8 EXTRAVERSION =
NAME = Flesh-Eating Bats with Fangs NAME = Flesh-Eating Bats with Fangs
# *DOCUMENTATION* # *DOCUMENTATION*

View File

@ -76,6 +76,7 @@ extern unsigned long it8152_base_address;
IT8152_PD_IRQ(0) Audio controller (ACR) IT8152_PD_IRQ(0) Audio controller (ACR)
*/ */
#define IT8152_IRQ(x) (IRQ_BOARD_START + (x)) #define IT8152_IRQ(x) (IRQ_BOARD_START + (x))
#define IT8152_LAST_IRQ (IRQ_BOARD_START + 40)
/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */ /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
#define IT8152_LD_IRQ_COUNT 9 #define IT8152_LD_IRQ_COUNT 9

View File

@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page);
extern void *kmap_high_get(struct page *page); extern void *kmap_high_get(struct page *page);
extern void kunmap_high(struct page *page); extern void kunmap_high(struct page *page);
extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte);
extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
/* /*
* The following functions are already defined by <linux/highmem.h> * The following functions are already defined by <linux/highmem.h>
* when CONFIG_HIGHMEM is not set. * when CONFIG_HIGHMEM is not set.

View File

@ -13,9 +13,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* DO NOT EDIT!! - this file automatically generated
* from .s file by awk -f s2h.awk
*/
/* Size definitions /* Size definitions
* Copyright (C) ARM Limited 1998. All rights reserved. * Copyright (C) ARM Limited 1998. All rights reserved.
*/ */
@ -25,6 +22,9 @@
/* handy sizes */ /* handy sizes */
#define SZ_16 0x00000010 #define SZ_16 0x00000010
#define SZ_32 0x00000020
#define SZ_64 0x00000040
#define SZ_128 0x00000080
#define SZ_256 0x00000100 #define SZ_256 0x00000100
#define SZ_512 0x00000200 #define SZ_512 0x00000200

View File

@ -150,6 +150,7 @@ extern unsigned int user_debug;
#define rmb() dmb() #define rmb() dmb()
#define wmb() mb() #define wmb() mb()
#else #else
#include <asm/memory.h>
#define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) #define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
#define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) #define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
#define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) #define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)

View File

@ -29,6 +29,9 @@ ret_fast_syscall:
ldr r1, [tsk, #TI_FLAGS] ldr r1, [tsk, #TI_FLAGS]
tst r1, #_TIF_WORK_MASK tst r1, #_TIF_WORK_MASK
bne fast_work_pending bne fast_work_pending
#if defined(CONFIG_IRQSOFF_TRACER)
asm_trace_hardirqs_on
#endif
/* perform architecture specific actions before user return */ /* perform architecture specific actions before user return */
arch_ret_to_user r1, lr arch_ret_to_user r1, lr
@ -65,6 +68,9 @@ ret_slow_syscall:
tst r1, #_TIF_WORK_MASK tst r1, #_TIF_WORK_MASK
bne work_pending bne work_pending
no_work_pending: no_work_pending:
#if defined(CONFIG_IRQSOFF_TRACER)
asm_trace_hardirqs_on
#endif
/* perform architecture specific actions before user return */ /* perform architecture specific actions before user return */
arch_ret_to_user r1, lr arch_ret_to_user r1, lr

View File

@ -310,7 +310,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
* All kernel threads share the same mm context; grab a * All kernel threads share the same mm context; grab a
* reference and switch to it. * reference and switch to it.
*/ */
atomic_inc(&mm->mm_users);
atomic_inc(&mm->mm_count); atomic_inc(&mm->mm_count);
current->active_mm = mm; current->active_mm = mm;
cpumask_set_cpu(cpu, mm_cpumask(mm)); cpumask_set_cpu(cpu, mm_cpumask(mm));

View File

@ -540,6 +540,7 @@ config MACH_ICONTROL
config ARCH_PXA_ESERIES config ARCH_PXA_ESERIES
bool "PXA based Toshiba e-series PDAs" bool "PXA based Toshiba e-series PDAs"
select PXA25x select PXA25x
select FB_W100
config MACH_E330 config MACH_E330
bool "Toshiba e330" bool "Toshiba e330"

View File

@ -353,8 +353,8 @@ resume_turn_on_mmu:
@ Let us ensure we jump to resume_after_mmu only when the mcr above @ Let us ensure we jump to resume_after_mmu only when the mcr above
@ actually took effect. They call it the "cpwait" operation. @ actually took effect. They call it the "cpwait" operation.
mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15 mrc p15, 0, r0, c2, c0, 0 @ queue a dependency on CP15
sub pc, r2, r1, lsr #32 @ jump to virtual addr sub pc, r2, r0, lsr #32 @ jump to virtual addr
nop nop
nop nop
nop nop

View File

@ -13,13 +13,9 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/highmem.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/kmap_types.h>
#include <asm/fixmap.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <plat/cache-feroceon-l2.h> #include <plat/cache-feroceon-l2.h>
#include "mm.h"
/* /*
* Low-level cache maintenance operations. * Low-level cache maintenance operations.
@ -39,27 +35,30 @@
* between which we don't want to be preempted. * between which we don't want to be preempted.
*/ */
static inline unsigned long l2_start_va(unsigned long paddr) static inline unsigned long l2_get_va(unsigned long paddr)
{ {
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
/* /*
* Let's do our own fixmap stuff in a minimal way here.
* Because range ops can't be done on physical addresses, * Because range ops can't be done on physical addresses,
* we simply install a virtual mapping for it only for the * we simply install a virtual mapping for it only for the
* TLB lookup to occur, hence no need to flush the untouched * TLB lookup to occur, hence no need to flush the untouched
* memory mapping. This is protected with the disabling of * memory mapping afterwards (note: a cache flush may happen
* interrupts by the caller. * in some circumstances depending on the path taken in kunmap_atomic).
*/ */
unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT);
unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); return (unsigned long)vaddr + (paddr & ~PAGE_MASK);
set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
local_flush_tlb_kernel_page(vaddr);
return vaddr + (paddr & ~PAGE_MASK);
#else #else
return __phys_to_virt(paddr); return __phys_to_virt(paddr);
#endif #endif
} }
static inline void l2_put_va(unsigned long vaddr)
{
#ifdef CONFIG_HIGHMEM
kunmap_atomic((void *)vaddr);
#endif
}
static inline void l2_clean_pa(unsigned long addr) static inline void l2_clean_pa(unsigned long addr)
{ {
__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr)); __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
*/ */
BUG_ON((start ^ end) >> PAGE_SHIFT); BUG_ON((start ^ end) >> PAGE_SHIFT);
raw_local_irq_save(flags); va_start = l2_get_va(start);
va_start = l2_start_va(start);
va_end = va_start + (end - start); va_end = va_start + (end - start);
raw_local_irq_save(flags);
__asm__("mcr p15, 1, %0, c15, c9, 4\n\t" __asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
"mcr p15, 1, %1, c15, c9, 5" "mcr p15, 1, %1, c15, c9, 5"
: : "r" (va_start), "r" (va_end)); : : "r" (va_start), "r" (va_end));
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
l2_put_va(va_start);
} }
static inline void l2_clean_inv_pa(unsigned long addr) static inline void l2_clean_inv_pa(unsigned long addr)
@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
*/ */
BUG_ON((start ^ end) >> PAGE_SHIFT); BUG_ON((start ^ end) >> PAGE_SHIFT);
raw_local_irq_save(flags); va_start = l2_get_va(start);
va_start = l2_start_va(start);
va_end = va_start + (end - start); va_end = va_start + (end - start);
raw_local_irq_save(flags);
__asm__("mcr p15, 1, %0, c15, c11, 4\n\t" __asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
"mcr p15, 1, %1, c15, c11, 5" "mcr p15, 1, %1, c15, c11, 5"
: : "r" (va_start), "r" (va_end)); : : "r" (va_start), "r" (va_end));
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
l2_put_va(va_start);
} }
static inline void l2_inv_all(void) static inline void l2_inv_all(void)

View File

@ -17,14 +17,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/highmem.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/kmap_types.h>
#include <asm/fixmap.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include "mm.h"
#define CR_L2 (1 << 26) #define CR_L2 (1 << 26)
@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void)
dsb(); dsb();
} }
static inline void l2_unmap_va(unsigned long va)
{
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
#define l2_map_save_flags(x) raw_local_save_flags(x) if (va != -1)
#define l2_map_restore_flags(x) raw_local_irq_restore(x) kunmap_atomic((void *)va);
#else
#define l2_map_save_flags(x) ((x) = 0)
#define l2_map_restore_flags(x) ((void)(x))
#endif #endif
}
static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va)
unsigned long flags)
{ {
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
unsigned long va = prev_va & PAGE_MASK; unsigned long va = prev_va & PAGE_MASK;
@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
/* /*
* Switching to a new page. Because cache ops are * Switching to a new page. Because cache ops are
* using virtual addresses only, we must put a mapping * using virtual addresses only, we must put a mapping
* in place for it. We also enable interrupts for a * in place for it.
* short while and disable them again to protect this
* mapping.
*/ */
unsigned long idx; l2_unmap_va(prev_va);
raw_local_irq_restore(flags); va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT);
idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
va = __fix_to_virt(FIX_KMAP_BEGIN + idx);
raw_local_irq_restore(flags | PSR_I_BIT);
set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0);
local_flush_tlb_kernel_page(va);
} }
return va + (pa_offset >> (32 - PAGE_SHIFT)); return va + (pa_offset >> (32 - PAGE_SHIFT));
#else #else
@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
static void xsc3_l2_inv_range(unsigned long start, unsigned long end) static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
{ {
unsigned long vaddr, flags; unsigned long vaddr;
if (start == 0 && end == -1ul) { if (start == 0 && end == -1ul) {
xsc3_l2_inv_all(); xsc3_l2_inv_all();
@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
} }
vaddr = -1; /* to force the first mapping */ vaddr = -1; /* to force the first mapping */
l2_map_save_flags(flags);
/* /*
* Clean and invalidate partial first cache line. * Clean and invalidate partial first cache line.
*/ */
if (start & (CACHE_LINE_SIZE - 1)) { if (start & (CACHE_LINE_SIZE - 1)) {
vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags); vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr);
xsc3_l2_clean_mva(vaddr); xsc3_l2_clean_mva(vaddr);
xsc3_l2_inv_mva(vaddr); xsc3_l2_inv_mva(vaddr);
start = (start | (CACHE_LINE_SIZE - 1)) + 1; start = (start | (CACHE_LINE_SIZE - 1)) + 1;
@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
* Invalidate all full cache lines between 'start' and 'end'. * Invalidate all full cache lines between 'start' and 'end'.
*/ */
while (start < (end & ~(CACHE_LINE_SIZE - 1))) { while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
vaddr = l2_map_va(start, vaddr, flags); vaddr = l2_map_va(start, vaddr);
xsc3_l2_inv_mva(vaddr); xsc3_l2_inv_mva(vaddr);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
* Clean and invalidate partial last cache line. * Clean and invalidate partial last cache line.
*/ */
if (start < end) { if (start < end) {
vaddr = l2_map_va(start, vaddr, flags); vaddr = l2_map_va(start, vaddr);
xsc3_l2_clean_mva(vaddr); xsc3_l2_clean_mva(vaddr);
xsc3_l2_inv_mva(vaddr); xsc3_l2_inv_mva(vaddr);
} }
l2_map_restore_flags(flags); l2_unmap_va(vaddr);
dsb(); dsb();
} }
static void xsc3_l2_clean_range(unsigned long start, unsigned long end) static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
{ {
unsigned long vaddr, flags; unsigned long vaddr;
vaddr = -1; /* to force the first mapping */ vaddr = -1; /* to force the first mapping */
l2_map_save_flags(flags);
start &= ~(CACHE_LINE_SIZE - 1); start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) { while (start < end) {
vaddr = l2_map_va(start, vaddr, flags); vaddr = l2_map_va(start, vaddr);
xsc3_l2_clean_mva(vaddr); xsc3_l2_clean_mva(vaddr);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
l2_map_restore_flags(flags); l2_unmap_va(vaddr);
dsb(); dsb();
} }
@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void)
static void xsc3_l2_flush_range(unsigned long start, unsigned long end) static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
{ {
unsigned long vaddr, flags; unsigned long vaddr;
if (start == 0 && end == -1ul) { if (start == 0 && end == -1ul) {
xsc3_l2_flush_all(); xsc3_l2_flush_all();
@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
} }
vaddr = -1; /* to force the first mapping */ vaddr = -1; /* to force the first mapping */
l2_map_save_flags(flags);
start &= ~(CACHE_LINE_SIZE - 1); start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) { while (start < end) {
vaddr = l2_map_va(start, vaddr, flags); vaddr = l2_map_va(start, vaddr);
xsc3_l2_clean_mva(vaddr); xsc3_l2_clean_mva(vaddr);
xsc3_l2_inv_mva(vaddr); xsc3_l2_inv_mva(vaddr);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
l2_map_restore_flags(flags); l2_unmap_va(vaddr);
dsb(); dsb();
} }

View File

@ -17,6 +17,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/highmem.h>
#include <asm/memory.h> #include <asm/memory.h>
#include <asm/highmem.h> #include <asm/highmem.h>
@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
op(vaddr, len, dir); op(vaddr, len, dir);
kunmap_high(page); kunmap_high(page);
} else if (cache_is_vipt()) { } else if (cache_is_vipt()) {
pte_t saved_pte; /* unmapped pages might still be cached */
vaddr = kmap_high_l1_vipt(page, &saved_pte); vaddr = kmap_atomic(page);
op(vaddr + offset, len, dir); op(vaddr + offset, len, dir);
kunmap_high_l1_vipt(page, saved_pte); kunmap_atomic(vaddr);
} }
} else { } else {
vaddr = page_address(page) + offset; vaddr = page_address(page) + offset;

View File

@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/highmem.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/cachetype.h> #include <asm/cachetype.h>
@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
__cpuc_flush_dcache_area(addr, PAGE_SIZE); __cpuc_flush_dcache_area(addr, PAGE_SIZE);
kunmap_high(page); kunmap_high(page);
} else if (cache_is_vipt()) { } else if (cache_is_vipt()) {
pte_t saved_pte; /* unmapped pages might still be cached */
addr = kmap_high_l1_vipt(page, &saved_pte); addr = kmap_atomic(page);
__cpuc_flush_dcache_area(addr, PAGE_SIZE); __cpuc_flush_dcache_area(addr, PAGE_SIZE);
kunmap_high_l1_vipt(page, saved_pte); kunmap_atomic(addr);
} }
} }

View File

@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr)
pte = TOP_PTE(vaddr); pte = TOP_PTE(vaddr);
return pte_page(*pte); return pte_page(*pte);
} }
#ifdef CONFIG_CPU_CACHE_VIPT
#include <linux/percpu.h>
/*
* The VIVT cache of a highmem page is always flushed before the page
* is unmapped. Hence unmapped highmem pages need no cache maintenance
* in that case.
*
* However unmapped pages may still be cached with a VIPT cache, and
* it is not possible to perform cache maintenance on them using physical
* addresses unfortunately. So we have no choice but to set up a temporary
* virtual mapping for that purpose.
*
* Yet this VIPT cache maintenance may be triggered from DMA support
* functions which are possibly called from interrupt context. As we don't
* want to keep interrupt disabled all the time when such maintenance is
* taking place, we therefore allow for some reentrancy by preserving and
* restoring the previous fixmap entry before the interrupted context is
* resumed. If the reentrancy depth is 0 then there is no need to restore
* the previous fixmap, and leaving the current one in place allow it to
* be reused the next time without a TLB flush (common with DMA).
*/
static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
{
unsigned int idx, cpu;
int *depth;
unsigned long vaddr, flags;
pte_t pte, *ptep;
if (!in_interrupt())
preempt_disable();
cpu = smp_processor_id();
depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
ptep = TOP_PTE(vaddr);
pte = mk_pte(page, kmap_prot);
raw_local_irq_save(flags);
(*depth)++;
if (pte_val(*ptep) == pte_val(pte)) {
*saved_pte = pte;
} else {
*saved_pte = *ptep;
set_pte_ext(ptep, pte, 0);
local_flush_tlb_kernel_page(vaddr);
}
raw_local_irq_restore(flags);
return (void *)vaddr;
}
void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte)
{
unsigned int idx, cpu = smp_processor_id();
int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
unsigned long vaddr, flags;
pte_t pte, *ptep;
idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
ptep = TOP_PTE(vaddr);
pte = mk_pte(page, kmap_prot);
BUG_ON(pte_val(*ptep) != pte_val(pte));
BUG_ON(*depth <= 0);
raw_local_irq_save(flags);
(*depth)--;
if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) {
set_pte_ext(ptep, saved_pte, 0);
local_flush_tlb_kernel_page(vaddr);
}
raw_local_irq_restore(flags);
if (!in_interrupt())
preempt_enable();
}
#endif /* CONFIG_CPU_CACHE_VIPT */

View File

@ -459,7 +459,7 @@ void migrate_irqs(void)
tmp = CROSS_GxICR(irq, new); tmp = CROSS_GxICR(irq, new);
x &= GxICR_LEVEL | GxICR_ENABLE; x &= GxICR_LEVEL | GxICR_ENABLE;
if (GxICR(irq) & GxICR_REQUEST) { if (GxICR(irq) & GxICR_REQUEST)
x |= GxICR_REQUEST | GxICR_DETECT; x |= GxICR_REQUEST | GxICR_DETECT;
CROSS_GxICR(irq, new) = x; CROSS_GxICR(irq, new) = x;
tmp = CROSS_GxICR(irq, new); tmp = CROSS_GxICR(irq, new);

View File

@ -575,6 +575,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
s->pics[1].elcr_mask = 0xde; s->pics[1].elcr_mask = 0xde;
s->pics[0].pics_state = s; s->pics[0].pics_state = s;
s->pics[1].pics_state = s; s->pics[1].pics_state = s;
s->pics[0].isr_ack = 0xff;
s->pics[1].isr_ack = 0xff;
/* /*
* Initialize PIO device * Initialize PIO device

View File

@ -2394,7 +2394,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
ASSERT(!VALID_PAGE(root)); ASSERT(!VALID_PAGE(root));
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_free_some_pages(vcpu); kvm_mmu_free_some_pages(vcpu);
sp = kvm_mmu_get_page(vcpu, i << 30, i << 30, sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
i << 30,
PT32_ROOT_LEVEL, 1, ACC_ALL, PT32_ROOT_LEVEL, 1, ACC_ALL,
NULL); NULL);
root = __pa(sp->spt); root = __pa(sp->spt);

View File

@ -637,21 +637,29 @@ static int __init_ibs_nmi(void)
return 0; return 0;
} }
/* initialize the APIC for the IBS interrupts if available */ /*
* check and reserve APIC extended interrupt LVT offset for IBS if
* available
*
* init_ibs() preforms implicitly cpu-local operations, so pin this
* thread to its current CPU
*/
static void init_ibs(void) static void init_ibs(void)
{ {
preempt_disable();
ibs_caps = get_ibs_caps(); ibs_caps = get_ibs_caps();
if (!ibs_caps) if (!ibs_caps)
return; goto out;
if (__init_ibs_nmi()) { if (__init_ibs_nmi() < 0)
ibs_caps = 0; ibs_caps = 0;
return; else
} printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", out:
(unsigned)ibs_caps); preempt_enable();
} }
static int (*create_arch_files)(struct super_block *sb, struct dentry *root); static int (*create_arch_files)(struct super_block *sb, struct dentry *root);

View File

@ -392,7 +392,10 @@ static int atmtcp_attach(struct atm_vcc *vcc,int itf)
atm_dev_put(dev); atm_dev_put(dev);
return -EMEDIUMTYPE; return -EMEDIUMTYPE;
} }
if (PRIV(dev)->vcc) return -EBUSY; if (PRIV(dev)->vcc) {
atm_dev_put(dev);
return -EBUSY;
}
} }
else { else {
int error; int error;

View File

@ -449,7 +449,7 @@ mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
static void mv_xor_tasklet(unsigned long data) static void mv_xor_tasklet(unsigned long data)
{ {
struct mv_xor_chan *chan = (struct mv_xor_chan *) data; struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
__mv_xor_slot_cleanup(chan); mv_xor_slot_cleanup(chan);
} }
static struct mv_xor_desc_slot * static struct mv_xor_desc_slot *

View File

@ -242,7 +242,7 @@ fail:
static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo) static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
{ {
return connector_status_unknown; return connector_status_connected;
} }
static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo, static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,

View File

@ -34,6 +34,7 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "../../../platform/x86/intel_ips.h"
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/vgaarb.h> #include <linux/vgaarb.h>
#include <linux/acpi.h> #include <linux/acpi.h>
@ -1870,6 +1871,26 @@ out_unlock:
} }
EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
/**
* Tells the intel_ips driver that the i915 driver is now loaded, if
* IPS got loaded first.
*
* This awkward dance is so that neither module has to depend on the
* other in order for IPS to do the appropriate communication of
* GPU turbo limits to i915.
*/
static void
ips_ping_for_i915_load(void)
{
void (*link)(void);
link = symbol_get(ips_link_to_i915_driver);
if (link) {
link();
symbol_put(ips_link_to_i915_driver);
}
}
/** /**
* i915_driver_load - setup chip and create an initial config * i915_driver_load - setup chip and create an initial config
* @dev: DRM device * @dev: DRM device
@ -2075,6 +2096,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->mchdev_lock = &mchdev_lock; dev_priv->mchdev_lock = &mchdev_lock;
spin_unlock(&mchdev_lock); spin_unlock(&mchdev_lock);
ips_ping_for_i915_load();
return 0; return 0;
out_workqueue_free: out_workqueue_free:

View File

@ -2471,6 +2471,9 @@
# define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18) # define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18)
# define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1) # define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1)
#define PCH_3DCGDIS1 0x46024
# define VFMUNIT_CLOCK_GATE_DISABLE (1 << 11)
#define FDI_PLL_FREQ_CTL 0x46030 #define FDI_PLL_FREQ_CTL 0x46030
#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24) #define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00 #define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
@ -2588,6 +2591,13 @@
#define ILK_DISPLAY_CHICKEN2 0x42004 #define ILK_DISPLAY_CHICKEN2 0x42004
#define ILK_DPARB_GATE (1<<22) #define ILK_DPARB_GATE (1<<22)
#define ILK_VSDPFD_FULL (1<<21) #define ILK_VSDPFD_FULL (1<<21)
#define ILK_DISPLAY_CHICKEN_FUSES 0x42014
#define ILK_INTERNAL_GRAPHICS_DISABLE (1<<31)
#define ILK_INTERNAL_DISPLAY_DISABLE (1<<30)
#define ILK_DISPLAY_DEBUG_DISABLE (1<<29)
#define ILK_HDCP_DISABLE (1<<25)
#define ILK_eDP_A_DISABLE (1<<24)
#define ILK_DESKTOP (1<<23)
#define ILK_DSPCLK_GATE 0x42020 #define ILK_DSPCLK_GATE 0x42020
#define ILK_DPARB_CLK_GATE (1<<5) #define ILK_DPARB_CLK_GATE (1<<5)
/* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */ /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */

View File

@ -270,7 +270,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
general->ssc_freq ? 66 : 48; general->ssc_freq ? 66 : 48;
else if (IS_GEN5(dev) || IS_GEN6(dev)) else if (IS_GEN5(dev) || IS_GEN6(dev))
dev_priv->lvds_ssc_freq = dev_priv->lvds_ssc_freq =
general->ssc_freq ? 120 : 100; general->ssc_freq ? 100 : 120;
else else
dev_priv->lvds_ssc_freq = dev_priv->lvds_ssc_freq =
general->ssc_freq ? 100 : 96; general->ssc_freq ? 100 : 96;

View File

@ -5379,6 +5379,23 @@ static int intel_encoder_clones(struct drm_device *dev, int type_mask)
return index_mask; return index_mask;
} }
static bool has_edp_a(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (!IS_MOBILE(dev))
return false;
if ((I915_READ(DP_A) & DP_DETECTED) == 0)
return false;
if (IS_GEN5(dev) &&
(I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
return false;
return true;
}
static void intel_setup_outputs(struct drm_device *dev) static void intel_setup_outputs(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
@ -5396,7 +5413,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
dpd_is_edp = intel_dpd_is_edp(dev); dpd_is_edp = intel_dpd_is_edp(dev);
if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED)) if (has_edp_a(dev))
intel_dp_init(dev, DP_A); intel_dp_init(dev, DP_A);
if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
@ -5825,6 +5842,8 @@ void intel_init_clock_gating(struct drm_device *dev)
I915_WRITE(PCH_3DCGDIS0, I915_WRITE(PCH_3DCGDIS0,
MARIUNIT_CLOCK_GATE_DISABLE | MARIUNIT_CLOCK_GATE_DISABLE |
SVSMUNIT_CLOCK_GATE_DISABLE); SVSMUNIT_CLOCK_GATE_DISABLE);
I915_WRITE(PCH_3DCGDIS1,
VFMUNIT_CLOCK_GATE_DISABLE);
} }
I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);

View File

@ -2040,13 +2040,14 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
SDVO_COLORIMETRY_RGB256); SDVO_COLORIMETRY_RGB256);
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
intel_sdvo->is_hdmi = true; intel_sdvo->is_hdmi = true;
} }
intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
(1 << INTEL_ANALOG_CLONE_BIT)); (1 << INTEL_ANALOG_CLONE_BIT));
intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
if (intel_sdvo->is_hdmi)
intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
return true; return true;
} }

View File

@ -234,7 +234,6 @@ static int s3c_hwmon_create_attr(struct device *dev,
attr->index = channel; attr->index = channel;
attr->dev_attr.attr.name = attrs->in_name; attr->dev_attr.attr.name = attrs->in_name;
attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.attr.mode = S_IRUGO;
attr->dev_attr.attr.owner = THIS_MODULE;
attr->dev_attr.show = s3c_hwmon_ch_show; attr->dev_attr.show = s3c_hwmon_ch_show;
ret = device_create_file(dev, &attr->dev_attr); ret = device_create_file(dev, &attr->dev_attr);
@ -252,7 +251,6 @@ static int s3c_hwmon_create_attr(struct device *dev,
attr->index = channel; attr->index = channel;
attr->dev_attr.attr.name = attrs->label_name; attr->dev_attr.attr.name = attrs->label_name;
attr->dev_attr.attr.mode = S_IRUGO; attr->dev_attr.attr.mode = S_IRUGO;
attr->dev_attr.attr.owner = THIS_MODULE;
attr->dev_attr.show = s3c_hwmon_label_show; attr->dev_attr.show = s3c_hwmon_label_show;
ret = device_create_file(dev, &attr->dev_attr); ret = device_create_file(dev, &attr->dev_attr);

View File

@ -1900,6 +1900,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
if (b3skb == NULL) { if (b3skb == NULL) {
dev_err(cs->dev, "%s: out of memory\n", __func__); dev_err(cs->dev, "%s: out of memory\n", __func__);
send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
kfree(b3cmsg);
return; return;
} }
capi_cmsg2message(b3cmsg, capi_cmsg2message(b3cmsg,

View File

@ -1989,8 +1989,23 @@ static int cx25840_probe(struct i2c_client *client,
v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops, v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
V4L2_CID_HUE, -128, 127, 1, 0); V4L2_CID_HUE, -128, 127, 1, 0);
if (!is_cx2583x(state)) { if (!is_cx2583x(state)) {
default_volume = 228 - cx25840_read(client, 0x8d4); default_volume = cx25840_read(client, 0x8d4);
default_volume = ((default_volume / 2) + 23) << 9; /*
* Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume
* scale mapping limits to avoid -ERANGE errors when
* initializing the volume control
*/
if (default_volume > 228) {
/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
default_volume = 228;
cx25840_write(client, 0x8d4, 228);
}
else if (default_volume < 20) {
/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
default_volume = 20;
cx25840_write(client, 0x8d4, 20);
}
default_volume = (((228 - default_volume) >> 1) + 23) << 9;
state->volume = v4l2_ctrl_new_std(&state->hdl, state->volume = v4l2_ctrl_new_std(&state->hdl,
&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,

View File

@ -40,7 +40,6 @@
#include <sound/control.h> #include <sound/control.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <media/wm8775.h>
#include "cx88.h" #include "cx88.h"
#include "cx88-reg.h" #include "cx88-reg.h"
@ -587,27 +586,6 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
int left, right, v, b; int left, right, v, b;
int changed = 0; int changed = 0;
u32 old; u32 old;
struct v4l2_control client_ctl;
/* Pass volume & balance onto any WM8775 */
if (value->value.integer.value[0] >= value->value.integer.value[1]) {
v = value->value.integer.value[0] << 10;
b = value->value.integer.value[0] ?
(0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] :
0x8000;
} else {
v = value->value.integer.value[1] << 10;
b = value->value.integer.value[1] ?
0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] :
0x8000;
}
client_ctl.value = v;
client_ctl.id = V4L2_CID_AUDIO_VOLUME;
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
client_ctl.value = b;
client_ctl.id = V4L2_CID_AUDIO_BALANCE;
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
left = value->value.integer.value[0] & 0x3f; left = value->value.integer.value[0] & 0x3f;
right = value->value.integer.value[1] & 0x3f; right = value->value.integer.value[1] & 0x3f;
@ -622,10 +600,10 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
old = cx_read(AUD_VOL_CTL); old = cx_read(AUD_VOL_CTL);
if (v != (old & 0x3f)) { if (v != (old & 0x3f)) {
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v); cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
changed = 1; changed = 1;
} }
if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) { if (cx_read(AUD_BAL_CTL) != b) {
cx_write(AUD_BAL_CTL, b); cx_write(AUD_BAL_CTL, b);
changed = 1; changed = 1;
} }
@ -640,7 +618,7 @@ static const struct snd_kcontrol_new snd_cx88_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ, SNDRV_CTL_ELEM_ACCESS_TLV_READ,
.name = "Analog-TV Volume", .name = "Playback Volume",
.info = snd_cx88_volume_info, .info = snd_cx88_volume_info,
.get = snd_cx88_volume_get, .get = snd_cx88_volume_get,
.put = snd_cx88_volume_put, .put = snd_cx88_volume_put,
@ -671,14 +649,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
vol = cx_read(AUD_VOL_CTL); vol = cx_read(AUD_VOL_CTL);
if (value->value.integer.value[0] != !(vol & bit)) { if (value->value.integer.value[0] != !(vol & bit)) {
vol ^= bit; vol ^= bit;
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); cx_write(AUD_VOL_CTL, vol);
/* Pass mute onto any WM8775 */
if ((1<<6) == bit) {
struct v4l2_control client_ctl;
client_ctl.value = 0 != (vol & bit);
client_ctl.id = V4L2_CID_AUDIO_MUTE;
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
}
ret = 1; ret = 1;
} }
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
@ -687,7 +658,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
static const struct snd_kcontrol_new snd_cx88_dac_switch = { static const struct snd_kcontrol_new snd_cx88_dac_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Audio-Out Switch", .name = "Playback Switch",
.info = snd_ctl_boolean_mono_info, .info = snd_ctl_boolean_mono_info,
.get = snd_cx88_switch_get, .get = snd_cx88_switch_get,
.put = snd_cx88_switch_put, .put = snd_cx88_switch_put,
@ -696,49 +667,13 @@ static const struct snd_kcontrol_new snd_cx88_dac_switch = {
static const struct snd_kcontrol_new snd_cx88_source_switch = { static const struct snd_kcontrol_new snd_cx88_source_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog-TV Switch", .name = "Capture Switch",
.info = snd_ctl_boolean_mono_info, .info = snd_ctl_boolean_mono_info,
.get = snd_cx88_switch_get, .get = snd_cx88_switch_get,
.put = snd_cx88_switch_put, .put = snd_cx88_switch_put,
.private_value = (1<<6), .private_value = (1<<6),
}; };
static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value)
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core = chip->core;
struct v4l2_control client_ctl;
client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
value->value.integer.value[0] = client_ctl.value ? 1 : 0;
return 0;
}
static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value)
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core = chip->core;
struct v4l2_control client_ctl;
client_ctl.value = 0 != value->value.integer.value[0];
client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
return 0;
}
static struct snd_kcontrol_new snd_cx88_alc_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line-In ALC Switch",
.info = snd_ctl_boolean_mono_info,
.get = snd_cx88_alc_get,
.put = snd_cx88_alc_put,
};
/**************************************************************************** /****************************************************************************
Basic Flow for Sound Devices Basic Flow for Sound Devices
****************************************************************************/ ****************************************************************************/
@ -860,7 +795,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
{ {
struct snd_card *card; struct snd_card *card;
snd_cx88_card_t *chip; snd_cx88_card_t *chip;
struct v4l2_subdev *sd;
int err; int err;
if (devno >= SNDRV_CARDS) if (devno >= SNDRV_CARDS)
@ -896,15 +830,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
if (err < 0) if (err < 0)
goto error; goto error;
/* If there's a wm8775 then add a Line-In ALC switch */
list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) {
if (WM8775_GID == sd->grp_id) {
snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch,
chip));
break;
}
}
strcpy (card->driver, "CX88x"); strcpy (card->driver, "CX88x");
sprintf(card->shortname, "Conexant CX%x", pci->device); sprintf(card->shortname, "Conexant CX%x", pci->device);
sprintf(card->longname, "%s at %#llx", sprintf(card->longname, "%s at %#llx",

View File

@ -1007,15 +1007,22 @@ static const struct cx88_board cx88_boards[] = {
.radio_type = UNSET, .radio_type = UNSET,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET,
.audio_chip = V4L2_IDENT_WM8775,
.input = {{ .input = {{
.type = CX88_VMUX_DVB, .type = CX88_VMUX_DVB,
.vmux = 0, .vmux = 0,
/* 2: Line-In */
.audioroute = 2,
},{ },{
.type = CX88_VMUX_COMPOSITE1, .type = CX88_VMUX_COMPOSITE1,
.vmux = 1, .vmux = 1,
/* 2: Line-In */
.audioroute = 2,
},{ },{
.type = CX88_VMUX_SVIDEO, .type = CX88_VMUX_SVIDEO,
.vmux = 2, .vmux = 2,
/* 2: Line-In */
.audioroute = 2,
}}, }},
.mpeg = CX88_MPEG_DVB, .mpeg = CX88_MPEG_DVB,
}, },

View File

@ -40,7 +40,6 @@
#include "cx88.h" #include "cx88.h"
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/wm8775.h>
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@ -977,7 +976,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
const struct cx88_ctrl *c = NULL; const struct cx88_ctrl *c = NULL;
u32 value,mask; u32 value,mask;
int i; int i;
struct v4l2_control client_ctl;
for (i = 0; i < CX8800_CTLS; i++) { for (i = 0; i < CX8800_CTLS; i++) {
if (cx8800_ctls[i].v.id == ctl->id) { if (cx8800_ctls[i].v.id == ctl->id) {
@ -991,27 +989,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
ctl->value = c->v.minimum; ctl->value = c->v.minimum;
if (ctl->value > c->v.maximum) if (ctl->value > c->v.maximum)
ctl->value = c->v.maximum; ctl->value = c->v.maximum;
/* Pass changes onto any WM8775 */
client_ctl.id = ctl->id;
switch (ctl->id) {
case V4L2_CID_AUDIO_MUTE:
client_ctl.value = ctl->value;
break;
case V4L2_CID_AUDIO_VOLUME:
client_ctl.value = (ctl->value) ?
(0x90 + ctl->value) << 8 : 0;
break;
case V4L2_CID_AUDIO_BALANCE:
client_ctl.value = ctl->value << 9;
break;
default:
client_ctl.id = 0;
break;
}
if (client_ctl.id)
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
mask=c->mask; mask=c->mask;
switch (ctl->id) { switch (ctl->id) {
case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BALANCE:
@ -1558,9 +1535,7 @@ static int radio_queryctrl (struct file *file, void *priv,
if (c->id < V4L2_CID_BASE || if (c->id < V4L2_CID_BASE ||
c->id >= V4L2_CID_LASTP1) c->id >= V4L2_CID_LASTP1)
return -EINVAL; return -EINVAL;
if (c->id == V4L2_CID_AUDIO_MUTE || if (c->id == V4L2_CID_AUDIO_MUTE) {
c->id == V4L2_CID_AUDIO_VOLUME ||
c->id == V4L2_CID_AUDIO_BALANCE) {
for (i = 0; i < CX8800_CTLS; i++) { for (i = 0; i < CX8800_CTLS; i++) {
if (cx8800_ctls[i].v.id == c->id) if (cx8800_ctls[i].v.id == c->id)
break; break;

View File

@ -398,19 +398,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
return container_of(v4l2_dev, struct cx88_core, v4l2_dev); return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
} }
#define call_hw(core, grpid, o, f, args...) \ #define call_all(core, o, f, args...) \
do { \ do { \
if (!core->i2c_rc) { \ if (!core->i2c_rc) { \
if (core->gate_ctrl) \ if (core->gate_ctrl) \
core->gate_ctrl(core, 1); \ core->gate_ctrl(core, 1); \
v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \ v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
if (core->gate_ctrl) \ if (core->gate_ctrl) \
core->gate_ctrl(core, 0); \ core->gate_ctrl(core, 0); \
} \ } \
} while (0) } while (0)
#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
struct cx8800_dev; struct cx8800_dev;
struct cx8802_dev; struct cx8802_dev;

View File

@ -2377,7 +2377,7 @@ static const struct v4l2_file_operations radio_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = em28xx_v4l2_open, .open = em28xx_v4l2_open,
.release = em28xx_v4l2_close, .release = em28xx_v4l2_close,
.ioctl = video_ioctl2, .unlocked_ioctl = video_ioctl2,
}; };
static const struct v4l2_ioctl_ops radio_ioctl_ops = { static const struct v4l2_ioctl_ops radio_ioctl_ops = {

View File

@ -35,7 +35,6 @@
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/wm8775.h>
MODULE_DESCRIPTION("wm8775 driver"); MODULE_DESCRIPTION("wm8775 driver");
MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
@ -51,16 +50,10 @@ enum {
TOT_REGS TOT_REGS
}; };
#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
#define ALC_EN 0x100 /* R17: ALC enable */
struct wm8775_state { struct wm8775_state {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *mute; struct v4l2_ctrl *mute;
struct v4l2_ctrl *vol;
struct v4l2_ctrl *bal;
struct v4l2_ctrl *loud;
u8 input; /* Last selected input (0-0xf) */ u8 input; /* Last selected input (0-0xf) */
}; };
@ -92,30 +85,6 @@ static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)
return -1; return -1;
} }
static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
{
struct wm8775_state *state = to_state(sd);
u8 vol_l, vol_r;
int muted = 0 != state->mute->val;
u16 volume = (u16)state->vol->val;
u16 balance = (u16)state->bal->val;
/* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
vol_l = (min(65536 - balance, 32768) * volume) >> 23;
vol_r = (min(balance, (u16)32768) * volume) >> 23;
/* Mute */
if (muted || quietly)
wm8775_write(sd, R21, 0x0c0 | state->input);
wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
/* Un-mute */
if (!muted)
wm8775_write(sd, R21, state->input);
}
static int wm8775_s_routing(struct v4l2_subdev *sd, static int wm8775_s_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config) u32 input, u32 output, u32 config)
{ {
@ -133,26 +102,25 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
state->input = input; state->input = input;
if (!v4l2_ctrl_g_ctrl(state->mute)) if (!v4l2_ctrl_g_ctrl(state->mute))
return 0; return 0;
if (!v4l2_ctrl_g_ctrl(state->vol)) wm8775_write(sd, R21, 0x0c0);
return 0; wm8775_write(sd, R14, 0x1d4);
if (!v4l2_ctrl_g_ctrl(state->bal)) wm8775_write(sd, R15, 0x1d4);
return 0; wm8775_write(sd, R21, 0x100 + state->input);
wm8775_set_audio(sd, 1);
return 0; return 0;
} }
static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl) static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct v4l2_subdev *sd = to_sd(ctrl); struct v4l2_subdev *sd = to_sd(ctrl);
struct wm8775_state *state = to_state(sd);
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
case V4L2_CID_AUDIO_VOLUME: wm8775_write(sd, R21, 0x0c0);
case V4L2_CID_AUDIO_BALANCE: wm8775_write(sd, R14, 0x1d4);
wm8775_set_audio(sd, 0); wm8775_write(sd, R15, 0x1d4);
return 0; if (!ctrl->val)
case V4L2_CID_AUDIO_LOUDNESS: wm8775_write(sd, R21, 0x100 + state->input);
wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
@ -176,7 +144,16 @@ static int wm8775_log_status(struct v4l2_subdev *sd)
static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
{ {
wm8775_set_audio(sd, 0); struct wm8775_state *state = to_state(sd);
/* If I remove this, then it can happen that I have no
sound the first time I tune from static to a valid channel.
It's difficult to reproduce and is almost certainly related
to the zero cross detect circuit. */
wm8775_write(sd, R21, 0x0c0);
wm8775_write(sd, R14, 0x1d4);
wm8775_write(sd, R15, 0x1d4);
wm8775_write(sd, R21, 0x100 + state->input);
return 0; return 0;
} }
@ -226,7 +203,6 @@ static int wm8775_probe(struct i2c_client *client,
{ {
struct wm8775_state *state; struct wm8775_state *state;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
int err;
/* Check if the adapter supports the needed features */ /* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@ -240,21 +216,15 @@ static int wm8775_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
sd = &state->sd; sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &wm8775_ops); v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
sd->grp_id = WM8775_GID; /* subdev group id */
state->input = 2; state->input = 2;
v4l2_ctrl_handler_init(&state->hdl, 4); v4l2_ctrl_handler_init(&state->hdl, 1);
state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops, state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
sd->ctrl_handler = &state->hdl; sd->ctrl_handler = &state->hdl;
err = state->hdl.error; if (state->hdl.error) {
if (err) { int err = state->hdl.error;
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state); kfree(state);
return err; return err;
@ -266,25 +236,29 @@ static int wm8775_probe(struct i2c_client *client,
wm8775_write(sd, R23, 0x000); wm8775_write(sd, R23, 0x000);
/* Disable zero cross detect timeout */ /* Disable zero cross detect timeout */
wm8775_write(sd, R7, 0x000); wm8775_write(sd, R7, 0x000);
/* HPF enable, I2S mode, 24-bit */ /* Left justified, 24-bit mode */
wm8775_write(sd, R11, 0x022); wm8775_write(sd, R11, 0x021);
/* Master mode, clock ratio 256fs */ /* Master mode, clock ratio 256fs */
wm8775_write(sd, R12, 0x102); wm8775_write(sd, R12, 0x102);
/* Powered up */ /* Powered up */
wm8775_write(sd, R13, 0x000); wm8775_write(sd, R13, 0x000);
/* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */ /* ADC gain +2.5dB, enable zero cross */
wm8775_write(sd, R16, 0x1bb); wm8775_write(sd, R14, 0x1d4);
/* Set ALC mode and hold time */ /* ADC gain +2.5dB, enable zero cross */
wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD); wm8775_write(sd, R15, 0x1d4);
/* ALC Stereo, ALC target level -1dB FS max gain +8dB */
wm8775_write(sd, R16, 0x1bf);
/* Enable gain control, use zero cross detection,
ALC hold time 42.6 ms */
wm8775_write(sd, R17, 0x185);
/* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */ /* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
wm8775_write(sd, R18, 0x0a2); wm8775_write(sd, R18, 0x0a2);
/* Enable noise gate, threshold -72dBfs */ /* Enable noise gate, threshold -72dBfs */
wm8775_write(sd, R19, 0x005); wm8775_write(sd, R19, 0x005);
/* Transient window 4ms, ALC min gain -5dB */ /* Transient window 4ms, lower PGA gain limit -1dB */
wm8775_write(sd, R20, 0x0fb); wm8775_write(sd, R20, 0x07a);
/* LRBOTH = 1, use input 2. */
wm8775_set_audio(sd, 1); /* set volume/mute/mux */ wm8775_write(sd, R21, 0x102);
return 0; return 0;
} }

View File

@ -3504,6 +3504,8 @@ static int atl1_set_ringparam(struct net_device *netdev,
struct atl1_rfd_ring rfd_old, rfd_new; struct atl1_rfd_ring rfd_old, rfd_new;
struct atl1_rrd_ring rrd_old, rrd_new; struct atl1_rrd_ring rrd_old, rrd_new;
struct atl1_ring_header rhdr_old, rhdr_new; struct atl1_ring_header rhdr_old, rhdr_new;
struct atl1_smb smb;
struct atl1_cmb cmb;
int err; int err;
tpd_old = adapter->tpd_ring; tpd_old = adapter->tpd_ring;
@ -3544,11 +3546,19 @@ static int atl1_set_ringparam(struct net_device *netdev,
adapter->rrd_ring = rrd_old; adapter->rrd_ring = rrd_old;
adapter->tpd_ring = tpd_old; adapter->tpd_ring = tpd_old;
adapter->ring_header = rhdr_old; adapter->ring_header = rhdr_old;
/*
* Save SMB and CMB, since atl1_free_ring_resources
* will clear them.
*/
smb = adapter->smb;
cmb = adapter->cmb;
atl1_free_ring_resources(adapter); atl1_free_ring_resources(adapter);
adapter->rfd_ring = rfd_new; adapter->rfd_ring = rfd_new;
adapter->rrd_ring = rrd_new; adapter->rrd_ring = rrd_new;
adapter->tpd_ring = tpd_new; adapter->tpd_ring = tpd_new;
adapter->ring_header = rhdr_new; adapter->ring_header = rhdr_new;
adapter->smb = smb;
adapter->cmb = cmb;
err = atl1_up(adapter); err = atl1_up(adapter);
if (err) if (err)

View File

@ -940,7 +940,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
&udev->l2_ring_map, &udev->l2_ring_map,
GFP_KERNEL | __GFP_COMP); GFP_KERNEL | __GFP_COMP);
if (!udev->l2_ring) if (!udev->l2_ring)
return -ENOMEM; goto err_udev;
udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size; udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size); udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
@ -948,7 +948,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
&udev->l2_buf_map, &udev->l2_buf_map,
GFP_KERNEL | __GFP_COMP); GFP_KERNEL | __GFP_COMP);
if (!udev->l2_buf) if (!udev->l2_buf)
return -ENOMEM; goto err_dma;
write_lock(&cnic_dev_lock); write_lock(&cnic_dev_lock);
list_add(&udev->list, &cnic_udev_list); list_add(&udev->list, &cnic_udev_list);
@ -959,6 +959,12 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
cp->udev = udev; cp->udev = udev;
return 0; return 0;
err_dma:
dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
udev->l2_ring, udev->l2_ring_map);
err_udev:
kfree(udev);
return -ENOMEM;
} }
static int cnic_init_uio(struct cnic_dev *dev) static int cnic_init_uio(struct cnic_dev *dev)

View File

@ -263,6 +263,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
static int ehea_set_flags(struct net_device *dev, u32 data) static int ehea_set_flags(struct net_device *dev, u32 data)
{ {
/* Avoid changing the VLAN flags */
if ((data & (ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN)) !=
(ethtool_op_get_flags(dev) & (ETH_FLAG_RXVLAN |
ETH_FLAG_TXVLAN))){
return -EINVAL;
}
return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO
| ETH_FLAG_TXVLAN | ETH_FLAG_TXVLAN
| ETH_FLAG_RXVLAN); | ETH_FLAG_RXVLAN);

View File

@ -1285,6 +1285,11 @@ ppp_push(struct ppp *ppp)
} }
#ifdef CONFIG_PPP_MULTILINK #ifdef CONFIG_PPP_MULTILINK
static bool mp_protocol_compress __read_mostly = true;
module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(mp_protocol_compress,
"compress protocol id in multilink fragments");
/* /*
* Divide a packet to be transmitted into fragments and * Divide a packet to be transmitted into fragments and
* send them out the individual links. * send them out the individual links.
@ -1347,10 +1352,10 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if (nfree == 0 || nfree < navail / 2) if (nfree == 0 || nfree < navail / 2)
return 0; /* can't take now, leave it in xmit_pending */ return 0; /* can't take now, leave it in xmit_pending */
/* Do protocol field compression (XXX this should be optional) */ /* Do protocol field compression */
p = skb->data; p = skb->data;
len = skb->len; len = skb->len;
if (*p == 0) { if (*p == 0 && mp_protocol_compress) {
++p; ++p;
--len; --len;
} }

View File

@ -412,7 +412,7 @@ static int skfp_driver_init(struct net_device *dev)
bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev, bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
bp->SharedMemSize, bp->SharedMemSize,
&bp->SharedMemDMA); &bp->SharedMemDMA);
if (!bp->SharedMemSize) { if (!bp->SharedMemAddr) {
printk("could not allocate mem for "); printk("could not allocate mem for ");
printk("hardware module: %ld byte\n", printk("hardware module: %ld byte\n",
bp->SharedMemSize); bp->SharedMemSize);

View File

@ -148,7 +148,7 @@ static int full_duplex[MAX_UNITS] = {0, };
* This SUCKS. * This SUCKS.
* We need a much better method to determine if dma_addr_t is 64-bit. * We need a much better method to determine if dma_addr_t is 64-bit.
*/ */
#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT)) #if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || (defined(CONFIG_MIPS) && ((defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || defined(CONFIG_64BIT))) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
/* 64-bit dma_addr_t */ /* 64-bit dma_addr_t */
#define ADDR_64BITS /* This chip uses 64 bit addresses. */ #define ADDR_64BITS /* This chip uses 64 bit addresses. */
#define netdrv_addr_t __le64 #define netdrv_addr_t __le64

View File

@ -12658,7 +12658,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
cnt = pci_read_vpd(tp->pdev, pos, cnt = pci_read_vpd(tp->pdev, pos,
TG3_NVM_VPD_LEN - pos, TG3_NVM_VPD_LEN - pos,
&vpd_data[pos]); &vpd_data[pos]);
if (cnt == -ETIMEDOUT || -EINTR) if (cnt == -ETIMEDOUT || cnt == -EINTR)
cnt = 0; cnt = 0;
else if (cnt < 0) else if (cnt < 0)
goto out_not_found; goto out_not_found;

View File

@ -75,6 +75,7 @@
#include <drm/i915_drm.h> #include <drm/i915_drm.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/processor.h> #include <asm/processor.h>
#include "intel_ips.h"
#define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32 #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
@ -245,6 +246,7 @@
#define thm_writel(off, val) writel((val), ips->regmap + (off)) #define thm_writel(off, val) writel((val), ips->regmap + (off))
static const int IPS_ADJUST_PERIOD = 5000; /* ms */ static const int IPS_ADJUST_PERIOD = 5000; /* ms */
static bool late_i915_load = false;
/* For initial average collection */ /* For initial average collection */
static const int IPS_SAMPLE_PERIOD = 200; /* ms */ static const int IPS_SAMPLE_PERIOD = 200; /* ms */
@ -339,6 +341,9 @@ struct ips_driver {
u64 orig_turbo_ratios; u64 orig_turbo_ratios;
}; };
static bool
ips_gpu_turbo_enabled(struct ips_driver *ips);
/** /**
* ips_cpu_busy - is CPU busy? * ips_cpu_busy - is CPU busy?
* @ips: IPS driver struct * @ips: IPS driver struct
@ -517,7 +522,7 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)
*/ */
static bool ips_gpu_busy(struct ips_driver *ips) static bool ips_gpu_busy(struct ips_driver *ips)
{ {
if (!ips->gpu_turbo_enabled) if (!ips_gpu_turbo_enabled(ips))
return false; return false;
return ips->gpu_busy(); return ips->gpu_busy();
@ -532,7 +537,7 @@ static bool ips_gpu_busy(struct ips_driver *ips)
*/ */
static void ips_gpu_raise(struct ips_driver *ips) static void ips_gpu_raise(struct ips_driver *ips)
{ {
if (!ips->gpu_turbo_enabled) if (!ips_gpu_turbo_enabled(ips))
return; return;
if (!ips->gpu_raise()) if (!ips->gpu_raise())
@ -549,7 +554,7 @@ static void ips_gpu_raise(struct ips_driver *ips)
*/ */
static void ips_gpu_lower(struct ips_driver *ips) static void ips_gpu_lower(struct ips_driver *ips)
{ {
if (!ips->gpu_turbo_enabled) if (!ips_gpu_turbo_enabled(ips))
return; return;
if (!ips->gpu_lower()) if (!ips->gpu_lower())
@ -1454,6 +1459,31 @@ out_err:
return false; return false;
} }
static bool
ips_gpu_turbo_enabled(struct ips_driver *ips)
{
if (!ips->gpu_busy && late_i915_load) {
if (ips_get_i915_syms(ips)) {
dev_info(&ips->dev->dev,
"i915 driver attached, reenabling gpu turbo\n");
ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS);
}
}
return ips->gpu_turbo_enabled;
}
void
ips_link_to_i915_driver()
{
/* We can't cleanly get at the various ips_driver structs from
* this caller (the i915 driver), so just set a flag saying
* that it's time to try getting the symbols again.
*/
late_i915_load = true;
}
EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2010 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*/
void ips_link_to_i915_driver(void);

View File

@ -317,7 +317,7 @@ static void mcfqspi_work(struct work_struct *work)
msg = container_of(mcfqspi->msgq.next, struct spi_message, msg = container_of(mcfqspi->msgq.next, struct spi_message,
queue); queue);
list_del_init(&mcfqspi->msgq); list_del_init(&msg->queue);
spin_unlock_irqrestore(&mcfqspi->lock, flags); spin_unlock_irqrestore(&mcfqspi->lock, flags);
spi = msg->spi; spi = msg->spi;

View File

@ -1305,10 +1305,49 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */ /* work with hotplug and coldplug */
MODULE_ALIAS("platform:omap2_mcspi"); MODULE_ALIAS("platform:omap2_mcspi");
#ifdef CONFIG_SUSPEND
/*
* When SPI wake up from off-mode, CS is in activate state. If it was in
* unactive state when driver was suspend, then force it to unactive state at
* wake up.
*/
static int omap2_mcspi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
struct omap2_mcspi_cs *cs;
omap2_mcspi_enable_clocks(mcspi);
list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
node) {
if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
/*
* We need to toggle CS state for OMAP take this
* change in account.
*/
MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
}
}
omap2_mcspi_disable_clocks(mcspi);
return 0;
}
#else
#define omap2_mcspi_resume NULL
#endif
static const struct dev_pm_ops omap2_mcspi_pm_ops = {
.resume = omap2_mcspi_resume,
};
static struct platform_driver omap2_mcspi_driver = { static struct platform_driver omap2_mcspi_driver = {
.driver = { .driver = {
.name = "omap2_mcspi", .name = "omap2_mcspi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &omap2_mcspi_pm_ops
}, },
.remove = __exit_p(omap2_mcspi_remove), .remove = __exit_p(omap2_mcspi_remove),
}; };

View File

@ -435,12 +435,6 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
int ret = 0; int ret = 0;
struct zram *zram = queue->queuedata; struct zram *zram = queue->queuedata;
if (unlikely(!zram->init_done)) {
set_bit(BIO_UPTODATE, &bio->bi_flags);
bio_endio(bio, 0);
return 0;
}
if (!valid_io_request(zram, bio)) { if (!valid_io_request(zram, bio)) {
zram_stat64_inc(zram, &zram->stats.invalid_io); zram_stat64_inc(zram, &zram->stats.invalid_io);
bio_io_error(bio); bio_io_error(bio);

View File

@ -2206,8 +2206,11 @@ static int uea_boot(struct uea_softc *sc)
goto err1; goto err1;
} }
sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm"); /* Create worker thread, but don't start it here. Start it after
if (sc->kthread == ERR_PTR(-ENOMEM)) { * all usbatm generic initialization is done.
*/
sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
if (IS_ERR(sc->kthread)) {
uea_err(INS_TO_USBDEV(sc), "failed to create thread\n"); uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
goto err2; goto err2;
} }
@ -2624,6 +2627,7 @@ static struct usbatm_driver uea_usbatm_driver = {
static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
{ {
struct usb_device *usb = interface_to_usbdev(intf); struct usb_device *usb = interface_to_usbdev(intf);
int ret;
uea_enters(usb); uea_enters(usb);
uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n", uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n",
@ -2637,7 +2641,19 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (UEA_IS_PREFIRM(id)) if (UEA_IS_PREFIRM(id))
return uea_load_firmware(usb, UEA_CHIP_VERSION(id)); return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
return usbatm_usb_probe(intf, id, &uea_usbatm_driver); ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver);
if (ret == 0) {
struct usbatm_data *usbatm = usb_get_intfdata(intf);
struct uea_softc *sc = usbatm->driver_data;
/* Ensure carrier is initialized to off as early as possible */
UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST);
/* Only start the worker thread when all init is done */
wake_up_process(sc->kthread);
}
return ret;
} }
static void uea_disconnect(struct usb_interface *intf) static void uea_disconnect(struct usb_interface *intf)

View File

@ -824,6 +824,8 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
#ifdef CONFIG_DMA_ENGINE #ifdef CONFIG_DMA_ENGINE
enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void dma_issue_pending_all(void); void dma_issue_pending_all(void);
struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
void dma_release_channel(struct dma_chan *chan);
#else #else
static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
{ {
@ -831,7 +833,14 @@ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descript
} }
static inline void dma_issue_pending_all(void) static inline void dma_issue_pending_all(void)
{ {
do { } while (0); }
static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param)
{
return NULL;
}
static inline void dma_release_channel(struct dma_chan *chan)
{
} }
#endif #endif
@ -842,8 +851,6 @@ void dma_async_device_unregister(struct dma_device *device);
void dma_run_dependencies(struct dma_async_tx_descriptor *tx); void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
void dma_release_channel(struct dma_chan *chan);
/* --- Helper iov-locking functions --- */ /* --- Helper iov-locking functions --- */

View File

@ -32,7 +32,4 @@
#define WM8775_AIN3 4 #define WM8775_AIN3 4
#define WM8775_AIN4 8 #define WM8775_AIN4 8
/* subdev group ID */
#define WM8775_GID (1 << 0)
#endif #endif

View File

@ -93,7 +93,7 @@ no_match:
* *
* Returns the matching dev_t on success or 0 on failure. * Returns the matching dev_t on success or 0 on failure.
*/ */
static dev_t __init devt_from_partuuid(char *uuid_str) static dev_t devt_from_partuuid(char *uuid_str)
{ {
dev_t res = 0; dev_t res = 0;
struct device *dev = NULL; struct device *dev = NULL;

View File

@ -158,6 +158,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
spin_lock_irq(&uidhash_lock); spin_lock_irq(&uidhash_lock);
up = uid_hash_find(uid, hashent); up = uid_hash_find(uid, hashent);
if (up) { if (up) {
put_user_ns(ns);
key_put(new->uid_keyring); key_put(new->uid_keyring);
key_put(new->session_keyring); key_put(new->session_keyring);
kmem_cache_free(uid_cachep, new); kmem_cache_free(uid_cachep, new);

View File

@ -366,7 +366,8 @@ static int watchdog_nmi_enable(int cpu)
goto out_save; goto out_save;
} }
printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event); printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n",
cpu, PTR_ERR(event));
return PTR_ERR(event); return PTR_ERR(event);
/* success path */ /* success path */

View File

@ -1925,19 +1925,18 @@ again:
rcu_read_lock(); rcu_read_lock();
p = rcu_dereference(mm->owner); p = rcu_dereference(mm->owner);
VM_BUG_ON(!p);
/* /*
* because we don't have task_lock(), "p" can exit while * Because we don't have task_lock(), "p" can exit.
* we're here. In that case, "mem" can point to root * In that case, "mem" can point to root or p can be NULL with
* cgroup but never be NULL. (and task_struct itself is freed * race with swapoff. Then, we have small risk of mis-accouning.
* by RCU, cgroup itself is RCU safe.) Then, we have small * But such kind of mis-account by race always happens because
* risk here to get wrong cgroup. But such kind of mis-account * we don't have cgroup_mutex(). It's overkill and we allo that
* by race always happens because we don't have cgroup_mutex(). * small race, here.
* It's overkill and we allow that small race, here. * (*) swapoff at el will charge against mm-struct not against
* task-struct. So, mm->owner can be NULL.
*/ */
mem = mem_cgroup_from_task(p); mem = mem_cgroup_from_task(p);
VM_BUG_ON(!mem); if (!mem || mem_cgroup_is_root(mem)) {
if (mem_cgroup_is_root(mem)) {
rcu_read_unlock(); rcu_read_unlock();
goto done; goto done;
} }

View File

@ -1430,7 +1430,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
struct net_bridge_port *port, struct net_bridge_port *port,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct sk_buff *skb2 = skb; struct sk_buff *skb2;
struct ipv6hdr *ip6h; struct ipv6hdr *ip6h;
struct icmp6hdr *icmp6h; struct icmp6hdr *icmp6h;
u8 nexthdr; u8 nexthdr;
@ -1469,15 +1469,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
if (!skb2) if (!skb2)
return -ENOMEM; return -ENOMEM;
err = -EINVAL;
if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr)))
goto out;
len -= offset - skb_network_offset(skb2); len -= offset - skb_network_offset(skb2);
__skb_pull(skb2, offset); __skb_pull(skb2, offset);
skb_reset_transport_header(skb2); skb_reset_transport_header(skb2);
err = -EINVAL;
if (!pskb_may_pull(skb2, sizeof(*icmp6h)))
goto out;
icmp6h = icmp6_hdr(skb2); icmp6h = icmp6_hdr(skb2);
switch (icmp6h->icmp6_type) { switch (icmp6h->icmp6_type) {
@ -1516,7 +1516,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
switch (icmp6h->icmp6_type) { switch (icmp6h->icmp6_type) {
case ICMPV6_MGM_REPORT: case ICMPV6_MGM_REPORT:
{ {
struct mld_msg *mld = (struct mld_msg *)icmp6h; struct mld_msg *mld;
if (!pskb_may_pull(skb2, sizeof(*mld))) {
err = -EINVAL;
goto out;
}
mld = (struct mld_msg *)skb_transport_header(skb2);
BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
break; break;
@ -1529,14 +1534,17 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
break; break;
case ICMPV6_MGM_REDUCTION: case ICMPV6_MGM_REDUCTION:
{ {
struct mld_msg *mld = (struct mld_msg *)icmp6h; struct mld_msg *mld;
if (!pskb_may_pull(skb2, sizeof(*mld))) {
err = -EINVAL;
goto out;
}
mld = (struct mld_msg *)skb_transport_header(skb2);
br_ip6_multicast_leave_group(br, port, &mld->mld_mca); br_ip6_multicast_leave_group(br, port, &mld->mld_mca);
} }
} }
out: out:
__skb_push(skb2, offset);
if (skb2 != skb)
kfree_skb(skb2); kfree_skb(skb2);
return err; return err;
} }

View File

@ -50,6 +50,8 @@ static void br_send_bpdu(struct net_bridge_port *p,
llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr); llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr);
skb_reset_mac_header(skb);
NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit); dev_queue_xmit);
} }

View File

@ -125,7 +125,7 @@ struct bcm_sock {
struct list_head tx_ops; struct list_head tx_ops;
unsigned long dropped_usr_msgs; unsigned long dropped_usr_msgs;
struct proc_dir_entry *bcm_proc_read; struct proc_dir_entry *bcm_proc_read;
char procname [20]; /* pointer printed in ASCII with \0 */ char procname [32]; /* inode number in decimal with \0 */
}; };
static inline struct bcm_sock *bcm_sk(const struct sock *sk) static inline struct bcm_sock *bcm_sk(const struct sock *sk)
@ -1521,7 +1521,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
if (proc_dir) { if (proc_dir) {
/* unique socket address as filename */ /* unique socket address as filename */
sprintf(bo->procname, "%p", sock); sprintf(bo->procname, "%lu", sock_i_ino(sk));
bo->bcm_proc_read = proc_create_data(bo->procname, 0644, bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
proc_dir, proc_dir,
&bcm_proc_fops, sk); &bcm_proc_fops, sk);

View File

@ -2649,8 +2649,12 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
} }
if (res.type == RTN_LOCAL) { if (res.type == RTN_LOCAL) {
if (!fl.fl4_src) if (!fl.fl4_src) {
if (res.fi->fib_prefsrc)
fl.fl4_src = res.fi->fib_prefsrc;
else
fl.fl4_src = fl.fl4_dst; fl.fl4_src = fl.fl4_dst;
}
dev_out = net->loopback_dev; dev_out = net->loopback_dev;
fl.oif = dev_out->ifindex; fl.oif = dev_out->ifindex;
res.fi = NULL; res.fi = NULL;

View File

@ -140,6 +140,20 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
} }
if (current_entry->prompt && current_entry != &rootmenu) if (current_entry->prompt && current_entry != &rootmenu)
prop_warn(prop, "prompt redefined"); prop_warn(prop, "prompt redefined");
/* Apply all upper menus' visibilities to actual prompts. */
if(type == P_PROMPT) {
struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) {
if (!menu->visibility)
continue;
prop->visible.expr
= expr_alloc_and(prop->visible.expr,
menu->visibility);
}
}
current_entry->prompt = prop; current_entry->prompt = prop;
} }
prop->text = prompt; prop->text = prompt;

View File

@ -253,6 +253,8 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
result = security_filter_rule_init(entry->lsm[lsm_rule].type, result = security_filter_rule_init(entry->lsm[lsm_rule].type,
Audit_equal, args, Audit_equal, args,
&entry->lsm[lsm_rule].rule); &entry->lsm[lsm_rule].rule);
if (!entry->lsm[lsm_rule].rule)
return -EINVAL;
return result; return result;
} }

View File

@ -87,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)
int i, n; int i, n;
for (i = 0; i < num_mixer_volumes; i++) { for (i = 0; i < num_mixer_volumes; i++) {
if (strcmp(name, mixer_vols[i].name) == 0) { if (strncmp(name, mixer_vols[i].name, 32) == 0) {
if (present) if (present)
mixer_vols[i].num = i; mixer_vols[i].num = i;
return mixer_vols[i].levels; return mixer_vols[i].levels;
@ -99,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)
} }
n = num_mixer_volumes++; n = num_mixer_volumes++;
strcpy(mixer_vols[n].name, name); strncpy(mixer_vols[n].name, name, 32);
if (present) if (present)
mixer_vols[n].num = n; mixer_vols[n].num = n;

View File

@ -2300,6 +2300,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),

View File

@ -40,7 +40,6 @@ struct max98088_cdata {
}; };
struct max98088_priv { struct max98088_priv {
u8 reg_cache[M98088_REG_CNT];
enum max98088_type devtype; enum max98088_type devtype;
void *control_data; void *control_data;
struct max98088_pdata *pdata; struct max98088_pdata *pdata;
@ -1588,7 +1587,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
static void max98088_sync_cache(struct snd_soc_codec *codec) static void max98088_sync_cache(struct snd_soc_codec *codec)
{ {
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache;
int i; int i;
if (!codec->cache_sync) if (!codec->cache_sync)
@ -1599,14 +1598,14 @@ static void max98088_sync_cache(struct snd_soc_codec *codec)
/* write back cached values if they're writeable and /* write back cached values if they're writeable and
* different from the hardware default. * different from the hardware default.
*/ */
for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) { for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (!max98088_access[i].writable) if (!max98088_access[i].writable)
continue; continue;
if (max98088->reg_cache[i] == max98088_reg[i]) if (reg_cache[i] == max98088_reg[i])
continue; continue;
snd_soc_write(codec, i, max98088->reg_cache[i]); snd_soc_write(codec, i, reg_cache[i]);
} }
codec->cache_sync = 0; codec->cache_sync = 0;
@ -1951,7 +1950,6 @@ static int max98088_probe(struct snd_soc_codec *codec)
int ret = 0; int ret = 0;
codec->cache_sync = 1; codec->cache_sync = 1;
memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret != 0) { if (ret != 0) {

View File

@ -41,7 +41,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
/* codec private data */ /* codec private data */
struct wm8523_priv { struct wm8523_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
u16 reg_cache[WM8523_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
unsigned int sysclk; unsigned int sysclk;
unsigned int rate_constraint_list[WM8523_NUM_RATES]; unsigned int rate_constraint_list[WM8523_NUM_RATES];
@ -314,6 +313,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret, i; int ret, i;
switch (level) { switch (level) {
@ -344,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
/* Sync back default/cached values */ /* Sync back default/cached values */
for (i = WM8523_AIF_CTRL1; for (i = WM8523_AIF_CTRL1;
i < WM8523_MAX_REGISTER; i++) i < WM8523_MAX_REGISTER; i++)
snd_soc_write(codec, i, wm8523->reg_cache[i]); snd_soc_write(codec, i, reg_cache[i]);
msleep(100); msleep(100);
@ -414,6 +414,7 @@ static int wm8523_resume(struct snd_soc_codec *codec)
static int wm8523_probe(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec)
{ {
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret, i; int ret, i;
codec->hw_write = (hw_write_t)i2c_master_send; codec->hw_write = (hw_write_t)i2c_master_send;
@ -470,8 +471,8 @@ static int wm8523_probe(struct snd_soc_codec *codec)
} }
/* Change some default settings - latch VU and enable ZC */ /* Change some default settings - latch VU and enable ZC */
wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

View File

@ -41,7 +41,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
/* codec private data */ /* codec private data */
struct wm8741_priv { struct wm8741_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
u16 reg_cache[WM8741_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
unsigned int sysclk; unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints; struct snd_pcm_hw_constraint_list *sysclk_constraints;
@ -422,6 +421,7 @@ static int wm8741_resume(struct snd_soc_codec *codec)
static int wm8741_probe(struct snd_soc_codec *codec) static int wm8741_probe(struct snd_soc_codec *codec)
{ {
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret = 0; int ret = 0;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
@ -437,10 +437,10 @@ static int wm8741_probe(struct snd_soc_codec *codec)
} }
/* Change some default settings - latch VU */ /* Change some default settings - latch VU */
wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
snd_soc_add_controls(codec, wm8741_snd_controls, snd_soc_add_controls(codec, wm8741_snd_controls,
ARRAY_SIZE(wm8741_snd_controls)); ARRAY_SIZE(wm8741_snd_controls));

View File

@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
* are using 2 wire for device control, so we cache them instead. * are using 2 wire for device control, so we cache them instead.
*/ */
static const u16 wm8753_reg[] = { static const u16 wm8753_reg[] = {
0x0008, 0x0000, 0x000a, 0x000a, 0x0000, 0x0008, 0x0000, 0x000a,
0x0033, 0x0000, 0x0007, 0x00ff, 0x000a, 0x0033, 0x0000, 0x0007,
0x00ff, 0x000f, 0x000f, 0x007b, 0x00ff, 0x00ff, 0x000f, 0x000f,
0x0000, 0x0032, 0x0000, 0x00c3, 0x007b, 0x0000, 0x0032, 0x0000,
0x00c3, 0x00c0, 0x0000, 0x0000, 0x00c3, 0x00c3, 0x00c0, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0055, 0x0000, 0x0000, 0x0000, 0x0000,
0x0005, 0x0050, 0x0055, 0x0050, 0x0055, 0x0005, 0x0050, 0x0055,
0x0055, 0x0050, 0x0055, 0x0079, 0x0050, 0x0055, 0x0050, 0x0055,
0x0079, 0x0079, 0x0079, 0x0079, 0x0079, 0x0079, 0x0079, 0x0079,
0x0000, 0x0000, 0x0000, 0x0000, 0x0079, 0x0000, 0x0000, 0x0000,
0x0097, 0x0097, 0x0000, 0x0004, 0x0000, 0x0097, 0x0097, 0x0000,
0x0000, 0x0083, 0x0024, 0x01ba, 0x0004, 0x0000, 0x0083, 0x0024,
0x0000, 0x0083, 0x0024, 0x01ba, 0x01ba, 0x0000, 0x0083, 0x0024,
0x0000, 0x0000, 0x0000 0x01ba, 0x0000, 0x0000, 0x0000
}; };
/* codec private data */ /* codec private data */
@ -88,57 +88,10 @@ struct wm8753_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
unsigned int sysclk; unsigned int sysclk;
unsigned int pcmclk; unsigned int pcmclk;
u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
int dai_func; int dai_func;
}; };
/* #define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
* read wm8753 register cache
*/
static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
return -1;
return cache[reg - 1];
}
/*
* write wm8753 register cache
*/
static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
return;
cache[reg - 1] = value;
}
/*
* write to the WM8753 register space
*/
static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8753_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
/* /*
* WM8753 Controls * WM8753 Controls
@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); int mode = snd_soc_read(codec, WM8753_IOCTL);
ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
return 0; return 0;
@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); int mode = snd_soc_read(codec, WM8753_IOCTL);
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
if (pll_id == WM8753_PLL1) { if (pll_id == WM8753_PLL1) {
offset = 0; offset = 0;
enable = 0x10; enable = 0x10;
reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;
} else { } else {
offset = 4; offset = 4;
enable = 0x8; enable = 0x8;
reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;
} }
if (!freq_in || !freq_out) { if (!freq_in || !freq_out) {
/* disable PLL */ /* disable PLL */
wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
wm8753_write(codec, WM8753_CLOCK, reg); snd_soc_write(codec, WM8753_CLOCK, reg);
return 0; return 0;
} else { } else {
u16 value = 0; u16 value = 0;
@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
/* set up N and K PLL divisor ratios */ /* set up N and K PLL divisor ratios */
/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);
/* bits 8:0 = PLL_K[17:9] */ /* bits 8:0 = PLL_K[17:9] */
value = (pll_div.k & 0x03fe00) >> 9; value = (pll_div.k & 0x03fe00) >> 9;
wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);
/* bits 8:0 = PLL_K[8:0] */ /* bits 8:0 = PLL_K[8:0] */
value = pll_div.k & 0x0001ff; value = pll_div.k & 0x0001ff;
wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);
/* set PLL as input and enable */ /* set PLL as input and enable */
wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
(pll_div.div2 << 3)); (pll_div.div2 << 3));
wm8753_write(codec, WM8753_CLOCK, reg | enable); snd_soc_write(codec, WM8753_CLOCK, reg | enable);
} }
return 0; return 0;
} }
@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;
/* interface format */ /* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_PCM, voice); snd_soc_write(codec, WM8753_PCM, voice);
return 0; return 0;
} }
@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3;
u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
/* bit size */ /* bit size */
switch (params_format(params)) { switch (params_format(params)) {
@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
/* sample rate */ /* sample rate */
if (params_rate(params) * 384 == wm8753->pcmclk) if (params_rate(params) * 384 == wm8753->pcmclk)
srate |= 0x80; srate |= 0x80;
wm8753_write(codec, WM8753_SRATE1, srate); snd_soc_write(codec, WM8753_SRATE1, srate);
wm8753_write(codec, WM8753_PCM, voice); snd_soc_write(codec, WM8753_PCM, voice);
return 0; return 0;
} }
@ -958,8 +911,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 voice, ioctl; u16 voice, ioctl;
voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_PCM, voice); snd_soc_write(codec, WM8753_PCM, voice);
wm8753_write(codec, WM8753_IOCTL, ioctl); snd_soc_write(codec, WM8753_IOCTL, ioctl);
return 0; return 0;
} }
@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) { switch (div_id) {
case WM8753_PCMDIV: case WM8753_PCMDIV:
reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f;
wm8753_write(codec, WM8753_CLOCK, reg | div); snd_soc_write(codec, WM8753_CLOCK, reg | div);
break; break;
case WM8753_BCLKDIV: case WM8753_BCLKDIV:
reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7;
wm8753_write(codec, WM8753_SRATE2, reg | div); snd_soc_write(codec, WM8753_SRATE2, reg | div);
break; break;
case WM8753_VXCLKDIV: case WM8753_VXCLKDIV:
reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f;
wm8753_write(codec, WM8753_SRATE2, reg | div); snd_soc_write(codec, WM8753_SRATE2, reg | div);
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;
/* interface format */ /* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_HIFI, hifi); snd_soc_write(codec, WM8753_HIFI, hifi);
return 0; return 0;
} }
@ -1085,8 +1038,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 ioctl, hifi; u16 ioctl, hifi;
hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;
/* set master/slave audio interface */ /* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8753_write(codec, WM8753_HIFI, hifi); snd_soc_write(codec, WM8753_HIFI, hifi);
wm8753_write(codec, WM8753_IOCTL, ioctl); snd_soc_write(codec, WM8753_IOCTL, ioctl);
return 0; return 0;
} }
@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0;
u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;
int coeff; int coeff;
/* is digital filter coefficient valid ? */ /* is digital filter coefficient valid ? */
@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
return coeff; return coeff;
} }
wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
coeff_div[coeff].usb); coeff_div[coeff].usb);
/* bit size */ /* bit size */
@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
break; break;
} }
wm8753_write(codec, WM8753_HIFI, hifi); snd_soc_write(codec, WM8753_HIFI, hifi);
return 0; return 0;
} }
@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock; u16 clock;
/* set clk source as pcmclk */ /* set clk source as pcmclk */
clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
wm8753_write(codec, WM8753_CLOCK, clock); snd_soc_write(codec, WM8753_CLOCK, clock);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL; return -EINVAL;
@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock; u16 clock;
/* set clk source as pcmclk */ /* set clk source as pcmclk */
clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
wm8753_write(codec, WM8753_CLOCK, clock); snd_soc_write(codec, WM8753_CLOCK, clock);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL; return -EINVAL;
@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 clock; u16 clock;
/* set clk source as mclk */ /* set clk source as mclk */
clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
wm8753_write(codec, WM8753_CLOCK, clock | 0x4); snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);
if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
return -EINVAL; return -EINVAL;
@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int wm8753_mute(struct snd_soc_dai *dai, int mute) static int wm8753_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
/* the digital mute covers the HiFi and Voice DAC's on the WM8753. /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
* make sure we check if they are not both active when we mute */ * make sure we check if they are not both active when we mute */
if (mute && wm8753->dai_func == 1) { if (mute && wm8753->dai_func == 1) {
if (!codec->active) if (!codec->active)
wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
} else { } else {
if (mute) if (mute)
wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
else else
wm8753_write(codec, WM8753_DAC, mute_reg); snd_soc_write(codec, WM8753_DAC, mute_reg);
} }
return 0; return 0;
@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
static int wm8753_set_bias_level(struct snd_soc_codec *codec, static int wm8753_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
/* set vmid to 50k and unmute dac */ /* set vmid to 50k and unmute dac */
wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
break; break;
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
/* set vmid to 5k for quick power up */ /* set vmid to 5k for quick power up */
wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* mute dac and set vmid to 500k, enable VREF */ /* mute dac and set vmid to 500k, enable VREF */
wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
wm8753_write(codec, WM8753_PWR1, 0x0001); snd_soc_write(codec, WM8753_PWR1, 0x0001);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
else else
dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
} }
wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);
} }
static void wm8753_work(struct work_struct *work) static void wm8753_work(struct work_struct *work)
@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8753_resume(struct snd_soc_codec *codec) static int wm8753_resume(struct snd_soc_codec *codec)
{ {
u16 *reg_cache = codec->reg_cache;
int i; int i;
u8 data[2];
u16 *cache = codec->reg_cache;
/* Sync reg_cache with the hardware */ /* Sync reg_cache with the hardware */
for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
if (i + 1 == WM8753_RESET) if (i == WM8753_RESET)
continue; continue;
/* No point in writing hardware default values back */ /* No point in writing hardware default values back */
if (cache[i] == wm8753_reg[i]) if (reg_cache[i] == wm8753_reg[i])
continue; continue;
data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); snd_soc_write(codec, i, reg_cache[i]);
data[1] = cache[i] & 0x00ff;
codec->hw_write(codec->control_data, data, 2);
} }
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork)
static int wm8753_probe(struct snd_soc_codec *codec) static int wm8753_probe(struct snd_soc_codec *codec)
{ {
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
int ret = 0, reg; int ret;
INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec)
msecs_to_jiffies(caps_charge)); msecs_to_jiffies(caps_charge));
/* set the update bits */ /* set the update bits */
reg = wm8753_read_reg_cache(codec, WM8753_LDAC); snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
wm8753_write(codec, WM8753_LDAC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_RDAC); snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
wm8753_write(codec, WM8753_RDAC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LADC); snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
wm8753_write(codec, WM8753_LADC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_RADC); snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
wm8753_write(codec, WM8753_RADC, reg | 0x0100); snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
snd_soc_add_controls(codec, wm8753_snd_controls, snd_soc_add_controls(codec, wm8753_snd_controls,
ARRAY_SIZE(wm8753_snd_controls)); ARRAY_SIZE(wm8753_snd_controls));

View File

@ -50,8 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
/* codec private data */ /* codec private data */
struct wm8904_priv { struct wm8904_priv {
u16 reg_cache[WM8904_MAX_REGISTER + 1];
enum wm8904_type devtype; enum wm8904_type devtype;
void *control_data; void *control_data;
@ -2094,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
static void wm8904_sync_cache(struct snd_soc_codec *codec) static void wm8904_sync_cache(struct snd_soc_codec *codec)
{ {
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache;
int i; int i;
if (!codec->cache_sync) if (!codec->cache_sync)
@ -2105,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec)
/* Sync back cached values if they're different from the /* Sync back cached values if they're different from the
* hardware default. * hardware default.
*/ */
for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (!wm8904_access[i].writable) if (!wm8904_access[i].writable)
continue; continue;
if (wm8904->reg_cache[i] == wm8904_reg[i]) if (reg_cache[i] == wm8904_reg[i])
continue; continue;
snd_soc_write(codec, i, wm8904->reg_cache[i]); snd_soc_write(codec, i, reg_cache[i]);
} }
codec->cache_sync = 0; codec->cache_sync = 0;
@ -2371,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
{ {
struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata; struct wm8904_pdata *pdata = wm8904->pdata;
u16 *reg_cache = codec->reg_cache;
int ret, i; int ret, i;
codec->cache_sync = 1; codec->cache_sync = 1;
@ -2437,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec)
} }
/* Change some default settings - latch VU and enable ZC */ /* Change some default settings - latch VU and enable ZC */
wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
WM8904_HPOUTLZC; WM8904_HPOUTLZC;
wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
WM8904_HPOUTRZC; WM8904_HPOUTRZC;
wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
WM8904_LINEOUTLZC; WM8904_LINEOUTLZC;
wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
WM8904_LINEOUTRZC; WM8904_LINEOUTRZC;
wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
/* Apply configuration from the platform data. */ /* Apply configuration from the platform data. */
if (wm8904->pdata) { if (wm8904->pdata) {
@ -2457,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec)
if (!pdata->gpio_cfg[i]) if (!pdata->gpio_cfg[i])
continue; continue;
wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] reg_cache[WM8904_GPIO_CONTROL_1 + i]
= pdata->gpio_cfg[i] & 0xffff; = pdata->gpio_cfg[i] & 0xffff;
} }
/* Zero is the default value for these anyway */ /* Zero is the default value for these anyway */
for (i = 0; i < WM8904_MIC_REGS; i++) for (i = 0; i < WM8904_MIC_REGS; i++)
wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
= pdata->mic_cfg[i]; = pdata->mic_cfg[i];
} }
/* Set Class W by default - this will be managed by the Class /* Set Class W by default - this will be managed by the Class
* G widget at runtime where bypass paths are available. * G widget at runtime where bypass paths are available.
*/ */
wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
/* Use normal bias source */ /* Use normal bias source */
wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

View File

@ -768,6 +768,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, wm8940); i2c_set_clientdata(i2c, wm8940);
wm8940->control_data = i2c; wm8940->control_data = i2c;
wm8940->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev, ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8940, &wm8940_dai, 1); &soc_codec_dev_wm8940, &wm8940_dai, 1);

View File

@ -42,8 +42,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
struct wm8955_priv { struct wm8955_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
u16 reg_cache[WM8955_MAX_REGISTER + 1];
unsigned int mclk_rate; unsigned int mclk_rate;
int deemph; int deemph;
@ -768,6 +766,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret, i; int ret, i;
switch (level) { switch (level) {
@ -800,14 +799,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
/* Sync back cached values if they're /* Sync back cached values if they're
* different from the hardware default. * different from the hardware default.
*/ */
for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) { for (i = 0; i < codec->driver->reg_cache_size; i++) {
if (i == WM8955_RESET) if (i == WM8955_RESET)
continue; continue;
if (wm8955->reg_cache[i] == wm8955_reg[i]) if (reg_cache[i] == wm8955_reg[i])
continue; continue;
snd_soc_write(codec, i, wm8955->reg_cache[i]); snd_soc_write(codec, i, reg_cache[i]);
} }
/* Enable VREF and VMID */ /* Enable VREF and VMID */
@ -902,6 +901,7 @@ static int wm8955_probe(struct snd_soc_codec *codec)
{ {
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
u16 *reg_cache = codec->reg_cache;
int ret, i; int ret, i;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
@ -934,25 +934,25 @@ static int wm8955_probe(struct snd_soc_codec *codec)
} }
/* Change some default settings - latch VU and enable ZC */ /* Change some default settings - latch VU and enable ZC */
wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
/* Also enable adaptive bass boost by default */ /* Also enable adaptive bass boost by default */
wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
/* Set platform data values */ /* Set platform data values */
if (pdata) { if (pdata) {
if (pdata->out2_speaker) if (pdata->out2_speaker)
wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] reg_cache[WM8955_ADDITIONAL_CONTROL_2]
|= WM8955_ROUT2INV; |= WM8955_ROUT2INV;
if (pdata->monoin_diff) if (pdata->monoin_diff)
wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] reg_cache[WM8955_MONO_OUT_MIX_1]
|= WM8955_DMEN; |= WM8955_DMEN;
} }
@ -1003,6 +1003,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(i2c, wm8955); i2c_set_clientdata(i2c, wm8955);
wm8955->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev, ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8955, &wm8955_dai, 1); &soc_codec_dev_wm8955, &wm8955_dai, 1);

View File

@ -1013,6 +1013,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(i2c, wm8960); i2c_set_clientdata(i2c, wm8960);
wm8960->control_type = SND_SOC_I2C;
wm8960->control_data = i2c; wm8960->control_data = i2c;
ret = snd_soc_register_codec(&i2c->dev, ret = snd_soc_register_codec(&i2c->dev,

View File

@ -52,8 +52,6 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
struct wm8962_priv { struct wm8962_priv {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
u16 reg_cache[WM8962_MAX_REGISTER + 1];
int sysclk; int sysclk;
int sysclk_rate; int sysclk_rate;
@ -1991,8 +1989,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache;
u16 *reg_cache = wm8962->reg_cache;
int ret; int ret;
/* Apply the update (if any) */ /* Apply the update (if any) */
@ -2020,8 +2017,7 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache;
u16 *reg_cache = wm8962->reg_cache;
int ret; int ret;
/* Apply the update (if any) */ /* Apply the update (if any) */
@ -2329,8 +2325,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol, int event)
{ {
struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = w->codec;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache;
u16 *reg_cache = wm8962->reg_cache;
int reg; int reg;
switch (w->shift) { switch (w->shift) {
@ -2719,7 +2714,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
static void wm8962_sync_cache(struct snd_soc_codec *codec) static void wm8962_sync_cache(struct snd_soc_codec *codec)
{ {
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache;
int i; int i;
if (!codec->cache_sync) if (!codec->cache_sync)
@ -2732,13 +2727,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec)
/* Sync back cached values if they're different from the /* Sync back cached values if they're different from the
* hardware default. * hardware default.
*/ */
for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (i == WM8962_SOFTWARE_RESET) if (i == WM8962_SOFTWARE_RESET)
continue; continue;
if (wm8962->reg_cache[i] == wm8962_reg[i]) if (reg_cache[i] == wm8962_reg[i])
continue; continue;
snd_soc_write(codec, i, wm8962->reg_cache[i]); snd_soc_write(codec, i, reg_cache[i]);
} }
codec->cache_sync = 0; codec->cache_sync = 0;
@ -3406,12 +3401,11 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int wm8962_resume(struct snd_soc_codec *codec) static int wm8962_resume(struct snd_soc_codec *codec)
{ {
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache; u16 *reg_cache = codec->reg_cache;
int i; int i;
/* Restore the registers */ /* Restore the registers */
for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { for (i = 1; i < codec->driver->reg_cache_size; i++) {
switch (i) { switch (i) {
case WM8962_SOFTWARE_RESET: case WM8962_SOFTWARE_RESET:
continue; continue;
@ -3705,6 +3699,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
dev); dev);
u16 *reg_cache = codec->reg_cache;
int i, trigger, irq_pol; int i, trigger, irq_pol;
wm8962->codec = codec; wm8962->codec = codec;
@ -3804,7 +3799,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
/* Put the speakers into mono mode? */ /* Put the speakers into mono mode? */
if (pdata->spk_mono) if (pdata->spk_mono)
wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2] reg_cache[WM8962_CLASS_D_CONTROL_2]
|= WM8962_SPK_MONO; |= WM8962_SPK_MONO;
/* Micbias setup, detection enable and detection /* Micbias setup, detection enable and detection
@ -3819,16 +3814,16 @@ static int wm8962_probe(struct snd_soc_codec *codec)
} }
/* Latch volume update bits */ /* Latch volume update bits */
wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
wm8962_add_widgets(codec); wm8962_add_widgets(codec);

View File

@ -718,6 +718,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
if (wm8971 == NULL) if (wm8971 == NULL)
return -ENOMEM; return -ENOMEM;
wm8971->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, wm8971); i2c_set_clientdata(i2c, wm8971);
ret = snd_soc_register_codec(&i2c->dev, ret = snd_soc_register_codec(&i2c->dev,

View File

@ -1335,6 +1335,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(i2c, wm9081); i2c_set_clientdata(i2c, wm9081);
wm9081->control_type = SND_SOC_I2C;
wm9081->control_data = i2c; wm9081->control_data = i2c;
ret = snd_soc_register_codec(&i2c->dev, ret = snd_soc_register_codec(&i2c->dev,

View File

@ -141,7 +141,6 @@ static const u16 wm9090_reg_defaults[] = {
/* This struct is used to save the context */ /* This struct is used to save the context */
struct wm9090_priv { struct wm9090_priv {
struct mutex mutex; struct mutex mutex;
u16 reg_cache[WM9090_MAX_REGISTER + 1];
struct wm9090_platform_data pdata; struct wm9090_platform_data pdata;
void *control_data; void *control_data;
}; };
@ -552,6 +551,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
static int wm9090_probe(struct snd_soc_codec *codec) static int wm9090_probe(struct snd_soc_codec *codec)
{ {
struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int ret; int ret;
codec->control_data = wm9090->control_data; codec->control_data = wm9090->control_data;
@ -576,22 +576,22 @@ static int wm9090_probe(struct snd_soc_codec *codec)
/* Configure some defaults; they will be written out when we /* Configure some defaults; they will be written out when we
* bring the bias up. * bring the bias up.
*/ */
wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
| WM9090_IN1A_ZC; | WM9090_IN1A_ZC;
wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
| WM9090_IN1B_ZC; | WM9090_IN1B_ZC;
wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
| WM9090_IN2A_ZC; | WM9090_IN2A_ZC;
wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
| WM9090_IN2B_ZC; | WM9090_IN2B_ZC;
wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

View File

@ -356,7 +356,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
int depth, int depth_mask, int period, int depth, int depth_mask, int period,
u64 total_samples, int hits, u64 total_samples, u64 hits,
int left_margin) int left_margin)
{ {
int i; int i;