ASoC: Merge branch 'for-2.6.39' into for-2.6.40
[firefly-linux-kernel-4.4.55.git] / sound / soc / soc-cache.c
index 4ee473d6057abae81938a2fd88a05974d927da86..f46a198a48c0928f847ccf5458f99f893fe95be8 100644 (file)
 
 #include <trace/events/asoc.h>
 
+#if defined(CONFIG_SPI_MASTER)
+static int do_spi_write(void *control_data, const void *msg,
+                       int len)
+{
+       struct spi_device *spi = control_data;
+       struct spi_transfer t;
+       struct spi_message m;
+
+       if (len <= 0)
+               return 0;
+
+       spi_message_init(&m);
+       memset(&t, 0, sizeof t);
+
+       t.tx_buf = msg;
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+#endif
+
 static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
                       unsigned int value, const void *data, int len)
 {
@@ -47,20 +71,19 @@ static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
                return -EIO;
 }
 
-static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
-                                    unsigned int reg)
+static unsigned int do_hw_read(struct snd_soc_codec *codec, unsigned int reg)
 {
        int ret;
        unsigned int val;
 
        if (reg >= codec->driver->reg_cache_size ||
-               snd_soc_codec_volatile_register(codec, reg) ||
-               codec->cache_bypass) {
-                       if (codec->cache_only)
-                               return -1;
+           snd_soc_codec_volatile_register(codec, reg) ||
+           codec->cache_bypass) {
+               if (codec->cache_only)
+                       return -1;
 
-                       BUG_ON(!codec->hw_read);
-                       return codec->hw_read(codec, reg);
+               BUG_ON(!codec->hw_read);
+               return codec->hw_read(codec, reg);
        }
 
        ret = snd_soc_cache_read(codec, reg, &val);
@@ -69,8 +92,14 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
        return val;
 }
 
+static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
+                                     unsigned int reg)
+{
+       return do_hw_read(codec, reg);
+}
+
 static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
-                            unsigned int value)
+                             unsigned int value)
 {
        u8 data[2];
 
@@ -82,29 +111,14 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
 
 #if defined(CONFIG_SPI_MASTER)
 static int snd_soc_4_12_spi_write(void *control_data, const char *data,
-                                int len)
+                                 int len)
 {
-       struct spi_device *spi = control_data;
-       struct spi_transfer t;
-       struct spi_message m;
        u8 msg[2];
 
-       if (len <= 0)
-               return 0;
-
        msg[0] = data[1];
        msg[1] = data[0];
 
-       spi_message_init(&m);
-       memset(&t, 0, sizeof t);
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
+       return do_spi_write(control_data, msg, len);
 }
 #else
 #define snd_soc_4_12_spi_write NULL
@@ -113,23 +127,7 @@ static int snd_soc_4_12_spi_write(void *control_data, const char *data,
 static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
                                     unsigned int reg)
 {
-       int ret;
-       unsigned int val;
-
-       if (reg >= codec->driver->reg_cache_size ||
-               snd_soc_codec_volatile_register(codec, reg) ||
-               codec->cache_bypass) {
-                       if (codec->cache_only)
-                               return -1;
-
-                       BUG_ON(!codec->hw_read);
-                       return codec->hw_read(codec, reg);
-       }
-
-       ret = snd_soc_cache_read(codec, reg, &val);
-       if (ret < 0)
-               return -1;
-       return val;
+       return do_hw_read(codec, reg);
 }
 
 static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
@@ -147,27 +145,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
 static int snd_soc_7_9_spi_write(void *control_data, const char *data,
                                 int len)
 {
-       struct spi_device *spi = control_data;
-       struct spi_transfer t;
-       struct spi_message m;
        u8 msg[2];
 
-       if (len <= 0)
-               return 0;
-
        msg[0] = data[0];
        msg[1] = data[1];
 
-       spi_message_init(&m);
-       memset(&t, 0, sizeof t);
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
+       return do_spi_write(control_data, msg, len);
 }
 #else
 #define snd_soc_7_9_spi_write NULL
@@ -188,51 +171,19 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
 static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
                                     unsigned int reg)
 {
-       int ret;
-       unsigned int val;
-
-       reg &= 0xff;
-       if (reg >= codec->driver->reg_cache_size ||
-               snd_soc_codec_volatile_register(codec, reg) ||
-               codec->cache_bypass) {
-                       if (codec->cache_only)
-                               return -1;
-
-                       BUG_ON(!codec->hw_read);
-                       return codec->hw_read(codec, reg);
-       }
-
-       ret = snd_soc_cache_read(codec, reg, &val);
-       if (ret < 0)
-               return -1;
-       return val;
+       return do_hw_read(codec, reg);
 }
 
 #if defined(CONFIG_SPI_MASTER)
 static int snd_soc_8_8_spi_write(void *control_data, const char *data,
                                 int len)
 {
-       struct spi_device *spi = control_data;
-       struct spi_transfer t;
-       struct spi_message m;
        u8 msg[2];
 
-       if (len <= 0)
-               return 0;
-
        msg[0] = data[0];
        msg[1] = data[1];
 
-       spi_message_init(&m);
-       memset(&t, 0, sizeof t);
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
+       return do_spi_write(control_data, msg, len);
 }
 #else
 #define snd_soc_8_8_spi_write NULL
