V4L/DVB (3246): Use VIDIOC_S_AUDIO instead of AUDC_SET_INPUT in cs53l32a
[linux-2.6-microblaze.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/videodev.h>
30 #include <media/audiochip.h>
31
32 MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
33 MODULE_AUTHOR("Martin Vaughan");
34 MODULE_LICENSE("GPL");
35
36 static int debug = 0;
37
38 module_param(debug, bool, 0644);
39
40 MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
41
42 #define cs53l32a_dbg(fmt, arg...) \
43         do { \
44                 if (debug) \
45                         printk(KERN_INFO "%s debug %d-%04x: " fmt, \
46                                client->driver->driver.name, \
47                                i2c_adapter_id(client->adapter), client->addr , ## arg); \
48         } while (0)
49
50 #define cs53l32a_err(fmt, arg...) do { \
51         printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
52                 i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
53 #define cs53l32a_info(fmt, arg...) do { \
54         printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
55                 i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
56
57 static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
58
59
60 I2C_CLIENT_INSMOD;
61
62 /* ----------------------------------------------------------------------- */
63
64 static int cs53l32a_write(struct i2c_client *client, u8 reg, u8 value)
65 {
66         return i2c_smbus_write_byte_data(client, reg, value);
67 }
68
69 static int cs53l32a_read(struct i2c_client *client, u8 reg)
70 {
71         return i2c_smbus_read_byte_data(client, reg);
72 }
73
74 static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
75                             void *arg)
76 {
77         struct v4l2_audio *input = arg;
78         struct v4l2_control *ctrl = arg;
79
80         switch (cmd) {
81         case VIDIOC_S_AUDIO:
82                 /* There are 2 physical inputs, but the second input can be
83                    placed in two modes, the first mode bypasses the PGA (gain),
84                    the second goes through the PGA. Hence there are three
85                    possible inputs to choose from. */
86                 if (input->index > 2) {
87                         cs53l32a_err("Invalid input %d.\n", input->index);
88                         return -EINVAL;
89                 }
90                 cs53l32a_write(client, 0x01, 0x01 + (input->index << 4));
91                 break;
92
93         case VIDIOC_G_AUDIO:
94                 memset(input, 0, sizeof(*input));
95                 input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
96                 break;
97
98         case VIDIOC_G_CTRL:
99                 if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
100                         ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0;
101                         break;
102                 }
103                 if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
104                         return -EINVAL;
105                 ctrl->value = (s8)cs53l32a_read(client, 0x04);
106                 break;
107
108         case VIDIOC_S_CTRL:
109                 if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
110                         cs53l32a_write(client, 0x03, ctrl->value ? 0xf0 : 0x30);
111                         break;
112                 }
113                 if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
114                         return -EINVAL;
115                 if (ctrl->value > 12 || ctrl->value < -96)
116                         return -EINVAL;
117                 cs53l32a_write(client, 0x04, (u8) ctrl->value);
118                 cs53l32a_write(client, 0x05, (u8) ctrl->value);
119                 break;
120
121         case VIDIOC_LOG_STATUS:
122                 {
123                         u8 v = cs53l32a_read(client, 0x01);
124                         u8 m = cs53l32a_read(client, 0x03);
125                         s8 vol = cs53l32a_read(client, 0x04);
126
127                         cs53l32a_info("Input:  %d%s\n", (v >> 4) & 3,
128                                       (m & 0xC0) ? " (muted)" : "");
129                         cs53l32a_info("Volume: %d dB\n", vol);
130                         break;
131                 }
132
133         default:
134                 return -EINVAL;
135         }
136         return 0;
137 }
138
139 /* ----------------------------------------------------------------------- */
140
141 /* i2c implementation */
142
143 /*
144  * Generic i2c probe
145  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
146  */
147
148 static struct i2c_driver i2c_driver;
149
150 static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
151 {
152         struct i2c_client *client;
153         int i;
154
155         /* Check if the adapter supports the needed features */
156         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
157                 return 0;
158
159         client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
160         if (client == 0)
161                 return -ENOMEM;
162
163         memset(client, 0, sizeof(struct i2c_client));
164         client->addr = address;
165         client->adapter = adapter;
166         client->driver = &i2c_driver;
167         snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
168
169         cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
170
171         for (i = 1; i <= 7; i++) {
172                 u8 v = cs53l32a_read(client, i);
173
174                 cs53l32a_dbg("Read Reg %d %02x\n", i, v);
175         }
176
177         /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
178
179         cs53l32a_write(client, 0x01, (u8) 0x21);
180         cs53l32a_write(client, 0x02, (u8) 0x29);
181         cs53l32a_write(client, 0x03, (u8) 0x30);
182         cs53l32a_write(client, 0x04, (u8) 0x00);
183         cs53l32a_write(client, 0x05, (u8) 0x00);
184         cs53l32a_write(client, 0x06, (u8) 0x00);
185         cs53l32a_write(client, 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(client, i);
191
192                 cs53l32a_dbg("Read Reg %d %02x\n", i, v);
193         }
194
195         i2c_attach_client(client);
196
197         return 0;
198 }
199
200 static int cs53l32a_probe(struct i2c_adapter *adapter)
201 {
202         if (adapter->class & I2C_CLASS_TV_ANALOG)
203                 return i2c_probe(adapter, &addr_data, cs53l32a_attach);
204         return 0;
205 }
206
207 static int cs53l32a_detach(struct i2c_client *client)
208 {
209         int err;
210
211         err = i2c_detach_client(client);
212         if (err) {
213                 return err;
214         }
215         kfree(client);
216
217         return 0;
218 }
219
220 /* ----------------------------------------------------------------------- */
221
222 /* i2c implementation */
223 static struct i2c_driver i2c_driver = {
224         .driver = {
225                 .name = "cs53l32a",
226         },
227         .id = I2C_DRIVERID_CS53L32A,
228         .attach_adapter = cs53l32a_probe,
229         .detach_client = cs53l32a_detach,
230         .command = cs53l32a_command,
231 };
232
233
234 static int __init cs53l32a_init_module(void)
235 {
236         return i2c_add_driver(&i2c_driver);
237 }
238
239 static void __exit cs53l32a_cleanup_module(void)
240 {
241         i2c_del_driver(&i2c_driver);
242 }
243
244 module_init(cs53l32a_init_module);
245 module_exit(cs53l32a_cleanup_module);