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