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