]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
authorMark Brown <broonie@linaro.org>
Wed, 23 Oct 2013 15:44:41 +0000 (16:44 +0100)
committerMark Brown <broonie@linaro.org>
Wed, 23 Oct 2013 15:44:41 +0000 (16:44 +0100)
1  2 
drivers/base/regmap/internal.h
drivers/base/regmap/regmap.c
include/linux/regmap.h
include/sound/rcar_snd.h
sound/soc/sh/rcar/rsnd.h

index 6873b4ce03f917802412a4ed29cdd1550c2e61f3,9010614f77937396399a30d43c0c5e4b984742c0..33414b1de2013b8e3fc68f31a70f8a56f2900cbe
@@@ -44,6 -44,7 +44,6 @@@ struct regmap_format 
  
  struct regmap_async {
        struct list_head list;
 -      struct work_struct cleanup;
        struct regmap *map;
        void *work_buf;
  };
@@@ -63,11 -64,9 +63,11 @@@ struct regmap 
        void *bus_context;
        const char *name;
  
 +      bool async;
        spinlock_t async_lock;
        wait_queue_head_t async_waitq;
        struct list_head async_list;
 +      struct list_head async_free;
        int async_ret;
  
  #ifdef CONFIG_DEBUG_FS
@@@ -180,6 -179,9 +180,9 @@@ struct regmap_field 
        /* lsb */
        unsigned int shift;
        unsigned int reg;
+       unsigned int id_size;
+       unsigned int id_offset;
  };
  
  #ifdef CONFIG_DEBUG_FS
@@@ -219,7 -221,7 +222,7 @@@ bool regcache_set_val(struct regmap *ma
  int regcache_lookup_reg(struct regmap *map, unsigned int reg);
  
  int _regmap_raw_write(struct regmap *map, unsigned int reg,
 -                    const void *val, size_t val_len, bool async);
 +                    const void *val, size_t val_len);
  
  void regmap_async_complete_cb(struct regmap_async *async, int ret);
  
