Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * rl6347a.c - RL6347A class device shared support
0004  *
0005  * Copyright 2015 Realtek Semiconductor Corp.
0006  *
0007  * Author: Oder Chiou <oder_chiou@realtek.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/i2c.h>
0012 #include <linux/regmap.h>
0013 
0014 #include "rl6347a.h"
0015 
0016 int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
0017 {
0018     struct i2c_client *client = context;
0019     struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);
0020     u8 data[4];
0021     int ret, i;
0022 
0023     /* handle index registers */
0024     if (reg <= 0xff) {
0025         rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
0026         for (i = 0; i < rl6347a->index_cache_size; i++) {
0027             if (reg == rl6347a->index_cache[i].reg) {
0028                 rl6347a->index_cache[i].def = value;
0029                 break;
0030             }
0031 
0032         }
0033         reg = RL6347A_PROC_COEF;
0034     }
0035 
0036     data[0] = (reg >> 24) & 0xff;
0037     data[1] = (reg >> 16) & 0xff;
0038     /*
0039      * 4 bit VID: reg should be 0
0040      * 12 bit VID: value should be 0
0041      * So we use an OR operator to handle it rather than use if condition.
0042      */
0043     data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
0044     data[3] = value & 0xff;
0045 
0046     ret = i2c_master_send(client, data, 4);
0047 
0048     if (ret == 4)
0049         return 0;
0050     else
0051         dev_err(&client->dev, "I2C error %d\n", ret);
0052     if (ret < 0)
0053         return ret;
0054     else
0055         return -EIO;
0056 }
0057 EXPORT_SYMBOL_GPL(rl6347a_hw_write);
0058 
0059 int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
0060 {
0061     struct i2c_client *client = context;
0062     struct i2c_msg xfer[2];
0063     int ret;
0064     __be32 be_reg, buf = 0x0;
0065     unsigned int index, vid;
0066 
0067     /* handle index registers */
0068     if (reg <= 0xff) {
0069         rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
0070         reg = RL6347A_PROC_COEF;
0071     }
0072 
0073     reg = reg | 0x80000;
0074     vid = (reg >> 8) & 0xfff;
0075 
0076     if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
0077         index = (reg >> 8) & 0xf;
0078         reg = (reg & ~0xf0f) | index;
0079     }
0080     be_reg = cpu_to_be32(reg);
0081 
0082     /* Write register */
0083     xfer[0].addr = client->addr;
0084     xfer[0].flags = 0;
0085     xfer[0].len = 4;
0086     xfer[0].buf = (u8 *)&be_reg;
0087 
0088     /* Read data */
0089     xfer[1].addr = client->addr;
0090     xfer[1].flags = I2C_M_RD;
0091     xfer[1].len = 4;
0092     xfer[1].buf = (u8 *)&buf;
0093 
0094     ret = i2c_transfer(client->adapter, xfer, 2);
0095     if (ret < 0)
0096         return ret;
0097     else if (ret != 2)
0098         return -EIO;
0099 
0100     *value = be32_to_cpu(buf);
0101 
0102     return 0;
0103 }
0104 EXPORT_SYMBOL_GPL(rl6347a_hw_read);
0105 
0106 MODULE_DESCRIPTION("RL6347A class device shared support");
0107 MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
0108 MODULE_LICENSE("GPL v2");