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