Merge tag 'pci-v4.8-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[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,
825c6aa2
HV
124};
125
126static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
127 .s_routing = cs53l32a_s_routing,
128};
129
130static const struct v4l2_subdev_ops cs53l32a_ops = {
131 .core = &cs53l32a_core_ops,
132 .audio = &cs53l32a_audio_ops,
133};
134
f4067fd4
HV
135/* ----------------------------------------------------------------------- */
136
137/* i2c implementation */
138
139/*
140 * Generic i2c probe
141 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
142 */
143
d2653e92
JD
144static int cs53l32a_probe(struct i2c_client *client,
145 const struct i2c_device_id *id)
f4067fd4 146{
251190cf 147 struct cs53l32a_state *state;
825c6aa2 148 struct v4l2_subdev *sd;
f4067fd4
HV
149 int i;
150
151 /* Check if the adapter supports the needed features */
e8e6b991 152 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
188f3457 153 return -EIO;
f4067fd4 154
af294867
JD
155 if (!id)
156 strlcpy(client->name, "cs53l32a", sizeof(client->name));
f4067fd4 157
4c05de9c
HV
158 v4l_info(client, "chip found @ 0x%x (%s)\n",
159 client->addr << 1, client->adapter->name);
f4067fd4 160
c02b211d 161 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
251190cf 162 if (state == NULL)
825c6aa2 163 return -ENOMEM;
251190cf 164 sd = &state->sd;
825c6aa2
HV
165 v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
166
f4067fd4 167 for (i = 1; i <= 7; i++) {
825c6aa2 168 u8 v = cs53l32a_read(sd, i);
f4067fd4 169
825c6aa2 170 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
f4067fd4
HV
171 }
172
251190cf
HV
173 v4l2_ctrl_handler_init(&state->hdl, 2);
174 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
175 V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
176 v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
177 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
178 sd->ctrl_handler = &state->hdl;
179 if (state->hdl.error) {
180 int err = state->hdl.error;
181
182 v4l2_ctrl_handler_free(&state->hdl);
251190cf
HV
183 return err;
184 }
185
f4067fd4
HV
186 /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
187
251190cf
HV
188 cs53l32a_write(sd, 0x01, 0x21);
189 cs53l32a_write(sd, 0x02, 0x29);
190 cs53l32a_write(sd, 0x03, 0x30);
191 cs53l32a_write(sd, 0x04, 0x00);
192 cs53l32a_write(sd, 0x05, 0x00);
193 cs53l32a_write(sd, 0x06, 0x00);
194 cs53l32a_write(sd, 0x07, 0x00);
f4067fd4
HV
195
196 /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
197
198 for (i = 1; i <= 7; i++) {
825c6aa2 199 u8 v = cs53l32a_read(sd, i);
f4067fd4 200
825c6aa2 201 v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
f4067fd4 202 }
f4067fd4
HV
203 return 0;
204}
205
825c6aa2
HV
206static int cs53l32a_remove(struct i2c_client *client)
207{
208 struct v4l2_subdev *sd = i2c_get_clientdata(client);
251190cf 209 struct cs53l32a_state *state = to_state(sd);
825c6aa2
HV
210
211 v4l2_device_unregister_subdev(sd);
251190cf 212 v4l2_ctrl_handler_free(&state->hdl);
825c6aa2
HV
213 return 0;
214}
215
af294867
JD
216static const struct i2c_device_id cs53l32a_id[] = {
217 { "cs53l32a", 0 },
218 { }
219};
220MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
221
50337ace
HV
222static struct i2c_driver cs53l32a_driver = {
223 .driver = {
50337ace
HV
224 .name = "cs53l32a",
225 },
226 .probe = cs53l32a_probe,
227 .remove = cs53l32a_remove,
228 .id_table = cs53l32a_id,
f4067fd4 229};
50337ace 230
c6e8d86f 231module_i2c_driver(cs53l32a_driver);
This page took 0.900015 seconds and 5 git commands to generate.