Merge branch 'agp-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[sfrench/cifs-2.6.git] / drivers / media / video / cs53l32a.c
1 /*
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>
25 #include <linux/ioctl.h>
26 #include <asm/uaccess.h>
27 #include <linux/i2c.h>
28 #include <linux/i2c-id.h>
29 #include <linux/videodev2.h>
30 #include <media/v4l2-device.h>
31 #include <media/v4l2-chip-ident.h>
32 #include <media/v4l2-i2c-drv.h>
33
34 MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
35 MODULE_AUTHOR("Martin Vaughan");
36 MODULE_LICENSE("GPL");
37
38 static int debug;
39
40 module_param(debug, bool, 0644);
41
42 MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
43
44
45 /* ----------------------------------------------------------------------- */
46
47 static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
48 {
49         struct i2c_client *client = v4l2_get_subdevdata(sd);
50
51         return i2c_smbus_write_byte_data(client, reg, value);
52 }
53
54 static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg)
55 {
56         struct i2c_client *client = v4l2_get_subdevdata(sd);
57
58         return i2c_smbus_read_byte_data(client, reg);
59 }
60
61 static int cs53l32a_s_routing(struct v4l2_subdev *sd,
62                               u32 input, u32 output, u32 config)
63 {
64         /* There are 2 physical inputs, but the second input can be
65            placed in two modes, the first mode bypasses the PGA (gain),
66            the second goes through the PGA. Hence there are three
67            possible inputs to choose from. */
68         if (input > 2) {
69                 v4l2_err(sd, "Invalid input %d.\n", input);
70                 return -EINVAL;
71         }
72         cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
73         return 0;
74 }
75
76 static int cs53l32a_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
77 {
78         if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
79                 ctrl->value = (cs53l32a_read(sd, 0x03) & 0xc0) != 0;
80                 return 0;
81         }
82         if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
83                 return -EINVAL;
84         ctrl->value = (s8)cs53l32a_read(sd, 0x04);
85         return 0;
86 }
87
88 static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
89 {
90         if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
91                 cs53l32a_write(sd, 0x03, ctrl->value ? 0xf0 : 0x30);
92                 return 0;
93         }
94         if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
95                 return -EINVAL;
96         if (ctrl->value > 12 || ctrl->value < -96)
97                 return -EINVAL;
98         cs53l32a_write(sd, 0x04, (u8) ctrl->value);
99         cs53l32a_write(sd, 0x05, (u8) ctrl->value);
100         return 0;
101 }
102
103 static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
104 {
105         struct i2c_client *client = v4l2_get_subdevdata(sd);
106
107         return v4l2_chip_ident_i2c_client(client,
108                         chip, V4L2_IDENT_CS53l32A, 0);
109 }
110
111 static int cs53l32a_log_status(struct v4l2_subdev *sd)
112 {
113         u8 v = cs53l32a_read(sd, 0x01);
114         u8 m = cs53l32a_read(sd, 0x03);
115         s8 vol = cs53l32a_read(sd, 0x04);
116
117         v4l2_info(sd, "Input:  %d%s\n", (v >> 4) & 3,
118                         (m & 0xC0) ? " (muted)" : "");
119         v4l2_info(sd, "Volume: %d dB\n", vol);
120         return 0;
121 }
122
123 /* ----------------------------------------------------------------------- */
124
125 static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
126         .log_status = cs53l32a_log_status,
127         .g_chip_ident = cs53l32a_g_chip_ident,
128         .g_ctrl = cs53l32a_g_ctrl,
129         .s_ctrl = cs53l32a_s_ctrl,
130 };
131
132 static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
133         .s_routing = cs53l32a_s_routing,
134 };
135
136 static const struct v4l2_subdev_ops cs53l32a_ops = {
137         .core = &cs53l32a_core_ops,
138         .audio = &cs53l32a_audio_ops,
139 };
140
141 /* ----------------------------------------------------------------------- */
142
143 /* i2c implementation */
144
145 /*
146  * Generic i2c probe
147  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
148  */
149
150 static int cs53l32a_probe(struct i2c_client *client,
151                           const struct i2c_device_id *id)
152 {
153         struct v4l2_subdev *sd;
154         int i;
155
156         /* Check if the adapter supports the needed features */
157         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
158                 return -EIO;
159
160         if (!id)
161                 strlcpy(client->name, "cs53l32a", sizeof(client->name));
162
163         v4l_info(client, "chip found @ 0x%x (%s)\n",
164                         client->addr << 1, client->adapter->name);
165
166         sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
167         if (sd == NULL)
168                 return -ENOMEM;
169         v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
170
171         for (i = 1; i <= 7; i++) {
172                 u8 v = cs53l32a_read(sd, i);
173
174                 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
175         }
176
177         /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
178
179         cs53l32a_write(sd, 0x01, (u8) 0x21);
180         cs53l32a_write(sd, 0x02, (u8) 0x29);
181         cs53l32a_write(sd, 0x03, (u8) 0x30);
182         cs53l32a_write(sd, 0x04, (u8) 0x00);
183         cs53l32a_write(sd, 0x05, (u8) 0x00);
184         cs53l32a_write(sd, 0x06, (u8) 0x00);
185         cs53l32a_write(sd, 0x07, (u8) 0x00);
186
187         /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
188
189         for (i = 1; i <= 7; i++) {
190                 u8 v = cs53l32a_read(sd, i);
191
192                 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
193         }
194         return 0;
195 }
196
197 static int cs53l32a_remove(struct i2c_client *client)
198 {
199         struct v4l2_subdev *sd = i2c_get_clientdata(client);
200
201         v4l2_device_unregister_subdev(sd);
202         kfree(sd);
203         return 0;
204 }
205
206 static const struct i2c_device_id cs53l32a_id[] = {
207         { "cs53l32a", 0 },
208         { }
209 };
210 MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
211
212 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
213         .name = "cs53l32a",
214         .remove = cs53l32a_remove,
215         .probe = cs53l32a_probe,
216         .id_table = cs53l32a_id,
217 };