blob: d93e5ab45fd31baadc8a325265f30911ef7dcbe8 [file] [log] [blame]
Hans Verkuilf4067fd2005-11-08 21:37:55 -08001/*
2 * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver.
3 * Copyright (C) 2005 Martin Vaughan
4 *
5 * Audio source switching for Adaptec AVC-2410 added by Trev Jackson
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 as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23#include <linux/module.h>
24#include <linux/types.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Hans Verkuilf4067fd2005-11-08 21:37:55 -080026#include <linux/ioctl.h>
27#include <asm/uaccess.h>
28#include <linux/i2c.h>
Hans Verkuil33b687c2008-07-25 05:32:50 -030029#include <linux/videodev2.h>
Hans Verkuil825c6aa2008-11-29 12:45:59 -030030#include <media/v4l2-device.h>
Hans Verkuil74cab312007-04-27 12:31:26 -030031#include <media/v4l2-chip-ident.h>
Hans Verkuil251190c2010-04-23 10:39:25 -030032#include <media/v4l2-ctrls.h>
Hans Verkuilf4067fd2005-11-08 21:37:55 -080033
34MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
35MODULE_AUTHOR("Martin Vaughan");
36MODULE_LICENSE("GPL");
37
Hans Verkuil4c05de92007-11-01 07:54:57 -030038static int debug;
Hans Verkuilf4067fd2005-11-08 21:37:55 -080039
40module_param(debug, bool, 0644);
41
Niels de Vos61a2d072008-07-31 00:07:23 -070042MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
Hans Verkuilf4067fd2005-11-08 21:37:55 -080043
Hans Verkuilf4067fd2005-11-08 21:37:55 -080044
Hans Verkuil251190c2010-04-23 10:39:25 -030045struct cs53l32a_state {
46 struct v4l2_subdev sd;
47 struct v4l2_ctrl_handler hdl;
48};
49
50static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
51{
52 return container_of(sd, struct cs53l32a_state, sd);
53}
54
55static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
56{
57 return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
58}
59
Hans Verkuilf4067fd2005-11-08 21:37:55 -080060/* ----------------------------------------------------------------------- */
61
Hans Verkuil825c6aa2008-11-29 12:45:59 -030062static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuilf4067fd2005-11-08 21:37:55 -080063{
Hans Verkuil825c6aa2008-11-29 12:45:59 -030064 struct i2c_client *client = v4l2_get_subdevdata(sd);
65
Hans Verkuilf4067fd2005-11-08 21:37:55 -080066 return i2c_smbus_write_byte_data(client, reg, value);
67}
68
Hans Verkuil825c6aa2008-11-29 12:45:59 -030069static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuilf4067fd2005-11-08 21:37:55 -080070{
Hans Verkuil825c6aa2008-11-29 12:45:59 -030071 struct i2c_client *client = v4l2_get_subdevdata(sd);
72
Hans Verkuilf4067fd2005-11-08 21:37:55 -080073 return i2c_smbus_read_byte_data(client, reg);
74}
75
Hans Verkuil5325b422009-04-02 11:26:22 -030076static int cs53l32a_s_routing(struct v4l2_subdev *sd,
77 u32 input, u32 output, u32 config)
Hans Verkuil825c6aa2008-11-29 12:45:59 -030078{
79 /* There are 2 physical inputs, but the second input can be
80 placed in two modes, the first mode bypasses the PGA (gain),
81 the second goes through the PGA. Hence there are three
82 possible inputs to choose from. */
Hans Verkuil5325b422009-04-02 11:26:22 -030083 if (input > 2) {
84 v4l2_err(sd, "Invalid input %d.\n", input);
Hans Verkuil825c6aa2008-11-29 12:45:59 -030085 return -EINVAL;
86 }
Hans Verkuil5325b422009-04-02 11:26:22 -030087 cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
Hans Verkuil825c6aa2008-11-29 12:45:59 -030088 return 0;
89}
90
Hans Verkuil251190c2010-04-23 10:39:25 -030091static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuil825c6aa2008-11-29 12:45:59 -030092{
Hans Verkuil251190c2010-04-23 10:39:25 -030093 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil825c6aa2008-11-29 12:45:59 -030094
Hans Verkuil251190c2010-04-23 10:39:25 -030095 switch (ctrl->id) {
96 case V4L2_CID_AUDIO_MUTE:
97 cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
98 return 0;
99 case V4L2_CID_AUDIO_VOLUME:
100 cs53l32a_write(sd, 0x04, (u8)ctrl->val);
101 cs53l32a_write(sd, 0x05, (u8)ctrl->val);
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300102 return 0;
103 }
Hans Verkuil251190c2010-04-23 10:39:25 -0300104 return -EINVAL;
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300105}
106
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300107static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300108{
109 struct i2c_client *client = v4l2_get_subdevdata(sd);
110
111 return v4l2_chip_ident_i2c_client(client,
112 chip, V4L2_IDENT_CS53l32A, 0);
113}
114
115static int cs53l32a_log_status(struct v4l2_subdev *sd)
116{
Hans Verkuil251190c2010-04-23 10:39:25 -0300117 struct cs53l32a_state *state = to_state(sd);
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300118 u8 v = cs53l32a_read(sd, 0x01);
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300119
Hans Verkuil251190c2010-04-23 10:39:25 -0300120 v4l2_info(sd, "Input: %d\n", (v >> 4) & 3);
121 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300122 return 0;
123}
124
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800125/* ----------------------------------------------------------------------- */
126
Hans Verkuil251190c2010-04-23 10:39:25 -0300127static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
128 .s_ctrl = cs53l32a_s_ctrl,
129};
130
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300131static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
132 .log_status = cs53l32a_log_status,
133 .g_chip_ident = cs53l32a_g_chip_ident,
Hans Verkuil251190c2010-04-23 10:39:25 -0300134 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
135 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
136 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
137 .g_ctrl = v4l2_subdev_g_ctrl,
138 .s_ctrl = v4l2_subdev_s_ctrl,
139 .queryctrl = v4l2_subdev_queryctrl,
140 .querymenu = v4l2_subdev_querymenu,
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300141};
142
143static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
144 .s_routing = cs53l32a_s_routing,
145};
146
147static const struct v4l2_subdev_ops cs53l32a_ops = {
148 .core = &cs53l32a_core_ops,
149 .audio = &cs53l32a_audio_ops,
150};
151
152/* ----------------------------------------------------------------------- */
153
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800154/* i2c implementation */
155
156/*
157 * Generic i2c probe
158 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
159 */
160
Jean Delvared2653e92008-04-29 23:11:39 +0200161static int cs53l32a_probe(struct i2c_client *client,
162 const struct i2c_device_id *id)
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800163{
Hans Verkuil251190c2010-04-23 10:39:25 -0300164 struct cs53l32a_state *state;
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300165 struct v4l2_subdev *sd;
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800166 int i;
167
168 /* Check if the adapter supports the needed features */
Hans Verkuile8e6b992007-09-13 11:30:38 -0300169 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -0300170 return -EIO;
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800171
Jean Delvareaf294862008-05-18 20:49:40 +0200172 if (!id)
173 strlcpy(client->name, "cs53l32a", sizeof(client->name));
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800174
Hans Verkuil4c05de92007-11-01 07:54:57 -0300175 v4l_info(client, "chip found @ 0x%x (%s)\n",
176 client->addr << 1, client->adapter->name);
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800177
Hans Verkuil251190c2010-04-23 10:39:25 -0300178 state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL);
179 if (state == NULL)
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300180 return -ENOMEM;
Hans Verkuil251190c2010-04-23 10:39:25 -0300181 sd = &state->sd;
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300182 v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800183
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300184 for (i = 1; i <= 7; i++) {
185 u8 v = cs53l32a_read(sd, i);
186
187 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800188 }
189
Hans Verkuil251190c2010-04-23 10:39:25 -0300190 v4l2_ctrl_handler_init(&state->hdl, 2);
191 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
192 V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
193 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
194 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
195 sd->ctrl_handler = &state->hdl;
196 if (state->hdl.error) {
197 int err = state->hdl.error;
198
199 v4l2_ctrl_handler_free(&state->hdl);
200 kfree(state);
201 return err;
202 }
203
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800204 /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
205
Hans Verkuil251190c2010-04-23 10:39:25 -0300206 cs53l32a_write(sd, 0x01, 0x21);
207 cs53l32a_write(sd, 0x02, 0x29);
208 cs53l32a_write(sd, 0x03, 0x30);
209 cs53l32a_write(sd, 0x04, 0x00);
210 cs53l32a_write(sd, 0x05, 0x00);
211 cs53l32a_write(sd, 0x06, 0x00);
212 cs53l32a_write(sd, 0x07, 0x00);
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800213
214 /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
215
216 for (i = 1; i <= 7; i++) {
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300217 u8 v = cs53l32a_read(sd, i);
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800218
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300219 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800220 }
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800221 return 0;
222}
223
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300224static int cs53l32a_remove(struct i2c_client *client)
225{
226 struct v4l2_subdev *sd = i2c_get_clientdata(client);
Hans Verkuil251190c2010-04-23 10:39:25 -0300227 struct cs53l32a_state *state = to_state(sd);
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300228
229 v4l2_device_unregister_subdev(sd);
Hans Verkuil251190c2010-04-23 10:39:25 -0300230 v4l2_ctrl_handler_free(&state->hdl);
231 kfree(state);
Hans Verkuil825c6aa2008-11-29 12:45:59 -0300232 return 0;
233}
234
Jean Delvareaf294862008-05-18 20:49:40 +0200235static const struct i2c_device_id cs53l32a_id[] = {
236 { "cs53l32a", 0 },
237 { }
238};
239MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
240
Hans Verkuil50337ace2010-09-15 15:42:38 -0300241static struct i2c_driver cs53l32a_driver = {
242 .driver = {
243 .owner = THIS_MODULE,
244 .name = "cs53l32a",
245 },
246 .probe = cs53l32a_probe,
247 .remove = cs53l32a_remove,
248 .id_table = cs53l32a_id,
Hans Verkuilf4067fd2005-11-08 21:37:55 -0800249};
Hans Verkuil50337ace2010-09-15 15:42:38 -0300250
251static __init int init_cs53l32a(void)
252{
253 return i2c_add_driver(&cs53l32a_driver);
254}
255
256static __exit void exit_cs53l32a(void)
257{
258 i2c_del_driver(&cs53l32a_driver);
259}
260
261module_init(init_cs53l32a);
262module_exit(exit_cs53l32a);