@@ -253,51 +204,20 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
 static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
                                      unsigned int reg)
 {
-       int ret;
-       unsigned int val;
-
-       if (reg >= codec->driver->reg_cache_size ||
-           snd_soc_codec_volatile_register(codec, reg) ||
-           codec->cache_bypass) {
-               if (codec->cache_only)
-                       return -1;
-
-               BUG_ON(!codec->hw_read);
-               return codec->hw_read(codec, reg);
-       }
-
-       ret = snd_soc_cache_read(codec, reg, &val);
-       if (ret < 0)
-               return -1;
-       return val;
+       return do_hw_read(codec, reg);
 }
 
 #if defined(CONFIG_SPI_MASTER)
 static int snd_soc_8_16_spi_write(void *control_data, const char *data,
-                                int len)
+                                 int len)
 {
-       struct spi_device *spi = control_data;
-       struct spi_transfer t;
-       struct spi_message m;
        u8 msg[3];
 
-       if (len <= 0)
-               return 0;
-
        msg[0] = data[0];
        msg[1] = data[1];
        msg[2] = data[2];
 
-       spi_message_init(&m);
-       memset(&t, 0, sizeof t);
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
+       return do_spi_write(control_data, msg, len);
 }
 #else
 #define snd_soc_8_16_spi_write NULL
@@ -325,7 +245,6 @@ static unsigned int do_i2c_read(struct snd_soc_codec *codec,
        xfer[1].buf = data;
 
        ret = i2c_transfer(client->adapter, xfer, 2);
-       dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
        if (ret == 2)
                return 0;
        else if (ret < 0)
@@ -337,7 +256,7 @@ static unsigned int do_i2c_read(struct snd_soc_codec *codec,
 
 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
 static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
-                                         unsigned int r)
+                                        unsigned int r)
 {
        u8 reg = r;
        u8 data;
@@ -387,30 +306,13 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
 #endif
 
 static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
-                                    unsigned int reg)
+                                     unsigned int reg)
 {
-       int ret;
-       unsigned int val;
-
-       reg &= 0xff;
-       if (reg >= codec->driver->reg_cache_size ||
-               snd_soc_codec_volatile_register(codec, reg) ||
-               codec->cache_bypass) {
-                       if (codec->cache_only)
-                               return -1;
-
-                       BUG_ON(!codec->hw_read);
-                       return codec->hw_read(codec, reg);
-       }
-
-       ret = snd_soc_cache_read(codec, reg, &val);
-       if (ret < 0)
-               return -1;
-       return val;
+       return do_hw_read(codec, reg);
 }
 
 static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
-                            unsigned int value)
+                             unsigned int value)
 {
        u8 data[3];
 
@@ -424,30 +326,15 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
 
 #if defined(CONFIG_SPI_MASTER)
 static int snd_soc_16_8_spi_write(void *control_data, const char *data,
-                                int len)
+                                 int len)
 {
-       struct spi_device *spi = control_data;
-       struct spi_transfer t;
-       struct spi_message m;
        u8 msg[3];
 
-       if (len <= 0)
-               return 0;
-
        msg[0] = data[0];
        msg[1] = data[1];
        msg[2] = data[2];
 
-       spi_message_init(&m);
-       memset(&t, 0, sizeof t);
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
+       return do_spi_write(control_data, msg, len);
 }
 #else
 #define snd_soc_16_8_spi_write NULL
@@ -473,24 +360,7 @@ static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
 static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
                                       unsigned int reg)
 {
-       int ret;
-       unsigned int val;
-
-       if (reg >= codec->driver->reg_cache_size ||
-           snd_soc_codec_volatile_register(codec, reg) ||
-           codec->cache_bypass) {
-               if (codec->cache_only)
-                       return -1;
-
-               BUG_ON(!codec->hw_read);
-               return codec->hw_read(codec, reg);
-       }
-
-       ret = snd_soc_cache_read(codec, reg, &val);
-       if (ret < 0)
-               return -1;
-
-       return val;
+       return do_hw_read(codec, reg);
 }
 
 static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
