109 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * rl6347a.c - RL6347A class device shared support4 *5 * Copyright 2015 Realtek Semiconductor Corp.6 *7 * Author: Oder Chiou <oder_chiou@realtek.com>8 */9 10#include <linux/module.h>11#include <linux/i2c.h>12#include <linux/regmap.h>13 14#include "rl6347a.h"15 16int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)17{18 struct i2c_client *client = context;19 struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);20 u8 data[4];21 int ret, i;22 23 /* handle index registers */24 if (reg <= 0xff) {25 rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);26 for (i = 0; i < rl6347a->index_cache_size; i++) {27 if (reg == rl6347a->index_cache[i].reg) {28 rl6347a->index_cache[i].def = value;29 break;30 }31 32 }33 reg = RL6347A_PROC_COEF;34 }35 36 data[0] = (reg >> 24) & 0xff;37 data[1] = (reg >> 16) & 0xff;38 /*39 * 4 bit VID: reg should be 040 * 12 bit VID: value should be 041 * So we use an OR operator to handle it rather than use if condition.42 */43 data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);44 data[3] = value & 0xff;45 46 ret = i2c_master_send(client, data, 4);47 48 if (ret == 4)49 return 0;50 else51 dev_err(&client->dev, "I2C error %d\n", ret);52 if (ret < 0)53 return ret;54 else55 return -EIO;56}57EXPORT_SYMBOL_GPL(rl6347a_hw_write);58 59int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)60{61 struct i2c_client *client = context;62 struct i2c_msg xfer[2];63 int ret;64 __be32 be_reg, buf = 0x0;65 unsigned int index, vid;66 67 /* handle index registers */68 if (reg <= 0xff) {69 rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);70 reg = RL6347A_PROC_COEF;71 }72 73 reg = reg | 0x80000;74 vid = (reg >> 8) & 0xfff;75 76 if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {77 index = (reg >> 8) & 0xf;78 reg = (reg & ~0xf0f) | index;79 }80 be_reg = cpu_to_be32(reg);81 82 /* Write register */83 xfer[0].addr = client->addr;84 xfer[0].flags = 0;85 xfer[0].len = 4;86 xfer[0].buf = (u8 *)&be_reg;87 88 /* Read data */89 xfer[1].addr = client->addr;90 xfer[1].flags = I2C_M_RD;91 xfer[1].len = 4;92 xfer[1].buf = (u8 *)&buf;93 94 ret = i2c_transfer(client->adapter, xfer, 2);95 if (ret < 0)96 return ret;97 else if (ret != 2)98 return -EIO;99 100 *value = be32_to_cpu(buf);101 102 return 0;103}104EXPORT_SYMBOL_GPL(rl6347a_hw_read);105 106MODULE_DESCRIPTION("RL6347A class device shared support");107MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");108MODULE_LICENSE("GPL v2");109