From 60b30db9a490782924bf5b8d85a3bdff49795f17 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 5 Dec 2010 19:42:30 -0300 Subject: [PATCH] --- yaml --- r: 223729 b: refs/heads/master c: f23b7952d37c69c0caa6c8dfb85dbf2eb9e5fcaa h: refs/heads/master i: 223727: e718fd69e601b381512c23307642b760f9a8ace2 v: v3 --- [refs] | 2 +- trunk/Documentation/filesystems/Locking | 214 +++++++++-------- trunk/arch/x86/kvm/i8259.c | 2 - trunk/arch/x86/kvm/mmu.c | 3 +- trunk/drivers/dma/mv_xor.c | 2 +- trunk/drivers/gpu/drm/i915/dvo_ch7017.c | 2 +- trunk/drivers/gpu/drm/i915/i915_dma.c | 23 -- trunk/drivers/gpu/drm/i915/i915_reg.h | 10 - trunk/drivers/gpu/drm/i915/intel_bios.c | 2 +- trunk/drivers/gpu/drm/i915/intel_display.c | 21 +- trunk/drivers/gpu/drm/i915/intel_sdvo.c | 3 +- trunk/drivers/hwmon/s3c-hwmon.c | 2 + .../media/video/cx25840/cx25840-core.c | 19 +- trunk/drivers/platform/x86/intel_ips.c | 36 +-- trunk/drivers/platform/x86/intel_ips.h | 21 -- trunk/drivers/spi/coldfire_qspi.c | 2 +- trunk/drivers/spi/omap2_mcspi.c | 39 --- trunk/drivers/staging/zram/zram_drv.c | 6 + trunk/include/linux/dmaengine.h | 13 +- trunk/init/do_mounts.c | 2 +- trunk/kernel/user.c | 1 - trunk/mm/memcontrol.c | 19 +- trunk/scripts/kconfig/menu.c | 14 -- trunk/sound/oss/soundcard.c | 4 +- trunk/sound/pci/hda/hda_intel.c | 1 - trunk/sound/soc/codecs/max98088.c | 10 +- trunk/sound/soc/codecs/wm8523.c | 9 +- trunk/sound/soc/codecs/wm8741.c | 10 +- trunk/sound/soc/codecs/wm8753.c | 226 +++++++++++------- trunk/sound/soc/codecs/wm8904.c | 37 +-- trunk/sound/soc/codecs/wm8940.c | 1 - trunk/sound/soc/codecs/wm8955.c | 31 ++- trunk/sound/soc/codecs/wm8960.c | 1 - trunk/sound/soc/codecs/wm8962.c | 45 ++-- trunk/sound/soc/codecs/wm8971.c | 1 - trunk/sound/soc/codecs/wm9081.c | 1 - trunk/sound/soc/codecs/wm9090.c | 18 +- 37 files changed, 390 insertions(+), 463 deletions(-) delete mode 100644 trunk/drivers/platform/x86/intel_ips.h diff --git a/[refs] b/[refs] index fd3e746c3494..fc8803802bab 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d45fa563a62c908d0e9a581d4f091fed6371ebd0 +refs/heads/master: f23b7952d37c69c0caa6c8dfb85dbf2eb9e5fcaa diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index 7686e7684495..b6426f15b4ae 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -18,6 +18,7 @@ prototypes: char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen); locking rules: + none have BKL dcache_lock rename_lock ->d_lock may block d_revalidate: no no no yes d_hash no no no yes @@ -41,23 +42,18 @@ ata *); int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char __user *,int); - void * (*follow_link) (struct dentry *, struct nameidata *); - void (*put_link) (struct dentry *, struct nameidata *, void *); + int (*follow_link) (struct dentry *, struct nameidata *); void (*truncate) (struct inode *); int (*permission) (struct inode *, int, struct nameidata *); - int (*check_acl)(struct inode *, int); int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); - void (*truncate_range)(struct inode *, loff_t, loff_t); - 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: - all may block + all may block, none have BKL i_mutex(inode) lookup: yes create: yes @@ -70,24 +66,19 @@ rmdir: yes (both) (see below) rename: yes (all) (see below) readlink: no follow_link: no -put_link: no truncate: yes (see below) setattr: yes permission: no -check_acl: no getattr: no setxattr: yes getxattr: no listxattr: no removexattr: yes -truncate_range: yes -fallocate: no -fiemap: no Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on victim. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. ->truncate() is never called directly - it's a callback, not a -method. It's called by vmtruncate() - deprecated library function used by +method. It's called by vmtruncate() - library function normally used by ->setattr(). Locking information above applies to that call (i.e. is inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been passed). @@ -100,7 +91,7 @@ prototypes: struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); void (*dirty_inode) (struct inode *); - int (*write_inode) (struct inode *, struct writeback_control *wbc); + int (*write_inode) (struct inode *, int); int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); @@ -114,11 +105,10 @@ prototypes: int (*show_options)(struct seq_file *, struct vfsmount *); 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); - int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t); - int (*trim_fs) (struct super_block *, struct fstrim_range *); locking rules: All may block [not true, see below] + None have BKL s_umount alloc_inode: destroy_inode: @@ -137,8 +127,6 @@ umount_begin: no show_options: no (namespace_sem) quota_read: no (see below) quota_write: no (see below) -bdev_try_to_free_page: no (see below) -trim_fs: no ->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 @@ -151,25 +139,19 @@ 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 writes to quota files with quotas on). For other details about locking 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 --------------------------- prototypes: int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *); - struct dentry *(*mount) (struct file_system_type *, int, - const char *, void *); void (*kill_sb) (struct super_block *); locking rules: - may block -get_sb yes -mount yes -kill_sb yes + may block BKL +get_sb yes no +kill_sb yes no ->get_sb() returns error or 0 with locked superblock attached to the vfsmount (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, unlocks and drops the reference. @@ -194,35 +176,27 @@ prototypes: void (*freepage)(struct page *); int (*direct_IO)(int, struct kiocb *, const struct iovec *iov, loff_t offset, unsigned long nr_segs); - 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 *); + int (*launder_page) (struct page *); locking rules: All except set_page_dirty and freepage may block - PageLocked(page) i_mutex -writepage: yes, unlocks (see below) -readpage: yes, unlocks -sync_page: maybe -writepages: -set_page_dirty no -readpages: -write_begin: locks the page yes -write_end: yes, unlocks yes -bmap: -invalidatepage: yes -releasepage: yes -freepage: yes -direct_IO: -get_xip_mem: maybe -migratepage: yes (both) -launder_page: yes -is_partially_uptodate: yes -error_remove_page: yes + BKL PageLocked(page) i_mutex +writepage: no yes, unlocks (see below) +readpage: no yes, unlocks +sync_page: no maybe +writepages: no +set_page_dirty no no +readpages: no +write_begin: no locks the page yes +write_end: no yes, unlocks yes +perform_write: no n/a yes +bmap: no +invalidatepage: no yes +releasepage: no yes +freepage: no yes +direct_IO: no +launder_page: no yes ->write_begin(), ->write_end(), ->sync_page() and ->readpage() may be called from the request handler (/dev/loop). @@ -302,8 +276,9 @@ under spinlock (it cannot block) and is sometimes called with the page not locked. ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some -filesystems and by the swapper. The latter will eventually go away. Please, -keep it that way and don't breed new callers. +filesystems and by the swapper. The latter will eventually go away. All +instances do not actually need the BKL. Please, keep it that way and don't +breed new callers. ->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 @@ -324,37 +299,47 @@ 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 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 ------------------------------ 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_release_private)(struct file_lock *); locking rules: - file_lock_lock may block -fl_copy_lock: yes no -fl_release_private: maybe no + BKL may block +fl_insert: yes no +fl_remove: yes no +fl_copy_lock: yes no +fl_release_private: yes yes ----------------------- lock_manager_operations --------------------------- prototypes: int (*fl_compare_owner)(struct file_lock *, struct file_lock *); 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_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: - file_lock_lock may block -fl_compare_owner: yes no -fl_notify: yes no -fl_grant: no no -fl_release_private: maybe no -fl_break: yes no -fl_mylease: yes no -fl_change yes no - + BKL may block +fl_compare_owner: yes no +fl_notify: yes no +fl_release_private: yes yes +fl_break: 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 ----------------------------------- prototypes: void (*b_end_io)(struct buffer_head *bh, int uptodate); @@ -379,17 +364,17 @@ prototypes: void (*swap_slot_free_notify) (struct block_device *, unsigned long); locking rules: - bd_mutex -open: yes -release: yes -ioctl: no -compat_ioctl: no -direct_access: no -media_changed: no -unlock_native_capacity: no -revalidate_disk: no -getgeo: no -swap_slot_free_notify: no (see below) + BKL bd_mutex +open: no yes +release: no yes +ioctl: no no +compat_ioctl: no no +direct_access: no no +media_changed: no no +unlock_native_capacity: no no +revalidate_disk: no no +getgeo: no no +swap_slot_free_notify: no no (see below) media_changed, unlock_native_capacity and revalidate_disk are called only from check_disk_change(). @@ -428,21 +413,34 @@ prototypes: unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); 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: - All may block except for ->setlease. - No VFS locks held on entry except for ->fsync and ->setlease. - -->fsync() has i_mutex on inode. - -->setlease has the file_list_lock held and must not sleep. + All may block. + BKL +llseek: no (see below) +read: no +aio_read: no +write: no +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 implementations. If your fs is not using generic_file_llseek, you @@ -452,10 +450,17 @@ mutex or just to use i_size_read() instead. Note: this does not protect the file->f_pos against concurrent modifications since this is something the userspace has to take care about. -->fasync() 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. +Note: ext2_release() was *the* source of contention on fs-intensive +loads and dropping BKL on ->release() helps to get rid of that (we still +grab BKL for cases when we close a file that had been opened r/w, but that +can and should be done using the internal locking with smaller critical areas). +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 move ->readdir() to inode_operations and use a separate method for directory @@ -466,6 +471,8 @@ 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 in sys_read() and friends. +->fsync() has i_mutex on inode. + --------------------------- dquot_operations ------------------------------- prototypes: int (*write_dquot) (struct dquot *); @@ -500,12 +507,12 @@ prototypes: int (*access)(struct vm_area_struct *, unsigned long, void*, int, int); locking rules: - mmap_sem PageLocked(page) -open: yes -close: yes -fault: yes can return with page locked -page_mkwrite: yes can return with page locked -access: yes + BKL mmap_sem PageLocked(page) +open: no yes +close: no yes +fault: no yes can return with page locked +page_mkwrite: no yes can return with page locked +access: no yes ->fault() is called when a previously not present pte is about to be faulted in. The filesystem must find and return the page associated @@ -532,3 +539,6 @@ VM_IO | VM_PFNMAP VMAs. (if you break something or notice that it is broken and do not fix it yourself - at least put it here) + +ipc/shm.c::shm_delete() - may need BKL. +->read() and ->write() in many drivers are (probably) missing BKL. diff --git a/trunk/arch/x86/kvm/i8259.c b/trunk/arch/x86/kvm/i8259.c index 3cece05e4ac4..f628234fbeca 100644 --- a/trunk/arch/x86/kvm/i8259.c +++ b/trunk/arch/x86/kvm/i8259.c @@ -575,8 +575,6 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm) s->pics[1].elcr_mask = 0xde; s->pics[0].pics_state = s; s->pics[1].pics_state = s; - s->pics[0].isr_ack = 0xff; - s->pics[1].isr_ack = 0xff; /* * Initialize PIO device diff --git a/trunk/arch/x86/kvm/mmu.c b/trunk/arch/x86/kvm/mmu.c index fbb04aee8301..fb8b376bf28c 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -2394,8 +2394,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) ASSERT(!VALID_PAGE(root)); spin_lock(&vcpu->kvm->mmu_lock); kvm_mmu_free_some_pages(vcpu); - sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT), - i << 30, + sp = kvm_mmu_get_page(vcpu, i << 30, i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL, NULL); root = __pa(sp->spt); diff --git a/trunk/drivers/dma/mv_xor.c b/trunk/drivers/dma/mv_xor.c index a25f5f61e0e0..411d5bf50fc4 100644 --- a/trunk/drivers/dma/mv_xor.c +++ b/trunk/drivers/dma/mv_xor.c @@ -449,7 +449,7 @@ mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) static void mv_xor_tasklet(unsigned long 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 * diff --git a/trunk/drivers/gpu/drm/i915/dvo_ch7017.c b/trunk/drivers/gpu/drm/i915/dvo_ch7017.c index d3e8c540f778..af70337567ce 100644 --- a/trunk/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/trunk/drivers/gpu/drm/i915/dvo_ch7017.c @@ -242,7 +242,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo) { - return connector_status_connected; + return connector_status_unknown; } static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo, diff --git a/trunk/drivers/gpu/drm/i915/i915_dma.c b/trunk/drivers/gpu/drm/i915/i915_dma.c index cb900dc83d95..e6800819bca8 100644 --- a/trunk/drivers/gpu/drm/i915/i915_dma.c +++ b/trunk/drivers/gpu/drm/i915/i915_dma.c @@ -34,7 +34,6 @@ #include "i915_drm.h" #include "i915_drv.h" #include "i915_trace.h" -#include "../../../platform/x86/intel_ips.h" #include #include #include @@ -1871,26 +1870,6 @@ bool i915_gpu_turbo_disable(void) } 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 * @dev: DRM device @@ -2096,8 +2075,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->mchdev_lock = &mchdev_lock; spin_unlock(&mchdev_lock); - ips_ping_for_i915_load(); - return 0; out_workqueue_free: diff --git a/trunk/drivers/gpu/drm/i915/i915_reg.h b/trunk/drivers/gpu/drm/i915/i915_reg.h index cb8f43429279..878fc766a12c 100644 --- a/trunk/drivers/gpu/drm/i915/i915_reg.h +++ b/trunk/drivers/gpu/drm/i915/i915_reg.h @@ -2471,9 +2471,6 @@ # define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18) # 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_CHANGE_REQUEST (1<<24) #define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00 @@ -2591,13 +2588,6 @@ #define ILK_DISPLAY_CHICKEN2 0x42004 #define ILK_DPARB_GATE (1<<22) #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_DPARB_CLK_GATE (1<<5) /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */ diff --git a/trunk/drivers/gpu/drm/i915/intel_bios.c b/trunk/drivers/gpu/drm/i915/intel_bios.c index b0b1200ed650..2b2078695d2a 100644 --- a/trunk/drivers/gpu/drm/i915/intel_bios.c +++ b/trunk/drivers/gpu/drm/i915/intel_bios.c @@ -270,7 +270,7 @@ parse_general_features(struct drm_i915_private *dev_priv, general->ssc_freq ? 66 : 48; else if (IS_GEN5(dev) || IS_GEN6(dev)) dev_priv->lvds_ssc_freq = - general->ssc_freq ? 100 : 120; + general->ssc_freq ? 120 : 100; else dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96; diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index fca523288aca..d9b7092439ef 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -5379,23 +5379,6 @@ static int intel_encoder_clones(struct drm_device *dev, int type_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) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5413,7 +5396,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { dpd_is_edp = intel_dpd_is_edp(dev); - if (has_edp_a(dev)) + if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED)) intel_dp_init(dev, DP_A); if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) @@ -5842,8 +5825,6 @@ void intel_init_clock_gating(struct drm_device *dev) I915_WRITE(PCH_3DCGDIS0, MARIUNIT_CLOCK_GATE_DISABLE | SVSMUNIT_CLOCK_GATE_DISABLE); - I915_WRITE(PCH_3DCGDIS1, - VFMUNIT_CLOCK_GATE_DISABLE); } I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); diff --git a/trunk/drivers/gpu/drm/i915/intel_sdvo.c b/trunk/drivers/gpu/drm/i915/intel_sdvo.c index 6bc42fa2a6ec..27e63abf2a73 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sdvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_sdvo.c @@ -2040,14 +2040,13 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) SDVO_COLORIMETRY_RGB256); connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; + intel_sdvo_add_hdmi_properties(intel_sdvo_connector); intel_sdvo->is_hdmi = true; } intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | (1 << INTEL_ANALOG_CLONE_BIT)); intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); - if (intel_sdvo->is_hdmi) - intel_sdvo_add_hdmi_properties(intel_sdvo_connector); return true; } diff --git a/trunk/drivers/hwmon/s3c-hwmon.c b/trunk/drivers/hwmon/s3c-hwmon.c index 92b42db43bcf..05248f2d7581 100644 --- a/trunk/drivers/hwmon/s3c-hwmon.c +++ b/trunk/drivers/hwmon/s3c-hwmon.c @@ -234,6 +234,7 @@ static int s3c_hwmon_create_attr(struct device *dev, attr->index = channel; attr->dev_attr.attr.name = attrs->in_name; attr->dev_attr.attr.mode = S_IRUGO; + attr->dev_attr.attr.owner = THIS_MODULE; attr->dev_attr.show = s3c_hwmon_ch_show; ret = device_create_file(dev, &attr->dev_attr); @@ -251,6 +252,7 @@ static int s3c_hwmon_create_attr(struct device *dev, attr->index = channel; attr->dev_attr.attr.name = attrs->label_name; attr->dev_attr.attr.mode = S_IRUGO; + attr->dev_attr.attr.owner = THIS_MODULE; attr->dev_attr.show = s3c_hwmon_label_show; ret = device_create_file(dev, &attr->dev_attr); diff --git a/trunk/drivers/media/video/cx25840/cx25840-core.c b/trunk/drivers/media/video/cx25840/cx25840-core.c index dfb198d0415b..f16461844c5c 100644 --- a/trunk/drivers/media/video/cx25840/cx25840-core.c +++ b/trunk/drivers/media/video/cx25840/cx25840-core.c @@ -1989,8 +1989,23 @@ static int cx25840_probe(struct i2c_client *client, v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops, V4L2_CID_HUE, -128, 127, 1, 0); if (!is_cx2583x(state)) { - default_volume = 228 - cx25840_read(client, 0x8d4); - default_volume = ((default_volume / 2) + 23) << 9; + default_volume = cx25840_read(client, 0x8d4); + /* + * 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, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME, diff --git a/trunk/drivers/platform/x86/intel_ips.c b/trunk/drivers/platform/x86/intel_ips.c index f0b3ad13c273..c44a5e8b8b82 100644 --- a/trunk/drivers/platform/x86/intel_ips.c +++ b/trunk/drivers/platform/x86/intel_ips.c @@ -75,7 +75,6 @@ #include #include #include -#include "intel_ips.h" #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32 @@ -246,7 +245,6 @@ #define thm_writel(off, val) writel((val), ips->regmap + (off)) static const int IPS_ADJUST_PERIOD = 5000; /* ms */ -static bool late_i915_load = false; /* For initial average collection */ static const int IPS_SAMPLE_PERIOD = 200; /* ms */ @@ -341,9 +339,6 @@ struct ips_driver { u64 orig_turbo_ratios; }; -static bool -ips_gpu_turbo_enabled(struct ips_driver *ips); - /** * ips_cpu_busy - is CPU busy? * @ips: IPS driver struct @@ -522,7 +517,7 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips) */ static bool ips_gpu_busy(struct ips_driver *ips) { - if (!ips_gpu_turbo_enabled(ips)) + if (!ips->gpu_turbo_enabled) return false; return ips->gpu_busy(); @@ -537,7 +532,7 @@ static bool ips_gpu_busy(struct ips_driver *ips) */ static void ips_gpu_raise(struct ips_driver *ips) { - if (!ips_gpu_turbo_enabled(ips)) + if (!ips->gpu_turbo_enabled) return; if (!ips->gpu_raise()) @@ -554,7 +549,7 @@ static void ips_gpu_raise(struct ips_driver *ips) */ static void ips_gpu_lower(struct ips_driver *ips) { - if (!ips_gpu_turbo_enabled(ips)) + if (!ips->gpu_turbo_enabled) return; if (!ips->gpu_lower()) @@ -1459,31 +1454,6 @@ static bool ips_get_i915_syms(struct ips_driver *ips) 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) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, diff --git a/trunk/drivers/platform/x86/intel_ips.h b/trunk/drivers/platform/x86/intel_ips.h deleted file mode 100644 index 73299beff5b3..000000000000 --- a/trunk/drivers/platform/x86/intel_ips.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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); diff --git a/trunk/drivers/spi/coldfire_qspi.c b/trunk/drivers/spi/coldfire_qspi.c index 8856bcca9d29..052b3c7fa6a0 100644 --- a/trunk/drivers/spi/coldfire_qspi.c +++ b/trunk/drivers/spi/coldfire_qspi.c @@ -317,7 +317,7 @@ static void mcfqspi_work(struct work_struct *work) msg = container_of(mcfqspi->msgq.next, struct spi_message, queue); - list_del_init(&msg->queue); + list_del_init(&mcfqspi->msgq); spin_unlock_irqrestore(&mcfqspi->lock, flags); spi = msg->spi; diff --git a/trunk/drivers/spi/omap2_mcspi.c b/trunk/drivers/spi/omap2_mcspi.c index 951a160fc27f..2a651e61bfbf 100644 --- a/trunk/drivers/spi/omap2_mcspi.c +++ b/trunk/drivers/spi/omap2_mcspi.c @@ -1305,49 +1305,10 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev) /* work with hotplug and coldplug */ 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 = { .driver = { .name = "omap2_mcspi", .owner = THIS_MODULE, - .pm = &omap2_mcspi_pm_ops }, .remove = __exit_p(omap2_mcspi_remove), }; diff --git a/trunk/drivers/staging/zram/zram_drv.c b/trunk/drivers/staging/zram/zram_drv.c index d0e9e0207539..8c3c057aa847 100644 --- a/trunk/drivers/staging/zram/zram_drv.c +++ b/trunk/drivers/staging/zram/zram_drv.c @@ -435,6 +435,12 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio) int ret = 0; 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)) { zram_stat64_inc(zram, &zram->stats.invalid_io); bio_io_error(bio); diff --git a/trunk/include/linux/dmaengine.h b/trunk/include/linux/dmaengine.h index 8cd00ad98d37..9d8688b92d8b 100644 --- a/trunk/include/linux/dmaengine.h +++ b/trunk/include/linux/dmaengine.h @@ -824,8 +824,6 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); #ifdef CONFIG_DMA_ENGINE enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); 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 static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) { @@ -833,14 +831,7 @@ 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 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) -{ + do { } while (0); } #endif @@ -851,6 +842,8 @@ void dma_async_device_unregister(struct dma_device *device); void dma_run_dependencies(struct dma_async_tx_descriptor *tx); 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) +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 --- */ diff --git a/trunk/init/do_mounts.c b/trunk/init/do_mounts.c index 2b54bef33b55..830aaec9c7d5 100644 --- a/trunk/init/do_mounts.c +++ b/trunk/init/do_mounts.c @@ -93,7 +93,7 @@ static int match_dev_by_uuid(struct device *dev, void *data) * * Returns the matching dev_t on success or 0 on failure. */ -static dev_t devt_from_partuuid(char *uuid_str) +static dev_t __init devt_from_partuuid(char *uuid_str) { dev_t res = 0; struct device *dev = NULL; diff --git a/trunk/kernel/user.c b/trunk/kernel/user.c index 5c598ca781df..2c7d8d5914b1 100644 --- a/trunk/kernel/user.c +++ b/trunk/kernel/user.c @@ -158,7 +158,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); if (up) { - put_user_ns(ns); key_put(new->uid_keyring); key_put(new->session_keyring); kmem_cache_free(uid_cachep, new); diff --git a/trunk/mm/memcontrol.c b/trunk/mm/memcontrol.c index 00bb8a64d028..7a22b4129211 100644 --- a/trunk/mm/memcontrol.c +++ b/trunk/mm/memcontrol.c @@ -1925,18 +1925,19 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, rcu_read_lock(); p = rcu_dereference(mm->owner); + VM_BUG_ON(!p); /* - * Because we don't have task_lock(), "p" can exit. - * In that case, "mem" can point to root or p can be NULL with - * race with swapoff. Then, we have small risk of mis-accouning. - * But such kind of mis-account by race always happens because - * we don't have cgroup_mutex(). It's overkill and we allo that - * small race, here. - * (*) swapoff at el will charge against mm-struct not against - * task-struct. So, mm->owner can be NULL. + * because we don't have task_lock(), "p" can exit while + * we're here. In that case, "mem" can point to root + * cgroup but never be NULL. (and task_struct itself is freed + * by RCU, cgroup itself is RCU safe.) Then, we have small + * risk here to get wrong cgroup. But such kind of mis-account + * by race always happens because we don't have cgroup_mutex(). + * It's overkill and we allow that small race, here. */ mem = mem_cgroup_from_task(p); - if (!mem || mem_cgroup_is_root(mem)) { + VM_BUG_ON(!mem); + if (mem_cgroup_is_root(mem)) { rcu_read_unlock(); goto done; } diff --git a/trunk/scripts/kconfig/menu.c b/trunk/scripts/kconfig/menu.c index 5f77dcb8977e..b9d9aa18e6d6 100644 --- a/trunk/scripts/kconfig/menu.c +++ b/trunk/scripts/kconfig/menu.c @@ -140,20 +140,6 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e } if (current_entry->prompt && current_entry != &rootmenu) 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; } prop->text = prompt; diff --git a/trunk/sound/oss/soundcard.c b/trunk/sound/oss/soundcard.c index fcb14a099822..46c0d03dbecc 100644 --- a/trunk/sound/oss/soundcard.c +++ b/trunk/sound/oss/soundcard.c @@ -87,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) int i, n; for (i = 0; i < num_mixer_volumes; i++) { - if (strncmp(name, mixer_vols[i].name, 32) == 0) { + if (strcmp(name, mixer_vols[i].name) == 0) { if (present) mixer_vols[i].num = i; return mixer_vols[i].levels; @@ -99,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) } n = num_mixer_volumes++; - strncpy(mixer_vols[n].name, name, 32); + strcpy(mixer_vols[n].name, name); if (present) mixer_vols[n].num = n; diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index a1c4008af891..b030c8eba21f 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -2300,7 +2300,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { 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, 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(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), diff --git a/trunk/sound/soc/codecs/max98088.c b/trunk/sound/soc/codecs/max98088.c index 6447dbb2f123..d63e28773eb1 100644 --- a/trunk/sound/soc/codecs/max98088.c +++ b/trunk/sound/soc/codecs/max98088.c @@ -40,6 +40,7 @@ struct max98088_cdata { }; struct max98088_priv { + u8 reg_cache[M98088_REG_CNT]; enum max98088_type devtype; void *control_data; struct max98088_pdata *pdata; @@ -1587,7 +1588,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, static void max98088_sync_cache(struct snd_soc_codec *codec) { - u16 *reg_cache = codec->reg_cache; + struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); int i; if (!codec->cache_sync) @@ -1598,14 +1599,14 @@ static void max98088_sync_cache(struct snd_soc_codec *codec) /* write back cached values if they're writeable and * different from the hardware default. */ - for (i = 1; i < codec->driver->reg_cache_size; i++) { + for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) { if (!max98088_access[i].writable) continue; - if (reg_cache[i] == max98088_reg[i]) + if (max98088->reg_cache[i] == max98088_reg[i]) continue; - snd_soc_write(codec, i, reg_cache[i]); + snd_soc_write(codec, i, max98088->reg_cache[i]); } codec->cache_sync = 0; @@ -1950,6 +1951,7 @@ static int max98088_probe(struct snd_soc_codec *codec) int ret = 0; 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); if (ret != 0) { diff --git a/trunk/sound/soc/codecs/wm8523.c b/trunk/sound/soc/codecs/wm8523.c index deca79ea2b4b..9a433a5396cb 100644 --- a/trunk/sound/soc/codecs/wm8523.c +++ b/trunk/sound/soc/codecs/wm8523.c @@ -41,6 +41,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { enum snd_soc_control_type control_type; + u16 reg_cache[WM8523_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; unsigned int rate_constraint_list[WM8523_NUM_RATES]; @@ -313,7 +314,6 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; int ret, i; switch (level) { @@ -344,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, /* Sync back default/cached values */ for (i = WM8523_AIF_CTRL1; i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, reg_cache[i]); + snd_soc_write(codec, i, wm8523->reg_cache[i]); msleep(100); @@ -414,7 +414,6 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; int ret, i; codec->hw_write = (hw_write_t)i2c_master_send; @@ -471,8 +470,8 @@ static int wm8523_probe(struct snd_soc_codec *codec) } /* Change some default settings - latch VU and enable ZC */ - reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; - reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; + wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; + wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/trunk/sound/soc/codecs/wm8741.c b/trunk/sound/soc/codecs/wm8741.c index aea60ef8aba7..90e31e9aa6f7 100644 --- a/trunk/sound/soc/codecs/wm8741.c +++ b/trunk/sound/soc/codecs/wm8741.c @@ -41,6 +41,7 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { enum snd_soc_control_type control_type; + u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; @@ -421,7 +422,6 @@ static int wm8741_resume(struct snd_soc_codec *codec) static int wm8741_probe(struct snd_soc_codec *codec) { struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; int ret = 0; 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 */ - reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; - reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; - reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; - reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; + wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; + wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; + wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; + wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; snd_soc_add_controls(codec, wm8741_snd_controls, ARRAY_SIZE(wm8741_snd_controls)); diff --git a/trunk/sound/soc/codecs/wm8753.c b/trunk/sound/soc/codecs/wm8753.c index 87caae59e939..8f679a13f2bc 100644 --- a/trunk/sound/soc/codecs/wm8753.c +++ b/trunk/sound/soc/codecs/wm8753.c @@ -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. */ static const u16 wm8753_reg[] = { - 0x0000, 0x0008, 0x0000, 0x000a, - 0x000a, 0x0033, 0x0000, 0x0007, - 0x00ff, 0x00ff, 0x000f, 0x000f, - 0x007b, 0x0000, 0x0032, 0x0000, - 0x00c3, 0x00c3, 0x00c0, 0x0000, + 0x0008, 0x0000, 0x000a, 0x000a, + 0x0033, 0x0000, 0x0007, 0x00ff, + 0x00ff, 0x000f, 0x000f, 0x007b, + 0x0000, 0x0032, 0x0000, 0x00c3, + 0x00c3, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0055, 0x0005, 0x0050, 0x0055, - 0x0050, 0x0055, 0x0050, 0x0055, + 0x0000, 0x0000, 0x0000, 0x0055, + 0x0005, 0x0050, 0x0055, 0x0050, + 0x0055, 0x0050, 0x0055, 0x0079, 0x0079, 0x0079, 0x0079, 0x0079, - 0x0079, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0097, 0x0097, 0x0000, - 0x0004, 0x0000, 0x0083, 0x0024, - 0x01ba, 0x0000, 0x0083, 0x0024, - 0x01ba, 0x0000, 0x0000, 0x0000 + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0097, 0x0097, 0x0000, 0x0004, + 0x0000, 0x0083, 0x0024, 0x01ba, + 0x0000, 0x0083, 0x0024, 0x01ba, + 0x0000, 0x0000, 0x0000 }; /* codec private data */ @@ -88,10 +88,57 @@ struct wm8753_priv { enum snd_soc_control_type control_type; unsigned int sysclk; unsigned int pcmclk; + u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; 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 @@ -171,7 +218,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = snd_soc_read(codec, WM8753_IOCTL); + int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; return 0; @@ -181,7 +228,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = snd_soc_read(codec, WM8753_IOCTL); + int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) @@ -691,17 +738,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (pll_id == WM8753_PLL1) { offset = 0; enable = 0x10; - reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef; + reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; } else { offset = 4; enable = 0x8; - reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7; + reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; } if (!freq_in || !freq_out) { /* disable PLL */ - snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); - snd_soc_write(codec, WM8753_CLOCK, reg); + wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); + wm8753_write(codec, WM8753_CLOCK, reg); return 0; } else { u16 value = 0; @@ -712,20 +759,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* set up N and K PLL divisor ratios */ /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); - snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value); + wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); /* bits 8:0 = PLL_K[17:9] */ value = (pll_div.k & 0x03fe00) >> 9; - snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value); + wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); /* bits 8:0 = PLL_K[8:0] */ value = pll_div.k & 0x0001ff; - snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value); + wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); /* set PLL as input and enable */ - snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | + wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | (pll_div.div2 << 3)); - snd_soc_write(codec, WM8753_CLOCK, reg | enable); + wm8753_write(codec, WM8753_CLOCK, reg | enable); } return 0; } @@ -832,7 +879,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec; + u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -854,7 +901,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8753_PCM, voice); + wm8753_write(codec, WM8753_PCM, voice); return 0; } @@ -875,8 +922,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3; - u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f; + u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; + u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; /* bit size */ switch (params_format(params)) { @@ -896,9 +943,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, /* sample rate */ if (params_rate(params) * 384 == wm8753->pcmclk) srate |= 0x80; - snd_soc_write(codec, WM8753_SRATE1, srate); + wm8753_write(codec, WM8753_SRATE1, srate); - snd_soc_write(codec, WM8753_PCM, voice); + wm8753_write(codec, WM8753_PCM, voice); return 0; } @@ -911,8 +958,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 voice, ioctl; - voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; - ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d; + voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; + ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -966,8 +1013,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8753_PCM, voice); - snd_soc_write(codec, WM8753_IOCTL, ioctl); + wm8753_write(codec, WM8753_PCM, voice); + wm8753_write(codec, WM8753_IOCTL, ioctl); return 0; } @@ -979,16 +1026,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8753_PCMDIV: - reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f; - snd_soc_write(codec, WM8753_CLOCK, reg | div); + reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; + wm8753_write(codec, WM8753_CLOCK, reg | div); break; case WM8753_BCLKDIV: - reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7; - snd_soc_write(codec, WM8753_SRATE2, reg | div); + reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; + wm8753_write(codec, WM8753_SRATE2, reg | div); break; case WM8753_VXCLKDIV: - reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f; - snd_soc_write(codec, WM8753_SRATE2, reg | div); + reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; + wm8753_write(codec, WM8753_SRATE2, reg | div); break; default: return -EINVAL; @@ -1003,7 +1050,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0; + u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1025,7 +1072,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8753_HIFI, hifi); + wm8753_write(codec, WM8753_HIFI, hifi); return 0; } @@ -1038,8 +1085,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 ioctl, hifi; - hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; - ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae; + hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; + ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1093,8 +1140,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8753_HIFI, hifi); - snd_soc_write(codec, WM8753_IOCTL, ioctl); + wm8753_write(codec, WM8753_HIFI, hifi); + wm8753_write(codec, WM8753_IOCTL, ioctl); return 0; } @@ -1115,8 +1162,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0; - u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3; + u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; + u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; int coeff; /* is digital filter coefficient valid ? */ @@ -1125,7 +1172,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); return coeff; } - snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | + wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); /* bit size */ @@ -1143,7 +1190,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, break; } - snd_soc_write(codec, WM8753_HIFI, hifi); + wm8753_write(codec, WM8753_HIFI, hifi); return 0; } @@ -1154,8 +1201,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clock; /* set clk source as pcmclk */ - clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; - snd_soc_write(codec, WM8753_CLOCK, clock); + clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; + wm8753_write(codec, WM8753_CLOCK, clock); if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1177,8 +1224,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clock; /* set clk source as pcmclk */ - clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; - snd_soc_write(codec, WM8753_CLOCK, clock); + clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; + wm8753_write(codec, WM8753_CLOCK, clock); if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1192,8 +1239,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clock; /* set clk source as mclk */ - clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; - snd_soc_write(codec, WM8753_CLOCK, clock | 0x4); + clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; + wm8753_write(codec, WM8753_CLOCK, clock | 0x4); if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1205,19 +1252,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) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7; + u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); /* 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 */ if (mute && wm8753->dai_func == 1) { if (!codec->active) - snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); + wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); } else { if (mute) - snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); + wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); else - snd_soc_write(codec, WM8753_DAC, mute_reg); + wm8753_write(codec, WM8753_DAC, mute_reg); } return 0; @@ -1226,23 +1273,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) static int wm8753_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; + u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); + wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_PREPARE: /* set vmid to 5k for quick power up */ - snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); + wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); + wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8753_PWR1, 0x0001); + wm8753_write(codec, WM8753_PWR1, 0x0001); break; } codec->bias_level = level; @@ -1430,7 +1477,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, else dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; } - snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func); + wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); } static void wm8753_work(struct work_struct *work) @@ -1448,19 +1495,22 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8753_resume(struct snd_soc_codec *codec) { - u16 *reg_cache = codec->reg_cache; int i; + u8 data[2]; + u16 *cache = codec->reg_cache; /* Sync reg_cache with the hardware */ - for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) { - if (i == WM8753_RESET) + for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { + if (i + 1 == WM8753_RESET) continue; /* No point in writing hardware default values back */ - if (reg_cache[i] == wm8753_reg[i]) + if (cache[i] == wm8753_reg[i]) continue; - snd_soc_write(codec, i, reg_cache[i]); + data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); + data[1] = cache[i] & 0x00ff; + codec->hw_write(codec->control_data, data, 2); } wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1498,7 +1548,7 @@ static int run_delayed_work(struct delayed_work *dwork) static int wm8753_probe(struct snd_soc_codec *codec) { struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - int ret; + int ret = 0, reg; INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); @@ -1523,16 +1573,26 @@ static int wm8753_probe(struct snd_soc_codec *codec) msecs_to_jiffies(caps_charge)); /* set the update bits */ - snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LDAC); + wm8753_write(codec, WM8753_LDAC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_RDAC); + wm8753_write(codec, WM8753_RDAC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LADC); + wm8753_write(codec, WM8753_LADC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_RADC); + wm8753_write(codec, WM8753_RADC, reg | 0x0100); + reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); + wm8753_write(codec, WM8753_LOUT1V, reg | 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, ARRAY_SIZE(wm8753_snd_controls)); diff --git a/trunk/sound/soc/codecs/wm8904.c b/trunk/sound/soc/codecs/wm8904.c index 1ec12eff0620..9001cc48ba13 100644 --- a/trunk/sound/soc/codecs/wm8904.c +++ b/trunk/sound/soc/codecs/wm8904.c @@ -50,6 +50,8 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { /* codec private data */ struct wm8904_priv { + u16 reg_cache[WM8904_MAX_REGISTER + 1]; + enum wm8904_type devtype; void *control_data; @@ -2092,7 +2094,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) static void wm8904_sync_cache(struct snd_soc_codec *codec) { - u16 *reg_cache = codec->reg_cache; + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); int i; if (!codec->cache_sync) @@ -2103,14 +2105,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec) /* Sync back cached values if they're different from the * hardware default. */ - for (i = 1; i < codec->driver->reg_cache_size; i++) { + for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { if (!wm8904_access[i].writable) continue; - if (reg_cache[i] == wm8904_reg[i]) + if (wm8904->reg_cache[i] == wm8904_reg[i]) continue; - snd_soc_write(codec, i, reg_cache[i]); + snd_soc_write(codec, i, wm8904->reg_cache[i]); } codec->cache_sync = 0; @@ -2369,7 +2371,6 @@ static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; - u16 *reg_cache = codec->reg_cache; int ret, i; codec->cache_sync = 1; @@ -2436,19 +2437,19 @@ static int wm8904_probe(struct snd_soc_codec *codec) } /* Change some default settings - latch VU and enable ZC */ - reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; - reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; - reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; - reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; - reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | + wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; + wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; + wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; + wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; + wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | WM8904_HPOUTLZC; - reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | + wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | WM8904_HPOUTRZC; - reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | + wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | WM8904_LINEOUTLZC; - reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | + wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | WM8904_LINEOUTRZC; - reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; + wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; /* Apply configuration from the platform data. */ if (wm8904->pdata) { @@ -2456,23 +2457,23 @@ static int wm8904_probe(struct snd_soc_codec *codec) if (!pdata->gpio_cfg[i]) continue; - reg_cache[WM8904_GPIO_CONTROL_1 + i] + wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] = pdata->gpio_cfg[i] & 0xffff; } /* Zero is the default value for these anyway */ for (i = 0; i < WM8904_MIC_REGS; i++) - reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] + wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] = pdata->mic_cfg[i]; } /* Set Class W by default - this will be managed by the Class * G widget at runtime where bypass paths are available. */ - reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; + wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; /* Use normal bias source */ - reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; + wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/trunk/sound/soc/codecs/wm8940.c b/trunk/sound/soc/codecs/wm8940.c index 23086e2c976a..2cb16f895c46 100644 --- a/trunk/sound/soc/codecs/wm8940.c +++ b/trunk/sound/soc/codecs/wm8940.c @@ -768,7 +768,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm8940); wm8940->control_data = i2c; - wm8940->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8940, &wm8940_dai, 1); diff --git a/trunk/sound/soc/codecs/wm8955.c b/trunk/sound/soc/codecs/wm8955.c index 2ac35b0be86a..9cbab8e1de01 100644 --- a/trunk/sound/soc/codecs/wm8955.c +++ b/trunk/sound/soc/codecs/wm8955.c @@ -42,6 +42,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { struct wm8955_priv { enum snd_soc_control_type control_type; + u16 reg_cache[WM8955_MAX_REGISTER + 1]; + unsigned int mclk_rate; int deemph; @@ -766,7 +768,6 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; int ret, i; switch (level) { @@ -799,14 +800,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, /* Sync back cached values if they're * different from the hardware default. */ - for (i = 0; i < codec->driver->reg_cache_size; i++) { + for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) { if (i == WM8955_RESET) continue; - if (reg_cache[i] == wm8955_reg[i]) + if (wm8955->reg_cache[i] == wm8955_reg[i]) continue; - snd_soc_write(codec, i, reg_cache[i]); + snd_soc_write(codec, i, wm8955->reg_cache[i]); } /* Enable VREF and VMID */ @@ -901,7 +902,6 @@ static int wm8955_probe(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); - u16 *reg_cache = codec->reg_cache; int ret, i; 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 */ - reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; - reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; - reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; - reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; - reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; - reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; - reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; + wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; + wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; + wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; + wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; + wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; + wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; + wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; /* Also enable adaptive bass boost by default */ - reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; + wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; /* Set platform data values */ if (pdata) { if (pdata->out2_speaker) - reg_cache[WM8955_ADDITIONAL_CONTROL_2] + wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] |= WM8955_ROUT2INV; if (pdata->monoin_diff) - reg_cache[WM8955_MONO_OUT_MIX_1] + wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] |= WM8955_DMEN; } @@ -1003,7 +1003,6 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8955); - wm8955->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8955, &wm8955_dai, 1); diff --git a/trunk/sound/soc/codecs/wm8960.c b/trunk/sound/soc/codecs/wm8960.c index ff6ff2f529d2..21986c42272f 100644 --- a/trunk/sound/soc/codecs/wm8960.c +++ b/trunk/sound/soc/codecs/wm8960.c @@ -1013,7 +1013,6 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8960); - wm8960->control_type = SND_SOC_I2C; wm8960->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, diff --git a/trunk/sound/soc/codecs/wm8962.c b/trunk/sound/soc/codecs/wm8962.c index 7c421cc837bd..1304ca91a11c 100644 --- a/trunk/sound/soc/codecs/wm8962.c +++ b/trunk/sound/soc/codecs/wm8962.c @@ -52,6 +52,8 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { struct wm8962_priv { struct snd_soc_codec *codec; + u16 reg_cache[WM8962_MAX_REGISTER + 1]; + int sysclk; int sysclk_rate; @@ -1989,7 +1991,8 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = wm8962->reg_cache; int ret; /* Apply the update (if any) */ @@ -2017,7 +2020,8 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = wm8962->reg_cache; int ret; /* Apply the update (if any) */ @@ -2325,7 +2329,8 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = wm8962->reg_cache; int reg; switch (w->shift) { @@ -2714,7 +2719,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) static void wm8962_sync_cache(struct snd_soc_codec *codec) { - u16 *reg_cache = codec->reg_cache; + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); int i; if (!codec->cache_sync) @@ -2727,13 +2732,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec) /* Sync back cached values if they're different from the * hardware default. */ - for (i = 1; i < codec->driver->reg_cache_size; i++) { + for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { if (i == WM8962_SOFTWARE_RESET) continue; - if (reg_cache[i] == wm8962_reg[i]) + if (wm8962->reg_cache[i] == wm8962_reg[i]) continue; - snd_soc_write(codec, i, reg_cache[i]); + snd_soc_write(codec, i, wm8962->reg_cache[i]); } codec->cache_sync = 0; @@ -3401,11 +3406,12 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect); #ifdef CONFIG_PM 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; int i; /* Restore the registers */ - for (i = 1; i < codec->driver->reg_cache_size; i++) { + for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { switch (i) { case WM8962_SOFTWARE_RESET: continue; @@ -3699,7 +3705,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, dev); - u16 *reg_cache = codec->reg_cache; int i, trigger, irq_pol; wm8962->codec = codec; @@ -3799,7 +3804,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) /* Put the speakers into mono mode? */ if (pdata->spk_mono) - reg_cache[WM8962_CLASS_D_CONTROL_2] + wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2] |= WM8962_SPK_MONO; /* Micbias setup, detection enable and detection @@ -3814,16 +3819,16 @@ static int wm8962_probe(struct snd_soc_codec *codec) } /* Latch volume update bits */ - reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; - reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; - reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; - reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; - reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; - reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; - reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; - reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; - reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; - reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; + wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; + wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; + wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; + wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; + wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; + wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; + wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; + wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; + wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; + wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; wm8962_add_widgets(codec); diff --git a/trunk/sound/soc/codecs/wm8971.c b/trunk/sound/soc/codecs/wm8971.c index 9f18db6e167c..63f6dbf5d070 100644 --- a/trunk/sound/soc/codecs/wm8971.c +++ b/trunk/sound/soc/codecs/wm8971.c @@ -718,7 +718,6 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, if (wm8971 == NULL) return -ENOMEM; - wm8971->control_type = SND_SOC_I2C; i2c_set_clientdata(i2c, wm8971); ret = snd_soc_register_codec(&i2c->dev, diff --git a/trunk/sound/soc/codecs/wm9081.c b/trunk/sound/soc/codecs/wm9081.c index a486670966bd..ecc7c37180c7 100644 --- a/trunk/sound/soc/codecs/wm9081.c +++ b/trunk/sound/soc/codecs/wm9081.c @@ -1335,7 +1335,6 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm9081); - wm9081->control_type = SND_SOC_I2C; wm9081->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, diff --git a/trunk/sound/soc/codecs/wm9090.c b/trunk/sound/soc/codecs/wm9090.c index 6e5f64f627cb..99c046ba46bb 100644 --- a/trunk/sound/soc/codecs/wm9090.c +++ b/trunk/sound/soc/codecs/wm9090.c @@ -141,6 +141,7 @@ static const u16 wm9090_reg_defaults[] = { /* This struct is used to save the context */ struct wm9090_priv { struct mutex mutex; + u16 reg_cache[WM9090_MAX_REGISTER + 1]; struct wm9090_platform_data pdata; void *control_data; }; @@ -551,7 +552,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; int ret; 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 * bring the bias up. */ - reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU + wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | WM9090_IN1A_ZC; - reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU + wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | WM9090_IN1B_ZC; - reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU + wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | WM9090_IN2A_ZC; - reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU + wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | WM9090_IN2B_ZC; - reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= + wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; - reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= + wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; - reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= + wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; - reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; + wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);