index 0503d868ff8c190b3fe5399b35cbd56505431e89,00152bf7ab1202b8bc0a0a06e91941ffdf9fe770..ccdac61ac5e2b2b6de72819d8911fd01ad1ecf60
@@@ -42,6 -42,15 +42,6 @@@ static int _regmap_bus_formatted_write(
  static int _regmap_bus_raw_write(void *context, unsigned int reg,
                                 unsigned int val);
  
 -static void async_cleanup(struct work_struct *work)
 -{
 -      struct regmap_async *async = container_of(work, struct regmap_async,
 -                                                cleanup);
 -
 -      kfree(async->work_buf);
 -      kfree(async);
 -}
 -
  bool regmap_reg_in_ranges(unsigned int reg,
                          const struct regmap_range *ranges,
                          unsigned int nranges)
@@@ -456,7 -465,6 +456,7 @@@ struct regmap *regmap_init(struct devic
  
        spin_lock_init(&map->async_lock);
        INIT_LIST_HEAD(&map->async_list);
 +      INIT_LIST_HEAD(&map->async_free);
        init_waitqueue_head(&map->async_waitq);
  
        if (config->read_flag_mask || config->write_flag_mask) {
@@@ -813,6 -821,8 +813,8 @@@ static void regmap_field_init(struct re
        rm_field->reg = reg_field.reg;
        rm_field->shift = reg_field.lsb;
        rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
+       rm_field->id_size = reg_field.id_size;
+       rm_field->id_offset = reg_field.id_offset;
  }
  
  /**
@@@ -934,22 -944,12 +936,22 @@@ EXPORT_SYMBOL_GPL(regmap_reinit_cache)
   */
  void regmap_exit(struct regmap *map)
  {
 +      struct regmap_async *async;
 +
        regcache_exit(map);
        regmap_debugfs_exit(map);
        regmap_range_exit(map);
        if (map->bus && map->bus->free_context)
                map->bus->free_context(map->bus_context);
        kfree(map->work_buf);
 +      while (!list_empty(&map->async_free)) {
 +              async = list_first_entry_or_null(&map->async_free,
 +                                               struct regmap_async,
 +                                               list);
 +              list_del(&async->list);
 +              kfree(async->work_buf);
 +              kfree(async);
 +      }
        kfree(map);
  }
  EXPORT_SYMBOL_GPL(regmap_exit);
@@@ -1041,7 -1041,7 +1043,7 @@@ static int _regmap_select_page(struct r
  }
  
  int _regmap_raw_write(struct regmap *map, unsigned int reg,
 -                    const void *val, size_t val_len, bool async)
 +                    const void *val, size_t val_len)
  {
        struct regmap_range_node *range;
        unsigned long flags;
                        dev_dbg(map->dev, "Writing window %d/%zu\n",
                                win_residue, val_len / map->format.val_bytes);
                        ret = _regmap_raw_write(map, reg, val, win_residue *
 -                                              map->format.val_bytes, async);
 +                                              map->format.val_bytes);
                        if (ret != 0)
                                return ret;
  
  
        u8[0] |= map->write_flag_mask;
  
 -      if (async && map->bus->async_write) {
 -              struct regmap_async *async = map->bus->async_alloc();
 -              if (!async)
 -                      return -ENOMEM;
 +      /*
 +       * Essentially all I/O mechanisms will be faster with a single
 +       * buffer to write.  Since register syncs often generate raw
 +       * writes of single registers optimise that case.
 +       */
 +      if (val != work_val && val_len == map->format.val_bytes) {
 +              memcpy(work_val, val, map->format.val_bytes);
 +              val = work_val;
 +      }
 +
 +      if (map->async && map->bus->async_write) {
 +              struct regmap_async *async;
  
                trace_regmap_async_write_start(map->dev, reg, val_len);
  
 -              async->work_buf = kzalloc(map->format.buf_size,
 -                                        GFP_KERNEL | GFP_DMA);
 -              if (!async->work_buf) {
 -                      kfree(async);
 -                      return -ENOMEM;
 +              spin_lock_irqsave(&map->async_lock, flags);
 +              async = list_first_entry_or_null(&map->async_free,
 +                                               struct regmap_async,
 +                                               list);
 +              if (async)
 +                      list_del(&async->list);
 +              spin_unlock_irqrestore(&map->async_lock, flags);
 +
 +              if (!async) {
 +                      async = map->bus->async_alloc();
 +                      if (!async)
 +                              return -ENOMEM;
 +
 +                      async->work_buf = kzalloc(map->format.buf_size,
 +                                                GFP_KERNEL | GFP_DMA);
 +                      if (!async->work_buf) {
 +                              kfree(async);
 +                              return -ENOMEM;
 +                      }
                }
  
 -              INIT_WORK(&async->cleanup, async_cleanup);
                async->map = map;
  
                /* If the caller supplied the value we can use it safely. */
                                ret);
  
                        spin_lock_irqsave(&map->async_lock, flags);
 -                      list_del(&async->list);
 +                      list_move(&async->list, &map->async_free);
                        spin_unlock_irqrestore(&map->async_lock, flags);
 -
 -                      kfree(async->work_buf);
 -                      kfree(async);
                }
  
                return ret;
@@@ -1273,7 -1255,7 +1275,7 @@@ static int _regmap_bus_raw_write(void *
                                 map->work_buf +
                                 map->format.reg_bytes +
                                 map->format.pad_bytes,
 -                               map->format.val_bytes, false);
 +                               map->format.val_bytes);
  }
  
  static inline void *_regmap_map_get_context(struct regmap *map)
@@@ -1337,37 -1319,6 +1339,37 @@@ int regmap_write(struct regmap *map, un
  }
  EXPORT_SYMBOL_GPL(regmap_write);
  
 +/**
 + * regmap_write_async(): Write a value to a single register asynchronously
 + *
 + * @map: Register map to write to
 + * @reg: Register to write to
 + * @val: Value to be written
 + *
 + * A value of zero will be returned on success, a negative errno will
 + * be returned in error cases.
 + */
 +int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
 +{
 +      int ret;
 +
 +      if (reg % map->reg_stride)
 +              return -EINVAL;
 +
 +      map->lock(map->lock_arg);
 +
 +      map->async = true;
 +
 +      ret = _regmap_write(map, reg, val);
 +
 +      map->async = false;
 +
 +      map->unlock(map->lock_arg);
 +
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(regmap_write_async);
 +
  /**
   * regmap_raw_write(): Write raw values to one or more registers
   *
@@@ -1396,7 -1347,7 +1398,7 @@@ int regmap_raw_write(struct regmap *map
  
        map->lock(map->lock_arg);
  
 -      ret = _regmap_raw_write(map, reg, val, val_len, false);
 +      ret = _regmap_raw_write(map, reg, val, val_len);
  
        map->unlock(map->lock_arg);
  
@@@ -1420,6 -1371,74 +1422,74 @@@ int regmap_field_write(struct regmap_fi
  }
  EXPORT_SYMBOL_GPL(regmap_field_write);
  
+ /**
+  * regmap_field_update_bits():        Perform a read/modify/write cycle
+  *                              on the register field
+  *
+  * @field: Register field to write to
+  * @mask: Bitmask to change
+  * @val: Value to be written
+  *
+  * A value of zero will be returned on success, a negative errno will
+  * be returned in error cases.
+  */
+ int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
+ {
+       mask = (mask << field->shift) & field->mask;
+       return regmap_update_bits(field->regmap, field->reg,
+                                 mask, val << field->shift);
+ }
+ EXPORT_SYMBOL_GPL(regmap_field_update_bits);
+ /**
+  * regmap_fields_write(): Write a value to a single register field with port ID
+  *
+  * @field: Register field to write to
+  * @id: port ID
+  * @val: Value to be written
+  *
+  * A value of zero will be returned on success, a negative errno will
+  * be returned in error cases.
+  */
+ int regmap_fields_write(struct regmap_field *field, unsigned int id,
+                       unsigned int val)
+ {
+       if (id >= field->id_size)
+               return -EINVAL;
+       return regmap_update_bits(field->regmap,
+                                 field->reg + (field->id_offset * id),
+                                 field->mask, val << field->shift);
+ }
+ EXPORT_SYMBOL_GPL(regmap_fields_write);
+ /**
+  * regmap_fields_update_bits():       Perform a read/modify/write cycle
+  *                              on the register field
+  *
+  * @field: Register field to write to
+  * @id: port ID
+  * @mask: Bitmask to change
+  * @val: Value to be written
+  *
+  * A value of zero will be returned on success, a negative errno will
+  * be returned in error cases.
+  */
+ int regmap_fields_update_bits(struct regmap_field *field,  unsigned int id,
+                             unsigned int mask, unsigned int val)
+ {
+       if (id >= field->id_size)
+               return -EINVAL;
+       mask = (mask << field->shift) & field->mask;
+       return regmap_update_bits(field->regmap,
+                                 field->reg + (field->id_offset * id),
+                                 mask, val << field->shift);
+ }
+ EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
  /*
   * regmap_bulk_write(): Write multiple registers to the device
   *
@@@ -1477,7 -1496,8 +1547,7 @@@ int regmap_bulk_write(struct regmap *ma
                                return ret;
                }
        } else {
 -              ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count,
 -                                      false);
 +              ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
        }
  
        if (val_bytes != 1)
@@@ -1523,11 -1543,7 +1593,11 @@@ int regmap_raw_write_async(struct regma
  
        map->lock(map->lock_arg);
  
 -      ret = _regmap_raw_write(map, reg, val, val_len, true);
 +      map->async = true;
 +
 +      ret = _regmap_raw_write(map, reg, val, val_len);
 +
 +      map->async = false;
  
        map->unlock(map->lock_arg);
  
@@@ -1730,6 -1746,39 +1800,39 @@@ int regmap_field_read(struct regmap_fie
  }
  EXPORT_SYMBOL_GPL(regmap_field_read);
  
+ /**
+  * regmap_fields_read(): Read a value to a single register field with port ID
+  *
+  * @field: Register field to read from
+  * @id: port ID
+  * @val: Pointer to store read value
+  *
+  * A value of zero will be returned on success, a negative errno will
+  * be returned in error cases.
+  */
+ int regmap_fields_read(struct regmap_field *field, unsigned int id,
+                      unsigned int *val)
+ {
+       int ret;
+       unsigned int reg_val;
+       if (id >= field->id_size)
+               return -EINVAL;
+       ret = regmap_read(field->regmap,
+                         field->reg + (field->id_offset * id),
+                         &reg_val);
+       if (ret != 0)
+               return ret;
+       reg_val &= field->mask;
+       reg_val >>= field->shift;
+       *val = reg_val;
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(regmap_fields_read);
  /**
   * regmap_bulk_read(): Read multiple registers from the device
   *
@@@ -1841,41 -1890,6 +1944,41 @@@ int regmap_update_bits(struct regmap *m
  }
  EXPORT_SYMBOL_GPL(regmap_update_bits);
  
 +/**
 + * regmap_update_bits_async: Perform a read/modify/write cycle on the register
 + *                           map asynchronously
 + *
 + * @map: Register map to update
 + * @reg: Register to update
 + * @mask: Bitmask to change
 + * @val: New value for bitmask
 + *
 + * With most buses the read must be done synchronously so this is most
 + * useful for devices with a cache which do not need to interact with
 + * the hardware to determine the current register value.
 + *
 + * Returns zero for success, a negative number on error.
 + */
 +int regmap_update_bits_async(struct regmap *map, unsigned int reg,
 +                           unsigned int mask, unsigned int val)
 +{
 +      bool change;
 +      int ret;
 +
 +      map->lock(map->lock_arg);
 +
 +      map->async = true;
 +
 +      ret = _regmap_update_bits(map, reg, mask, val, &change);
 +
 +      map->async = false;
 +
 +      map->unlock(map->lock_arg);
 +
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(regmap_update_bits_async);
 +
  /**
   * regmap_update_bits_check: Perform a read/modify/write cycle on the
   *                           register map and report if updated
@@@ -1901,43 -1915,6 +2004,43 @@@ int regmap_update_bits_check(struct reg
  }
  EXPORT_SYMBOL_GPL(regmap_update_bits_check);
  
 +/**
 + * regmap_update_bits_check_async: Perform a read/modify/write cycle on the
 + *                                 register map asynchronously and report if
 + *                                 updated
 + *
 + * @map: Register map to update
 + * @reg: Register to update
 + * @mask: Bitmask to change
 + * @val: New value for bitmask
 + * @change: Boolean indicating if a write was done
 + *
 + * With most buses the read must be done synchronously so this is most
 + * useful for devices with a cache which do not need to interact with
 + * the hardware to determine the current register value.
 + *
 + * Returns zero for success, a negative number on error.
 + */
 +int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
 +                                 unsigned int mask, unsigned int val,
 +                                 bool *change)
 +{
 +      int ret;
 +
 +      map->lock(map->lock_arg);
 +
 +      map->async = true;
 +
 +      ret = _regmap_update_bits(map, reg, mask, val, change);
 +
 +      map->async = false;
 +
 +      map->unlock(map->lock_arg);
 +
 +      return ret;
 +}
 +EXPORT_SYMBOL_GPL(regmap_update_bits_check_async);
 +
  void regmap_async_complete_cb(struct regmap_async *async, int ret)
  {
        struct regmap *map = async->map;
        trace_regmap_async_io_complete(map->dev);
  
        spin_lock(&map->async_lock);
 -
 -      list_del(&async->list);
 +      list_move(&async->list, &map->async_free);
        wake = list_empty(&map->async_list);
  
        if (ret != 0)
  
        spin_unlock(&map->async_lock);
  
 -      schedule_work(&async->cleanup);
 -
        if (wake)
                wake_up(&map->async_waitq);
  }
diff --combined include/linux/regmap.h
index 114565befbd2ae6e0a798142a5c5722d84031389,a12bea07f79ef89b184b6e1bab957f70fcf2e636..dc90b8c134a12a9d5b87755a3e27fcfa7b01e0c8
@@@ -374,7 -374,6 +374,7 @@@ int regmap_reinit_cache(struct regmap *
                        const struct regmap_config *config);
  struct regmap *dev_get_regmap(struct device *dev, const char *name);
  int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
 +int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val);
  int regmap_raw_write(struct regmap *map, unsigned int reg,
                     const void *val, size_t val_len);
  int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
@@@ -388,14 -387,9 +388,14 @@@ int regmap_bulk_read(struct regmap *map
                     size_t val_count);
  int regmap_update_bits(struct regmap *map, unsigned int reg,
                       unsigned int mask, unsigned int val);
 +int regmap_update_bits_async(struct regmap *map, unsigned int reg,
 +                           unsigned int mask, unsigned int val);
  int regmap_update_bits_check(struct regmap *map, unsigned int reg,
                             unsigned int mask, unsigned int val,
                             bool *change);
 +int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
 +                                 unsigned int mask, unsigned int val,
 +                                 bool *change);
  int regmap_get_val_bytes(struct regmap *map);
  int regmap_async_complete(struct regmap *map);
  bool regmap_can_raw_write(struct regmap *map);
@@@ -431,11 -425,15 +431,15 @@@ bool regmap_reg_in_ranges(unsigned int 
   * @reg: Offset of the register within the regmap bank
   * @lsb: lsb of the register field.
   * @reg: msb of the register field.
+  * @id_size: port size if it has some ports
+  * @id_offset: address offset for each ports
   */
  struct reg_field {
        unsigned int reg;
        unsigned int lsb;
        unsigned int msb;
+       unsigned int id_size;
+       unsigned int id_offset;
  };
  
  #define REG_FIELD(_reg, _lsb, _msb) {         \
@@@ -454,6 -452,15 +458,15 @@@ void devm_regmap_field_free(struct devi
  
  int regmap_field_read(struct regmap_field *field, unsigned int *val);
  int regmap_field_write(struct regmap_field *field, unsigned int val);
+ int regmap_field_update_bits(struct regmap_field *field,
+                            unsigned int mask, unsigned int val);
+ int regmap_fields_write(struct regmap_field *field, unsigned int id,
+                       unsigned int val);
+ int regmap_fields_read(struct regmap_field *field, unsigned int id,
+                      unsigned int *val);
+ int regmap_fields_update_bits(struct regmap_field *field,  unsigned int id,
+                             unsigned int mask, unsigned int val);
  
  /**
   * Description of an IRQ for the generic regmap irq_chip.
@@@ -533,13 -540,6 +546,13 @@@ static inline int regmap_write(struct r
        return -EINVAL;
  }
  
 +static inline int regmap_write_async(struct regmap *map, unsigned int reg,
 +                                   unsigned int val)
 +{
 +      WARN_ONCE(1, "regmap API is disabled");
 +      return -EINVAL;
 +}
 +
  static inline int regmap_raw_write(struct regmap *map, unsigned int reg,
                                   const void *val, size_t val_len)
  {
@@@ -589,14 -589,6 +602,14 @@@ static inline int regmap_update_bits(st
        return -EINVAL;
  }
  
 +static inline int regmap_update_bits_async(struct regmap *map,
 +                                         unsigned int reg,
 +                                         unsigned int mask, unsigned int val)
 +{
 +      WARN_ONCE(1, "regmap API is disabled");
 +      return -EINVAL;
 +}
 +
  static inline int regmap_update_bits_check(struct regmap *map,
                                           unsigned int reg,
                                           unsigned int mask, unsigned int val,
        return -EINVAL;
  }
  
 +static inline int regmap_update_bits_check_async(struct regmap *map,
 +                                               unsigned int reg,
 +                                               unsigned int mask,
 +                                               unsigned int val,
 +                                               bool *change)
 +{
 +      WARN_ONCE(1, "regmap API is disabled");
 +      return -EINVAL;
 +}
 +
  static inline int regmap_get_val_bytes(struct regmap *map)
  {
        WARN_ONCE(1, "regmap API is disabled");
diff --combined include/sound/rcar_snd.h
index fb0a312bcb810c93622028ef93934d3779189142,6b4211c256b30871f3ee873b05c346a1b090088e..12afab18945d056709df7495b75b0da6c0155426
@@@ -36,7 -36,6 +36,6 @@@
  #define RSND_SSI_CLK_PIN_SHARE                (1 << 31)
  #define RSND_SSI_CLK_FROM_ADG         (1 << 30) /* clock parent is master */
  #define RSND_SSI_SYNC                 (1 << 29) /* SSI34_sync etc */
- #define RSND_SSI_DEPENDENT            (1 << 28) /* SSI needs SRU/SCU */
  
  #define RSND_SSI_PLAY                 (1 << 24)
  
@@@ -68,7 -67,6 +67,7 @@@ struct rsnd_scu_platform_info 
   *
   * A : generation
   */
 +#define RSND_GEN_MASK (0xF << 0)
  #define RSND_GEN1     (1 << 0) /* fixme */
  #define RSND_GEN2     (2 << 0) /* fixme */
  
diff --combined sound/soc/sh/rcar/rsnd.h
index 5dd87f4c919e50650e61e8084856138d47f6f119,5feb67ca2d24f6a61d3f2eacb1e8861b240d3252..9e463e50e7e62b81fabeaeecf39f50de4206eeaf
@@@ -78,10 -78,6 +78,6 @@@ struct rsnd_dai_stream
  #define rsnd_mod_bset(m, r, s, d) \
        rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
  
- #define rsnd_priv_read(p, r)          rsnd_read(p, NULL, RSND_REG_##r)
- #define rsnd_priv_write(p, r, d)      rsnd_write(p, NULL, RSND_REG_##r, d)
- #define rsnd_priv_bset(p, r, s, d)    rsnd_bset(p, NULL, RSND_REG_##r, s, d)
  u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
  void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
                enum rsnd_reg reg, u32 data);
@@@ -220,8 -216,8 +216,8 @@@ int rsnd_gen_path_exit(struct rsnd_pri
  void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
                               struct rsnd_mod *mod,
                               enum rsnd_reg reg);
 -#define rsnd_is_gen1(s)               ((s)->info->flags & RSND_GEN1)
 -#define rsnd_is_gen2(s)               ((s)->info->flags & RSND_GEN2)
 +#define rsnd_is_gen1(s)               (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
 +#define rsnd_is_gen2(s)               (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
  
  /*
   *    R-Car ADG
@@@ -285,6 -281,7 +281,7 @@@ int rsnd_scu_probe(struct platform_devi
  void rsnd_scu_remove(struct platform_device *pdev,
                     struct rsnd_priv *priv);
  struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
+ bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod);
  #define rsnd_scu_nr(priv) ((priv)->scu_nr)
  
  /*