Linux Audio

Check our new training course

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