1 /*
2 * Driver for CX2081X voice capture IC.
3 *
4 * Copyright: Conexant Systems.
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/i2c.h>
16 #include <linux/interrupt.h>
17 #include <linux/ioport.h>
18 #include <linux/delay.h>
19 #include <linux/slab.h>
20 #include <linux/pm.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/io.h>
23 #include <linux/platform_device.h>
24 #include <linux/timer.h>
25 #include <linux/jiffies.h>
26 #include <linux/delay.h>
27 #include <linux/of.h>
28 #include <linux/of_device.h>
29
30 #include <linux/of_gpio.h>
31 #include <linux/gpio.h>
32
33 #include "cx20810_config.h"
34
i2c_send_array(struct i2c_client * client,const char * buf,int length)35 static int i2c_send_array(struct i2c_client *client,
36 const char *buf, int length)
37 {
38 int i, nwrite;
39 struct device *dev = &client->dev;
40
41 for (i = 0; i < (length / 2); i++) {
42 nwrite = i2c_master_send(client, buf + i * 2, 2);
43 if (nwrite != 2) {
44 dev_err(dev, "i2c send configs error!/n");
45 return -1;
46 }
47 }
48 return 0;
49 }
50
cx20810_set_mode(struct device * dev,int mode,int index)51 static int cx20810_set_mode(struct device *dev, int mode, int index)
52 {
53 struct i2c_client *client = to_i2c_client(dev);
54 int ret;
55 char *param;
56 int length;
57
58 switch (mode) {
59 case CX20810_NORMAL_MODE:
60 param = codec_config_param_normal_mode;
61 length = sizeof(codec_config_param_normal_mode);
62 break;
63 case CX20810_NORMAL_MODE2:
64 param = codec_config_param_normal_mode2;
65 length = sizeof(codec_config_param_normal_mode2);
66 break;
67 case CX20810_NORMAL_MODE_SIMPLE:
68 param = codec_config_param_normal_mode_simple;
69 length = sizeof(codec_config_param_normal_mode_simple);
70 break;
71 case CX20810_48K_16BIT_MODE:
72 param = codec_config_param_48k_16bit_mode;
73 length = sizeof(codec_config_param_48k_16bit_mode);
74 break;
75 case CX20810_96K_16BIT_MODE:
76 param = codec_config_param_96k_16bit_mode;
77 length = sizeof(codec_config_param_96k_16bit_mode);
78 break;
79 case CX20810_NIRMAL_MODE_CODEC3:
80 param = codec3_config_param_normal_mode;
81 length = sizeof(codec3_config_param_normal_mode);
82 break;
83 case CX20810_NIRMAL_MODE_CODEC3_SIMPLE:
84 param = codec3_config_param_normal_mode_simple;
85 length = sizeof(codec3_config_param_normal_mode_simple);
86 break;
87 default:
88 dev_err(dev, "Illegal mode.\n");
89 return 0;
90 }
91
92 ret = i2c_send_array(client, param, length);
93 if (ret != 0) {
94 dev_err(dev, "cx2081x send configs failed!\n");
95 return -1;
96 }
97
98 return 0;
99 }
100
101 /* initial cx20810 */
cx20810_init(struct device * dev,int index,int mode)102 static void cx20810_init(struct device *dev, int index, int mode)
103 {
104 if (cx20810_set_mode(dev, mode, index) < 0)
105 dev_err(dev, "cx20810 set mode fail.\n");
106 }
107
108 static const struct of_device_id of_cx2081x_match[] = {
109 { .compatible = "conexant,cx20810" },
110 { .compatible = "conexant,cx20811" },
111 {},
112 };
113
114 MODULE_DEVICE_TABLE(of, of_cx2081x_match);
115
cx2081x_probe(struct i2c_client * client,const struct i2c_device_id * id)116 static int cx2081x_probe(struct i2c_client *client,
117 const struct i2c_device_id *id)
118 {
119 const struct of_device_id *match;
120 struct device *dev = &client->dev;
121 struct gpio_desc *reset_gpio;
122
123 if (dev->of_node) {
124 match = of_match_device(of_cx2081x_match, dev);
125 if (!match) {
126 dev_err(dev, "Failed to find matching dt id\n");
127 return -EINVAL;
128 }
129 }
130
131 reset_gpio = gpiod_get_optional(dev,
132 "reset", GPIOD_OUT_LOW);
133 if (IS_ERR(reset_gpio)) {
134 int error = PTR_ERR(reset_gpio);
135
136 dev_err(dev, "Failed to request RESET gpio: %d\n", error);
137 } else {
138 gpiod_set_value(reset_gpio, 0);
139 mdelay(10);
140 gpiod_set_value(reset_gpio, 1);
141 /*
142 * we found there are possibilities download configs through
143 * i2c failed, some delay can fix it.
144 */
145 mdelay(10);
146 }
147
148 cx20810_init(dev, 0, CX20810_NORMAL_MODE);
149 if (!IS_ERR(reset_gpio))
150 gpiod_put(reset_gpio);
151
152 return 0;
153 }
154
155 static const struct i2c_device_id cx2081x_id[] = {
156 {"cx20810"},
157 {"cx20811"},
158 {}
159 };
160
161 MODULE_DEVICE_TABLE(i2c, cx20810_id);
162
163 static struct i2c_driver cx2081x_driver = {
164 .driver = {
165 .name = "cx2081x",
166 .of_match_table = of_cx2081x_match,
167 },
168 .probe = cx2081x_probe,
169 .id_table = cx2081x_id,
170 };
171
172 module_i2c_driver(cx2081x_driver);
173
174 MODULE_AUTHOR("Timothy");
175 MODULE_DESCRIPTION("I2C device cx20810 loader");
176 MODULE_LICENSE("GPL");
177