@@ -508,40 +378,26 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
 
 #if defined(CONFIG_SPI_MASTER)
 static int snd_soc_16_16_spi_write(void *control_data, const char *data,
-                                int len)
+                                  int len)
 {
-       struct spi_device *spi = control_data;
-       struct spi_transfer t;
-       struct spi_message m;
        u8 msg[4];
 
-       if (len <= 0)
-               return 0;
-
        msg[0] = data[0];
        msg[1] = data[1];
        msg[2] = data[2];
        msg[3] = data[3];
 
-       spi_message_init(&m);
-       memset(&t, 0, sizeof t);
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
+       return do_spi_write(control_data, msg, len);
 }
 #else
 #define snd_soc_16_16_spi_write NULL
 #endif
 
-/* Primitive bulk write support for soc-cache.  The data pointed to by `data' needs
- * to already be in the form the hardware expects including any leading register specific
- * data.  Any data written through this function will not go through the cache as it
- * only handles writing to volatile or out of bounds registers.
+/* Primitive bulk write support for soc-cache.  The data pointed to by
+ * `data' needs to already be in the form the hardware expects
+ * including any leading register specific data.  Any data written
+ * through this function will not go through the cache as it only
+ * handles writing to volatile or out of bounds registers.
  */
 static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
                                     const void *data, size_t len)
@@ -558,12 +414,16 @@ static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int r
                return -EINVAL;
 
        switch (codec->control_type) {
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
        case SND_SOC_I2C:
                ret = i2c_master_send(codec->control_data, data, len);
                break;
+#endif
+#if defined(CONFIG_SPI_MASTER)
        case SND_SOC_SPI:
                ret = do_spi_write(codec->control_data, data, len);
                break;
+#endif
        default:
                BUG();
        }
@@ -805,6 +665,8 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
                rbnode = rb_entry(node, struct snd_soc_rbtree_node, node);
                if (rbnode->value == rbnode->defval)
                        continue;
+               WARN_ON(codec->writable_register &&
+                       codec->writable_register(codec, rbnode->reg));
                ret = snd_soc_cache_read(codec, rbnode->reg, &val);
                if (ret)
                        return ret;
@@ -1065,6 +927,8 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
 
        lzo_blocks = codec->reg_cache;
        for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
+               WARN_ON(codec->writable_register &&
+                       codec->writable_register(codec, i));
                ret = snd_soc_cache_read(codec, i, &val);
                if (ret)
                        return ret;
@@ -1323,6 +1187,8 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 
        codec_drv = codec->driver;
        for (i = 0; i < codec_drv->reg_cache_size; ++i) {
+               WARN_ON(codec->writable_register &&
+                       codec->writable_register(codec, i));
                ret = snd_soc_cache_read(codec, i, &val);
                if (ret)
                        return ret;
@@ -1439,7 +1305,7 @@ int snd_soc_cache_init(struct snd_soc_codec *codec)
                                codec->cache_ops->name, codec->name);
                return codec->cache_ops->init(codec);
        }
-       return -EINVAL;
+       return -ENOSYS;
 }
 
 /*
@@ -1454,7 +1320,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec)
                                codec->cache_ops->name, codec->name);
                return codec->cache_ops->exit(codec);
        }
-       return -EINVAL;
+       return -ENOSYS;
 }
 
 /**
@@ -1478,7 +1344,7 @@ int snd_soc_cache_read(struct snd_soc_codec *codec,
        }
 
        mutex_unlock(&codec->cache_rw_mutex);
-       return -EINVAL;
+       return -ENOSYS;
 }
 EXPORT_SYMBOL_GPL(snd_soc_cache_read);
 
@@ -1503,7 +1369,7 @@ int snd_soc_cache_write(struct snd_soc_codec *codec,
        }
 
        mutex_unlock(&codec->cache_rw_mutex);
-       return -EINVAL;
+       return -ENOSYS;
 }
 EXPORT_SYMBOL_GPL(snd_soc_cache_write);
 
@@ -1526,7 +1392,7 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec)
        }
 
        if (!codec->cache_ops || !codec->cache_ops->sync)
-               return -EINVAL;
+               return -ENOSYS;
 
        if (codec->cache_ops->name)
                name = codec->cache_ops->name;
@@ -1593,3 +1459,17 @@ int snd_soc_default_readable_register(struct snd_soc_codec *codec,
        return codec->driver->reg_access_default[index].read;
 }
 EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
+
+int snd_soc_default_writable_register(struct snd_soc_codec *codec,
+                                     unsigned int reg)
+{
+       int index;
+
+       if (reg >= codec->driver->reg_cache_size)
+               return 1;
+       index = snd_soc_get_reg_access_index(codec, reg);
+       if (index < 0)
+               return 0;
+       return codec->driver->reg_access_default[index].write;
+}
+EXPORT_SYMBOL_GPL(snd_soc_default_writable_register);