Loading...
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");
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");