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");
112