cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rl6347a.c (2393B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * rl6347a.c - RL6347A class device shared support
      4 *
      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 0
     40	 * 12 bit VID: value should be 0
     41	 * 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	else
     51		dev_err(&client->dev, "I2C error %d\n", ret);
     52	if (ret < 0)
     53		return ret;
     54	else
     55		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");