1 /* 2 * rl6347a.c - RL6347A class device shared support 3 * 4 * Copyright 2015 Realtek Semiconductor Corp. 5 * 6 * Author: Oder Chiou <oder_chiou@realtek.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/module.h> 14 #include <linux/moduleparam.h> 15 #include <linux/init.h> 16 #include <linux/delay.h> 17 #include <linux/pm.h> 18 #include <linux/i2c.h> 19 #include <linux/platform_device.h> 20 #include <linux/spi/spi.h> 21 #include <linux/dmi.h> 22 #include <linux/acpi.h> 23 #include <sound/core.h> 24 #include <sound/pcm.h> 25 #include <sound/pcm_params.h> 26 #include <sound/soc.h> 27 #include <sound/soc-dapm.h> 28 #include <sound/initval.h> 29 #include <sound/tlv.h> 30 #include <sound/jack.h> 31 #include <linux/workqueue.h> 32 #include <sound/hda_verbs.h> 33 34 #include "rl6347a.h" 35 36 int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value) 37 { 38 struct i2c_client *client = context; 39 struct rl6347a_priv *rl6347a = i2c_get_clientdata(client); 40 u8 data[4]; 41 int ret, i; 42 43 /* handle index registers */ 44 if (reg <= 0xff) { 45 rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg); 46 for (i = 0; i < rl6347a->index_cache_size; i++) { 47 if (reg == rl6347a->index_cache[i].reg) { 48 rl6347a->index_cache[i].def = value; 49 break; 50 } 51 52 } 53 reg = RL6347A_PROC_COEF; 54 } 55 56 data[0] = (reg >> 24) & 0xff; 57 data[1] = (reg >> 16) & 0xff; 58 /* 59 * 4 bit VID: reg should be 0 60 * 12 bit VID: value should be 0 61 * So we use an OR operator to handle it rather than use if condition. 62 */ 63 data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff); 64 data[3] = value & 0xff; 65 66 ret = i2c_master_send(client, data, 4); 67 68 if (ret == 4) 69 return 0; 70 else 71 pr_err("ret=%d\n", ret); 72 if (ret < 0) 73 return ret; 74 else 75 return -EIO; 76 } 77 EXPORT_SYMBOL_GPL(rl6347a_hw_write); 78 79 int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value) 80 { 81 struct i2c_client *client = context; 82 struct i2c_msg xfer[2]; 83 int ret; 84 __be32 be_reg; 85 unsigned int index, vid, buf = 0x0; 86 87 /* handle index registers */ 88 if (reg <= 0xff) { 89 rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg); 90 reg = RL6347A_PROC_COEF; 91 } 92 93 reg = reg | 0x80000; 94 vid = (reg >> 8) & 0xfff; 95 96 if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) { 97 index = (reg >> 8) & 0xf; 98 reg = (reg & ~0xf0f) | index; 99 } 100 be_reg = cpu_to_be32(reg); 101 102 /* Write register */ 103 xfer[0].addr = client->addr; 104 xfer[0].flags = 0; 105 xfer[0].len = 4; 106 xfer[0].buf = (u8 *)&be_reg; 107 108 /* Read data */ 109 xfer[1].addr = client->addr; 110 xfer[1].flags = I2C_M_RD; 111 xfer[1].len = 4; 112 xfer[1].buf = (u8 *)&buf; 113 114 ret = i2c_transfer(client->adapter, xfer, 2); 115 if (ret < 0) 116 return ret; 117 else if (ret != 2) 118 return -EIO; 119 120 *value = be32_to_cpu(buf); 121 122 return 0; 123 } 124 EXPORT_SYMBOL_GPL(rl6347a_hw_read); 125 126 MODULE_DESCRIPTION("RL6347A class device shared support"); 127 MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 128 MODULE_LICENSE("GPL v2"); 129