Merge branch 'perf/rbtree_copy' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / drivers / media / i2c / 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>
33b687cf 29#include <linux/videodev2.h>
825c6aa2 30#include <media/v4l2-device.h>
251190cf 31#include <media/v4l2-ctrls.h>
f4067fd4
HV
32
33MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
34MODULE_AUTHOR("Martin Vaughan");
35MODULE_LICENSE("GPL");
36
90ab5ee9 37static bool debug;
f4067fd4
HV
38
39module_param(debug, bool, 0644);
40
61a2d07d 41MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
f4067fd4 42
f4067fd4 43
251190cf
HV
44struct cs53l32a_state {
45 struct v4l2_subdev sd;
46 struct v4l2_ctrl_handler hdl;
47};
48
49static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
50{
51 return container_of(sd, struct cs53l32a_state, sd);
52}
53
54static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
55{
56 return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
57}
58
f4067fd4
HV
59/* ----------------------------------------------------------------------- */
60
825c6aa2 61static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
f4067fd4 62{
825c6aa2
HV
63 struct i2c_client *client = v4l2_get_subdevdata(sd);
64
f4067fd4
HV
65 return i2c_smbus_write_byte_data(client, reg, value);
66}
67
825c6aa2 68static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg)
f4067fd4 69{
825c6aa2
HV
70 struct i2c_client *client = v4l2_get_subdevdata(sd);
71
f4067fd4
HV
72 return i2c_smbus_read_byte_data(client, reg);
73}
74
5325b427
HV
75static int cs53l32a_s_routing(struct v4l2_subdev *sd,
76 u32 input, u32 output, u32 config)
f4067fd4 77{
825c6aa2
HV
78 /* There are 2 physical inputs, but the second input can be
79 placed in two modes, the first mode bypasses the PGA (gain),
80 the second goes through the PGA. Hence there are three
81 possible inputs to choose from. */
5325b427
HV
82 if (input > 2) {
83 v4l2_err(sd, "Invalid input %d.\n", input);
f4067fd4
HV
84 return -EINVAL;
85 }
5325b427 86 cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
825c6aa2
HV
87 return 0;
88}
89
251190cf 90static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
825c6aa2 91{
251190cf 92 struct v4l2_subdev *sd = to_sd(ctrl);
825c6aa2 93
251190cf
HV
94 switch (ctrl->id) {
95 case V4L2_CID_AUDIO_MUTE:
96 cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
97 return 0;
98 case V4L2_CID_AUDIO_VOLUME:
99 cs53l32a_write(sd, 0x04, (u8)ctrl->val);
100 cs53l32a_write(sd, 0x05, (u8)ctrl->val);
825c6aa2
HV
101 return 0;
102 }
251190cf 103 return -EINVAL;
f4067fd4
HV
104}
105
825c6aa2
HV
106static int cs53l32a_log_status(struct v4l2_subdev *sd)
107{
251190cf 108 struct cs53l32a_state *state = to_state(sd);
825c6aa2 109 u8 v = cs53l32a_read(sd, 0x01);
825c6aa2 110
251190cf
HV
111 v4l2_info(sd, "Input: %d\n", (v >> 4) & 3);
112 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
825c6aa2
HV
113 return 0;
114}
115
825c6aa2
HV
116/* ----------------------------------------------------------------------- */
117
251190cf
HV
118static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
119 .s_ctrl = cs53l32a_s_ctrl,
120};
121
825c6aa2
HV
122static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
123 .log_status = cs53l32a_log_status,
251190cf
HV
124 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
125 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
126 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
127 .g_ctrl = v4l2_subdev_g_ctrl,
128 .s_ctrl = v4l2_subdev_s_ctrl,
129 .queryctrl = v4l2_subdev_queryctrl,
130 .querymenu = v4l2_subdev_querymenu,
825c6aa2
HV
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{
251190cf 154 struct cs53l32a_state *state;
825c6aa2 155 struct v4l2_subdev *sd;
f4067fd4
HV
156 int i;
157
158 /* Check if the adapter supports the needed features */
e8e6b991 159 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
188f3457 160 return -EIO;
f4067fd4 161
af294867
JD
162 if (!id)
163 strlcpy(client->name, "cs53l32a", sizeof(client->name));
f4067fd4 164
4c05de9c
HV
165 v4l_info(client, "chip found @ 0x%x (%s)\n",
166 client->addr << 1, client->adapter->name);
f4067fd4 167
c02b211d 168 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
251190cf 169 if (state == NULL)
825c6aa2 170 return -ENOMEM;
251190cf 171 sd = &state->sd;
825c6aa2
HV
172 v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
173
f4067fd4 174 for (i = 1; i <= 7; i++) {
825c6aa2 175 u8 v = cs53l32a_read(sd, i);
f4067fd4 176
825c6aa2 177 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
f4067fd4
HV
178 }
179
251190cf
HV
180 v4l2_ctrl_handler_init(&state->hdl, 2);
181 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
182 V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
183 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
184 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
185 sd->ctrl_handler = &state->hdl;
186 if (state->hdl.error) {
187 int err = state->hdl.error;
188
189 v4l2_ctrl_handler_free(&state->hdl);
251190cf
HV
190 return err;
191 }
192
f4067fd4
HV
193 /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
194
251190cf
HV
195 cs53l32a_write(sd, 0x01, 0x21);
196 cs53l32a_write(sd, 0x02, 0x29);
197 cs53l32a_write(sd, 0x03, 0x30);
198 cs53l32a_write(sd, 0x04, 0x00);
199 cs53l32a_write(sd, 0x05, 0x00);
200 cs53l32a_write(sd, 0x06, 0x00);
201 cs53l32a_write(sd, 0x07, 0x00);
f4067fd4
HV
202
203 /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
204
205 for (i = 1; i <= 7; i++) {
825c6aa2 206 u8 v = cs53l32a_read(sd, i);
f4067fd4 207
825c6aa2 208 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
f4067fd4 209 }
f4067fd4
HV
210 return 0;
211}
212
825c6aa2
HV
213static int cs53l32a_remove(struct i2c_client *client)
214{
215 struct v4l2_subdev *sd = i2c_get_clientdata(client);
251190cf 216 struct cs53l32a_state *state = to_state(sd);
825c6aa2
HV
217
218 v4l2_device_unregister_subdev(sd);
251190cf 219 v4l2_ctrl_handler_free(&state->hdl);
825c6aa2
HV
220 return 0;
221}
222
af294867
JD
223static const struct i2c_device_id cs53l32a_id[] = {
224 { "cs53l32a", 0 },
225 { }
226};
227MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
228
50337ace
HV
229static struct i2c_driver cs53l32a_driver = {
230 .driver = {
231 .owner = THIS_MODULE,
232 .name = "cs53l32a",
233 },
234 .probe = cs53l32a_probe,
235 .remove = cs53l32a_remove,
236 .id_table = cs53l32a_id,
f4067fd4 237};
50337ace 238
c6e8d86f 239module_i2c_driver(cs53l32a_driver);
This page took 0.963291 seconds and 5 git commands to generate.