Blame view
drivers/media/video/cs53l32a.c
6.76 KB
f4067fd46 [PATCH] v4l: 816:... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver. * Copyright (C) 2005 Martin Vaughan * * Audio source switching for Adaptec AVC-2410 added by Trev Jackson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/module.h> #include <linux/types.h> |
5a0e3ad6a include cleanup: ... |
25 |
#include <linux/slab.h> |
f4067fd46 [PATCH] v4l: 816:... |
26 27 28 |
#include <linux/ioctl.h> #include <asm/uaccess.h> #include <linux/i2c.h> |
33b687cf1 V4L/DVB (8487): v... |
29 |
#include <linux/videodev2.h> |
825c6aa2a V4L/DVB (9822): c... |
30 |
#include <media/v4l2-device.h> |
74cab31c4 V4L/DVB (5355): A... |
31 |
#include <media/v4l2-chip-ident.h> |
251190cff V4L/DVB: cs53l32a... |
32 |
#include <media/v4l2-ctrls.h> |
f4067fd46 [PATCH] v4l: 816:... |
33 34 35 36 |
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); MODULE_AUTHOR("Martin Vaughan"); MODULE_LICENSE("GPL"); |
90ab5ee94 module_param: mak... |
37 |
static bool debug; |
f4067fd46 [PATCH] v4l: 816:... |
38 39 |
module_param(debug, bool, 0644); |
61a2d07d3 Remove newline fr... |
40 |
MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); |
f4067fd46 [PATCH] v4l: 816:... |
41 |
|
f4067fd46 [PATCH] v4l: 816:... |
42 |
|
251190cff V4L/DVB: cs53l32a... |
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
struct cs53l32a_state { struct v4l2_subdev sd; struct v4l2_ctrl_handler hdl; }; static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd) { return container_of(sd, struct cs53l32a_state, sd); } static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) { return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd; } |
f4067fd46 [PATCH] v4l: 816:... |
57 |
/* ----------------------------------------------------------------------- */ |
825c6aa2a V4L/DVB (9822): c... |
58 |
static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value) |
f4067fd46 [PATCH] v4l: 816:... |
59 |
{ |
825c6aa2a V4L/DVB (9822): c... |
60 |
struct i2c_client *client = v4l2_get_subdevdata(sd); |
f4067fd46 [PATCH] v4l: 816:... |
61 62 |
return i2c_smbus_write_byte_data(client, reg, value); } |
825c6aa2a V4L/DVB (9822): c... |
63 |
static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg) |
f4067fd46 [PATCH] v4l: 816:... |
64 |
{ |
825c6aa2a V4L/DVB (9822): c... |
65 |
struct i2c_client *client = v4l2_get_subdevdata(sd); |
f4067fd46 [PATCH] v4l: 816:... |
66 67 |
return i2c_smbus_read_byte_data(client, reg); } |
5325b4272 V4L/DVB (11380): ... |
68 69 |
static int cs53l32a_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) |
f4067fd46 [PATCH] v4l: 816:... |
70 |
{ |
825c6aa2a V4L/DVB (9822): c... |
71 72 73 74 |
/* There are 2 physical inputs, but the second input can be placed in two modes, the first mode bypasses the PGA (gain), the second goes through the PGA. Hence there are three possible inputs to choose from. */ |
5325b4272 V4L/DVB (11380): ... |
75 76 77 |
if (input > 2) { v4l2_err(sd, "Invalid input %d. ", input); |
f4067fd46 [PATCH] v4l: 816:... |
78 79 |
return -EINVAL; } |
5325b4272 V4L/DVB (11380): ... |
80 |
cs53l32a_write(sd, 0x01, 0x01 + (input << 4)); |
825c6aa2a V4L/DVB (9822): c... |
81 82 |
return 0; } |
251190cff V4L/DVB: cs53l32a... |
83 |
static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl) |
825c6aa2a V4L/DVB (9822): c... |
84 |
{ |
251190cff V4L/DVB: cs53l32a... |
85 |
struct v4l2_subdev *sd = to_sd(ctrl); |
825c6aa2a V4L/DVB (9822): c... |
86 |
|
251190cff V4L/DVB: cs53l32a... |
87 88 89 90 91 92 93 |
switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30); return 0; case V4L2_CID_AUDIO_VOLUME: cs53l32a_write(sd, 0x04, (u8)ctrl->val); cs53l32a_write(sd, 0x05, (u8)ctrl->val); |
825c6aa2a V4L/DVB (9822): c... |
94 95 |
return 0; } |
251190cff V4L/DVB: cs53l32a... |
96 |
return -EINVAL; |
f4067fd46 [PATCH] v4l: 816:... |
97 |
} |
aecde8b53 V4L/DVB (10141): ... |
98 |
static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) |
825c6aa2a V4L/DVB (9822): c... |
99 100 101 102 103 104 105 106 107 |
{ struct i2c_client *client = v4l2_get_subdevdata(sd); return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_CS53l32A, 0); } static int cs53l32a_log_status(struct v4l2_subdev *sd) { |
251190cff V4L/DVB: cs53l32a... |
108 |
struct cs53l32a_state *state = to_state(sd); |
825c6aa2a V4L/DVB (9822): c... |
109 |
u8 v = cs53l32a_read(sd, 0x01); |
825c6aa2a V4L/DVB (9822): c... |
110 |
|
251190cff V4L/DVB: cs53l32a... |
111 112 113 |
v4l2_info(sd, "Input: %d ", (v >> 4) & 3); v4l2_ctrl_handler_log_status(&state->hdl, sd->name); |
825c6aa2a V4L/DVB (9822): c... |
114 115 |
return 0; } |
825c6aa2a V4L/DVB (9822): c... |
116 |
/* ----------------------------------------------------------------------- */ |
251190cff V4L/DVB: cs53l32a... |
117 118 119 |
static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = { .s_ctrl = cs53l32a_s_ctrl, }; |
825c6aa2a V4L/DVB (9822): c... |
120 121 122 |
static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { .log_status = cs53l32a_log_status, .g_chip_ident = cs53l32a_g_chip_ident, |
251190cff V4L/DVB: cs53l32a... |
123 124 125 126 127 128 129 |
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, .g_ctrl = v4l2_subdev_g_ctrl, .s_ctrl = v4l2_subdev_s_ctrl, .queryctrl = v4l2_subdev_queryctrl, .querymenu = v4l2_subdev_querymenu, |
825c6aa2a V4L/DVB (9822): c... |
130 131 132 133 134 135 136 137 138 139 |
}; static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = { .s_routing = cs53l32a_s_routing, }; static const struct v4l2_subdev_ops cs53l32a_ops = { .core = &cs53l32a_core_ops, .audio = &cs53l32a_audio_ops, }; |
f4067fd46 [PATCH] v4l: 816:... |
140 141 142 143 144 145 146 147 |
/* ----------------------------------------------------------------------- */ /* i2c implementation */ /* * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ |
d2653e927 i2c: Add support ... |
148 149 |
static int cs53l32a_probe(struct i2c_client *client, const struct i2c_device_id *id) |
f4067fd46 [PATCH] v4l: 816:... |
150 |
{ |
251190cff V4L/DVB: cs53l32a... |
151 |
struct cs53l32a_state *state; |
825c6aa2a V4L/DVB (9822): c... |
152 |
struct v4l2_subdev *sd; |
f4067fd46 [PATCH] v4l: 816:... |
153 154 155 |
int i; /* Check if the adapter supports the needed features */ |
e8e6b9918 V4L/DVB (6458): c... |
156 |
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
188f3457c V4L/DVB (6465): U... |
157 |
return -EIO; |
f4067fd46 [PATCH] v4l: 816:... |
158 |
|
af294867a i2c: Convert rema... |
159 160 |
if (!id) strlcpy(client->name, "cs53l32a", sizeof(client->name)); |
f4067fd46 [PATCH] v4l: 816:... |
161 |
|
4c05de9c9 V4L/DVB (6739): c... |
162 163 164 |
v4l_info(client, "chip found @ 0x%x (%s) ", client->addr << 1, client->adapter->name); |
f4067fd46 [PATCH] v4l: 816:... |
165 |
|
251190cff V4L/DVB: cs53l32a... |
166 167 |
state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL); if (state == NULL) |
825c6aa2a V4L/DVB (9822): c... |
168 |
return -ENOMEM; |
251190cff V4L/DVB: cs53l32a... |
169 |
sd = &state->sd; |
825c6aa2a V4L/DVB (9822): c... |
170 |
v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops); |
f4067fd46 [PATCH] v4l: 816:... |
171 |
for (i = 1; i <= 7; i++) { |
825c6aa2a V4L/DVB (9822): c... |
172 |
u8 v = cs53l32a_read(sd, i); |
f4067fd46 [PATCH] v4l: 816:... |
173 |
|
825c6aa2a V4L/DVB (9822): c... |
174 175 |
v4l2_dbg(1, debug, sd, "Read Reg %d %02x ", i, v); |
f4067fd46 [PATCH] v4l: 816:... |
176 |
} |
251190cff V4L/DVB: cs53l32a... |
177 178 179 180 181 182 183 184 185 186 187 188 189 |
v4l2_ctrl_handler_init(&state->hdl, 2); v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops, V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0); v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); sd->ctrl_handler = &state->hdl; if (state->hdl.error) { int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); kfree(state); return err; } |
f4067fd46 [PATCH] v4l: 816:... |
190 |
/* Set cs53l32a internal register for Adaptec 2010/2410 setup */ |
251190cff V4L/DVB: cs53l32a... |
191 192 193 194 195 196 197 |
cs53l32a_write(sd, 0x01, 0x21); cs53l32a_write(sd, 0x02, 0x29); cs53l32a_write(sd, 0x03, 0x30); cs53l32a_write(sd, 0x04, 0x00); cs53l32a_write(sd, 0x05, 0x00); cs53l32a_write(sd, 0x06, 0x00); cs53l32a_write(sd, 0x07, 0x00); |
f4067fd46 [PATCH] v4l: 816:... |
198 199 200 201 |
/* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */ for (i = 1; i <= 7; i++) { |
825c6aa2a V4L/DVB (9822): c... |
202 |
u8 v = cs53l32a_read(sd, i); |
f4067fd46 [PATCH] v4l: 816:... |
203 |
|
825c6aa2a V4L/DVB (9822): c... |
204 205 |
v4l2_dbg(1, debug, sd, "Read Reg %d %02x ", i, v); |
f4067fd46 [PATCH] v4l: 816:... |
206 |
} |
f4067fd46 [PATCH] v4l: 816:... |
207 208 |
return 0; } |
825c6aa2a V4L/DVB (9822): c... |
209 210 211 |
static int cs53l32a_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); |
251190cff V4L/DVB: cs53l32a... |
212 |
struct cs53l32a_state *state = to_state(sd); |
825c6aa2a V4L/DVB (9822): c... |
213 214 |
v4l2_device_unregister_subdev(sd); |
251190cff V4L/DVB: cs53l32a... |
215 216 |
v4l2_ctrl_handler_free(&state->hdl); kfree(state); |
825c6aa2a V4L/DVB (9822): c... |
217 218 |
return 0; } |
af294867a i2c: Convert rema... |
219 220 221 222 223 |
static const struct i2c_device_id cs53l32a_id[] = { { "cs53l32a", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, cs53l32a_id); |
50337acef V4L/DVB: cs53l32a... |
224 225 226 227 228 229 230 231 |
static struct i2c_driver cs53l32a_driver = { .driver = { .owner = THIS_MODULE, .name = "cs53l32a", }, .probe = cs53l32a_probe, .remove = cs53l32a_remove, .id_table = cs53l32a_id, |
f4067fd46 [PATCH] v4l: 816:... |
232 |
}; |
50337acef V4L/DVB: cs53l32a... |
233 234 235 236 237 238 239 240 241 242 243 244 245 |
static __init int init_cs53l32a(void) { return i2c_add_driver(&cs53l32a_driver); } static __exit void exit_cs53l32a(void) { i2c_del_driver(&cs53l32a_driver); } module_init(init_cs53l32a); module_exit(exit_cs53l32a); |