Blame view

drivers/media/video/cs53l32a.c 6.76 KB
f4067fd46   Hans Verkuil   [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   Tejun Heo   include cleanup: ...
25
  #include <linux/slab.h>
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
26
27
28
  #include <linux/ioctl.h>
  #include <asm/uaccess.h>
  #include <linux/i2c.h>
33b687cf1   Hans Verkuil   V4L/DVB (8487): v...
29
  #include <linux/videodev2.h>
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
30
  #include <media/v4l2-device.h>
74cab31c4   Hans Verkuil   V4L/DVB (5355): A...
31
  #include <media/v4l2-chip-ident.h>
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
32
  #include <media/v4l2-ctrls.h>
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
33
34
35
36
  
  MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
  MODULE_AUTHOR("Martin Vaughan");
  MODULE_LICENSE("GPL");
90ab5ee94   Rusty Russell   module_param: mak...
37
  static bool debug;
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
38
39
  
  module_param(debug, bool, 0644);
61a2d07d3   Niels de Vos   Remove newline fr...
40
  MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
41

f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
42

251190cff   Hans Verkuil   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   Hans Verkuil   [PATCH] v4l: 816:...
57
  /* ----------------------------------------------------------------------- */
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
58
  static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
59
  {
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
60
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
61
62
  	return i2c_smbus_write_byte_data(client, reg, value);
  }
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
63
  static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg)
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
64
  {
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
65
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
66
67
  	return i2c_smbus_read_byte_data(client, reg);
  }
5325b4272   Hans Verkuil   V4L/DVB (11380): ...
68
69
  static int cs53l32a_s_routing(struct v4l2_subdev *sd,
  			      u32 input, u32 output, u32 config)
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
70
  {
825c6aa2a   Hans Verkuil   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   Hans Verkuil   V4L/DVB (11380): ...
75
76
77
  	if (input > 2) {
  		v4l2_err(sd, "Invalid input %d.
  ", input);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
78
79
  		return -EINVAL;
  	}
5325b4272   Hans Verkuil   V4L/DVB (11380): ...
80
  	cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
81
82
  	return 0;
  }
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
83
  static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
84
  {
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
85
  	struct v4l2_subdev *sd = to_sd(ctrl);
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
86

251190cff   Hans Verkuil   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   Hans Verkuil   V4L/DVB (9822): c...
94
95
  		return 0;
  	}
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
96
  	return -EINVAL;
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
97
  }
aecde8b53   Hans Verkuil   V4L/DVB (10141): ...
98
  static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
825c6aa2a   Hans Verkuil   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   Hans Verkuil   V4L/DVB: cs53l32a...
108
  	struct cs53l32a_state *state = to_state(sd);
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
109
  	u8 v = cs53l32a_read(sd, 0x01);
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
110

251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
111
112
113
  	v4l2_info(sd, "Input:  %d
  ", (v >> 4) & 3);
  	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
114
115
  	return 0;
  }
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
116
  /* ----------------------------------------------------------------------- */
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
117
118
119
  static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
  	.s_ctrl = cs53l32a_s_ctrl,
  };
825c6aa2a   Hans Verkuil   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   Hans Verkuil   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   Hans Verkuil   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   Hans Verkuil   [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   Jean Delvare   i2c: Add support ...
148
149
  static int cs53l32a_probe(struct i2c_client *client,
  			  const struct i2c_device_id *id)
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
150
  {
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
151
  	struct cs53l32a_state *state;
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
152
  	struct v4l2_subdev *sd;
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
153
154
155
  	int i;
  
  	/* Check if the adapter supports the needed features */
e8e6b9918   Hans Verkuil   V4L/DVB (6458): c...
156
  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
188f3457c   Hans Verkuil   V4L/DVB (6465): U...
157
  		return -EIO;
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
158

af294867a   Jean Delvare   i2c: Convert rema...
159
160
  	if (!id)
  		strlcpy(client->name, "cs53l32a", sizeof(client->name));
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
161

4c05de9c9   Hans Verkuil   V4L/DVB (6739): c...
162
163
164
  	v4l_info(client, "chip found @ 0x%x (%s)
  ",
  			client->addr << 1, client->adapter->name);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
165

251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
166
167
  	state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL);
  	if (state == NULL)
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
168
  		return -ENOMEM;
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
169
  	sd = &state->sd;
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
170
  	v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
171
  	for (i = 1; i <= 7; i++) {
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
172
  		u8 v = cs53l32a_read(sd, i);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
173

825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
174
175
  		v4l2_dbg(1, debug, sd, "Read Reg %d %02x
  ", i, v);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
176
  	}
251190cff   Hans Verkuil   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   Hans Verkuil   [PATCH] v4l: 816:...
190
  	/* Set cs53l32a internal register for Adaptec 2010/2410 setup */
251190cff   Hans Verkuil   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   Hans Verkuil   [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   Hans Verkuil   V4L/DVB (9822): c...
202
  		u8 v = cs53l32a_read(sd, i);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
203

825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
204
205
  		v4l2_dbg(1, debug, sd, "Read Reg %d %02x
  ", i, v);
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
206
  	}
f4067fd46   Hans Verkuil   [PATCH] v4l: 816:...
207
208
  	return 0;
  }
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
209
210
211
  static int cs53l32a_remove(struct i2c_client *client)
  {
  	struct v4l2_subdev *sd = i2c_get_clientdata(client);
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
212
  	struct cs53l32a_state *state = to_state(sd);
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
213
214
  
  	v4l2_device_unregister_subdev(sd);
251190cff   Hans Verkuil   V4L/DVB: cs53l32a...
215
216
  	v4l2_ctrl_handler_free(&state->hdl);
  	kfree(state);
825c6aa2a   Hans Verkuil   V4L/DVB (9822): c...
217
218
  	return 0;
  }
af294867a   Jean Delvare   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   Hans Verkuil   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   Hans Verkuil   [PATCH] v4l: 816:...
232
  };
50337acef   Hans Verkuil   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);