These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / sound / soc / codecs / rl6347a.c
diff --git a/kernel/sound/soc/codecs/rl6347a.c b/kernel/sound/soc/codecs/rl6347a.c
new file mode 100644 (file)
index 0000000..a4b910e
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * rl6347a.c - RL6347A class device shared support
+ *
+ * Copyright 2015 Realtek Semiconductor Corp.
+ *
+ * Author: Oder Chiou <oder_chiou@realtek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include "rl6347a.h"
+
+int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
+{
+       struct i2c_client *client = context;
+       struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);
+       u8 data[4];
+       int ret, i;
+
+       /* handle index registers */
+       if (reg <= 0xff) {
+               rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
+               for (i = 0; i < rl6347a->index_cache_size; i++) {
+                       if (reg == rl6347a->index_cache[i].reg) {
+                               rl6347a->index_cache[i].def = value;
+                               break;
+                       }
+
+               }
+               reg = RL6347A_PROC_COEF;
+       }
+
+       data[0] = (reg >> 24) & 0xff;
+       data[1] = (reg >> 16) & 0xff;
+       /*
+        * 4 bit VID: reg should be 0
+        * 12 bit VID: value should be 0
+        * So we use an OR operator to handle it rather than use if condition.
+        */
+       data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
+       data[3] = value & 0xff;
+
+       ret = i2c_master_send(client, data, 4);
+
+       if (ret == 4)
+               return 0;
+       else
+               pr_err("ret=%d\n", ret);
+       if (ret < 0)
+               return ret;
+       else
+               return -EIO;
+}
+EXPORT_SYMBOL_GPL(rl6347a_hw_write);
+
+int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
+{
+       struct i2c_client *client = context;
+       struct i2c_msg xfer[2];
+       int ret;
+       __be32 be_reg;
+       unsigned int index, vid, buf = 0x0;
+
+       /* handle index registers */
+       if (reg <= 0xff) {
+               rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
+               reg = RL6347A_PROC_COEF;
+       }
+
+       reg = reg | 0x80000;
+       vid = (reg >> 8) & 0xfff;
+
+       if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
+               index = (reg >> 8) & 0xf;
+               reg = (reg & ~0xf0f) | index;
+       }
+       be_reg = cpu_to_be32(reg);
+
+       /* Write register */
+       xfer[0].addr = client->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 4;
+       xfer[0].buf = (u8 *)&be_reg;
+
+       /* Read data */
+       xfer[1].addr = client->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = 4;
+       xfer[1].buf = (u8 *)&buf;
+
+       ret = i2c_transfer(client->adapter, xfer, 2);
+       if (ret < 0)
+               return ret;
+       else if (ret != 2)
+               return -EIO;
+
+       *value = be32_to_cpu(buf);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rl6347a_hw_read);
+
+MODULE_DESCRIPTION("RL6347A class device shared support");
+MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
+MODULE_LICENSE("GPL v2");