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:
commit
aef1b9cef7
@ -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_copy_lock: yes no
|
||||||
fl_remove: yes no
|
fl_release_private: maybe no
|
||||||
fl_copy_lock: yes no
|
|
||||||
fl_release_private: yes yes
|
|
||||||
|
|
||||||
----------------------- 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_break: yes no
|
fl_release_private: maybe 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.
|
|
||||||
|
@ -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]
|
||||||
|
|
||||||
|
17
MAINTAINERS
17
MAINTAINERS
@ -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>
|
||||||
|
2
Makefile
2
Makefile
@ -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*
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 *
|
||||||
|
@ -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,
|
||||||
|
@ -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:
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,47 +586,26 @@ 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;
|
||||||
b = right - left;
|
b = right - left;
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
v = 0x3f - left;
|
v = 0x3f - left;
|
||||||
b = (-b) | 0x40;
|
b = (-b) | 0x40;
|
||||||
} else {
|
} else {
|
||||||
v = 0x3f - right;
|
v = 0x3f - right;
|
||||||
}
|
}
|
||||||
/* Do we really know this will always be called with IRQs on? */
|
/* Do we really know this will always be called with IRQs on? */
|
||||||
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;
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&chip->reg_lock);
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
|
||||||
@ -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",
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 = {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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), },
|
||||||
|
21
drivers/platform/x86/intel_ips.h
Normal file
21
drivers/platform/x86/intel_ips.h
Normal 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);
|
@ -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;
|
||||||
|
@ -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),
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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 --- */
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,15 +1534,18 @@ 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);
|
kfree_skb(skb2);
|
||||||
if (skb2 != skb)
|
|
||||||
kfree_skb(skb2);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
fl.fl4_src = fl.fl4_dst;
|
if (res.fi->fib_prefsrc)
|
||||||
|
fl.fl4_src = res.fi->fib_prefsrc;
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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),
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user