0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <linux/module.h>
0027 #include <linux/init.h>
0028 #include <linux/kernel.h>
0029 #include <linux/string.h>
0030 #include <linux/timer.h>
0031 #include <linux/delay.h>
0032 #include <linux/errno.h>
0033 #include <linux/slab.h>
0034 #include <linux/videodev2.h>
0035 #include <linux/i2c.h>
0036
0037 #include <media/v4l2-device.h>
0038 #include <media/v4l2-ioctl.h>
0039 #include <media/v4l2-ctrls.h>
0040
0041 #ifndef VIDEO_AUDIO_BALANCE
0042 # define VIDEO_AUDIO_BALANCE 32
0043 #endif
0044
0045 MODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>");
0046 MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip");
0047 MODULE_LICENSE("GPL");
0048
0049 static int maxvol;
0050 static int loudness;
0051 static int debug;
0052 module_param(debug, int, S_IRUGO | S_IWUSR);
0053 MODULE_PARM_DESC(debug, "Set debugging level from 0 to 3. Default is off(0).");
0054 module_param(loudness, int, S_IRUGO);
0055 MODULE_PARM_DESC(loudness, "Turn loudness on(1) else off(0). Default is off(0).");
0056 module_param(maxvol, int, S_IRUGO | S_IWUSR);
0057 MODULE_PARM_DESC(maxvol, "Set maximum volume to +20dB(0) else +0dB(1). Default is +20dB(0).");
0058
0059
0060
0061
0062 struct tda7432 {
0063 struct v4l2_subdev sd;
0064 struct v4l2_ctrl_handler hdl;
0065 struct {
0066
0067 struct v4l2_ctrl *bass;
0068 struct v4l2_ctrl *treble;
0069 };
0070 struct {
0071
0072 struct v4l2_ctrl *mute;
0073 struct v4l2_ctrl *balance;
0074 };
0075 };
0076
0077 static inline struct tda7432 *to_state(struct v4l2_subdev *sd)
0078 {
0079 return container_of(sd, struct tda7432, sd);
0080 }
0081
0082 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
0083 {
0084 return &container_of(ctrl->handler, struct tda7432, hdl)->sd;
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 #define TDA7432_IN 0x00
0103 #define TDA7432_VL 0x01
0104 #define TDA7432_TN 0x02
0105 #define TDA7432_LF 0x03
0106 #define TDA7432_LR 0x04
0107 #define TDA7432_RF 0x05
0108 #define TDA7432_RR 0x06
0109 #define TDA7432_LD 0x07
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 #define TDA7432_STEREO_IN 0
0132 #define TDA7432_MONO_IN 2
0133 #define TDA7432_BASS_SYM 1 << 3
0134 #define TDA7432_BASS_NORM 1 << 4
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 #define TDA7432_VOL_0DB 0x20
0150 #define TDA7432_LD_ON 1 << 7
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 #define TDA7432_TREBLE_0DB 0xf
0175 #define TDA7432_TREBLE 7
0176 #define TDA7432_TREBLE_GAIN 1 << 3
0177 #define TDA7432_BASS_0DB 0xf
0178 #define TDA7432_BASS 7 << 4
0179 #define TDA7432_BASS_GAIN 1 << 7
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 #define TDA7432_ATTEN_0DB 0x00
0199 #define TDA7432_MUTE 0x1 << 5
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val)
0221 {
0222 struct i2c_client *client = v4l2_get_subdevdata(sd);
0223 unsigned char buffer[2];
0224
0225 v4l2_dbg(2, debug, sd, "In tda7432_write\n");
0226 v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val);
0227 buffer[0] = subaddr;
0228 buffer[1] = val;
0229 if (2 != i2c_master_send(client, buffer, 2)) {
0230 v4l2_err(sd, "I/O error, trying (write %d 0x%x)\n",
0231 subaddr, val);
0232 return -1;
0233 }
0234 return 0;
0235 }
0236
0237 static int tda7432_set(struct v4l2_subdev *sd)
0238 {
0239 struct i2c_client *client = v4l2_get_subdevdata(sd);
0240 unsigned char buf[16];
0241
0242 buf[0] = TDA7432_IN;
0243 buf[1] = TDA7432_STEREO_IN |
0244 TDA7432_BASS_SYM |
0245 TDA7432_BASS_NORM;
0246 buf[2] = 0x3b;
0247 if (loudness)
0248 buf[2] |= TDA7432_LD_ON;
0249 buf[3] = TDA7432_TREBLE_0DB | (TDA7432_BASS_0DB << 4);
0250 buf[4] = TDA7432_ATTEN_0DB;
0251 buf[5] = TDA7432_ATTEN_0DB;
0252 buf[6] = TDA7432_ATTEN_0DB;
0253 buf[7] = TDA7432_ATTEN_0DB;
0254 buf[8] = loudness;
0255 if (9 != i2c_master_send(client, buf, 9)) {
0256 v4l2_err(sd, "I/O error, trying tda7432_set\n");
0257 return -1;
0258 }
0259
0260 return 0;
0261 }
0262
0263 static int tda7432_log_status(struct v4l2_subdev *sd)
0264 {
0265 struct tda7432 *state = to_state(sd);
0266
0267 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
0268 return 0;
0269 }
0270
0271 static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl)
0272 {
0273 struct v4l2_subdev *sd = to_sd(ctrl);
0274 struct tda7432 *t = to_state(sd);
0275 u8 bass, treble, volume;
0276 u8 lf, lr, rf, rr;
0277
0278 switch (ctrl->id) {
0279 case V4L2_CID_AUDIO_MUTE:
0280 if (t->balance->val < 0) {
0281
0282 rr = rf = -t->balance->val;
0283 lr = lf = TDA7432_ATTEN_0DB;
0284 } else if (t->balance->val > 0) {
0285
0286 rr = rf = TDA7432_ATTEN_0DB;
0287 lr = lf = t->balance->val;
0288 } else {
0289
0290 rr = rf = TDA7432_ATTEN_0DB;
0291 lr = lf = TDA7432_ATTEN_0DB;
0292 }
0293 if (t->mute->val) {
0294 lf |= TDA7432_MUTE;
0295 lr |= TDA7432_MUTE;
0296 rf |= TDA7432_MUTE;
0297 rr |= TDA7432_MUTE;
0298 }
0299
0300 tda7432_write(sd, TDA7432_LF, lf);
0301 tda7432_write(sd, TDA7432_LR, lr);
0302 tda7432_write(sd, TDA7432_RF, rf);
0303 tda7432_write(sd, TDA7432_RR, rr);
0304 return 0;
0305 case V4L2_CID_AUDIO_VOLUME:
0306 volume = 0x6f - ctrl->val;
0307 if (loudness)
0308 volume |= TDA7432_LD_ON;
0309
0310 tda7432_write(sd, TDA7432_VL, volume);
0311 return 0;
0312 case V4L2_CID_AUDIO_BASS:
0313 bass = t->bass->val;
0314 treble = t->treble->val;
0315 if (bass >= 0x8)
0316 bass = 14 - (bass - 8);
0317 if (treble >= 0x8)
0318 treble = 14 - (treble - 8);
0319
0320 tda7432_write(sd, TDA7432_TN, 0x10 | (bass << 4) | treble);
0321 return 0;
0322 }
0323 return -EINVAL;
0324 }
0325
0326
0327
0328 static const struct v4l2_ctrl_ops tda7432_ctrl_ops = {
0329 .s_ctrl = tda7432_s_ctrl,
0330 };
0331
0332 static const struct v4l2_subdev_core_ops tda7432_core_ops = {
0333 .log_status = tda7432_log_status,
0334 };
0335
0336 static const struct v4l2_subdev_ops tda7432_ops = {
0337 .core = &tda7432_core_ops,
0338 };
0339
0340
0341
0342
0343
0344
0345
0346 static int tda7432_probe(struct i2c_client *client,
0347 const struct i2c_device_id *id)
0348 {
0349 struct tda7432 *t;
0350 struct v4l2_subdev *sd;
0351
0352 v4l_info(client, "chip found @ 0x%02x (%s)\n",
0353 client->addr << 1, client->adapter->name);
0354
0355 t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL);
0356 if (!t)
0357 return -ENOMEM;
0358 sd = &t->sd;
0359 v4l2_i2c_subdev_init(sd, client, &tda7432_ops);
0360 v4l2_ctrl_handler_init(&t->hdl, 5);
0361 v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
0362 V4L2_CID_AUDIO_VOLUME, 0, maxvol ? 0x68 : 0x4f, 1, maxvol ? 0x5d : 0x47);
0363 t->mute = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
0364 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
0365 t->balance = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
0366 V4L2_CID_AUDIO_BALANCE, -31, 31, 1, 0);
0367 t->bass = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
0368 V4L2_CID_AUDIO_BASS, 0, 14, 1, 7);
0369 t->treble = v4l2_ctrl_new_std(&t->hdl, &tda7432_ctrl_ops,
0370 V4L2_CID_AUDIO_TREBLE, 0, 14, 1, 7);
0371 sd->ctrl_handler = &t->hdl;
0372 if (t->hdl.error) {
0373 int err = t->hdl.error;
0374
0375 v4l2_ctrl_handler_free(&t->hdl);
0376 return err;
0377 }
0378 v4l2_ctrl_cluster(2, &t->bass);
0379 v4l2_ctrl_cluster(2, &t->mute);
0380 v4l2_ctrl_handler_setup(&t->hdl);
0381 if (loudness < 0 || loudness > 15) {
0382 v4l2_warn(sd, "loudness parameter must be between 0 and 15\n");
0383 if (loudness < 0)
0384 loudness = 0;
0385 if (loudness > 15)
0386 loudness = 15;
0387 }
0388
0389 tda7432_set(sd);
0390 return 0;
0391 }
0392
0393 static int tda7432_remove(struct i2c_client *client)
0394 {
0395 struct v4l2_subdev *sd = i2c_get_clientdata(client);
0396 struct tda7432 *t = to_state(sd);
0397
0398 tda7432_set(sd);
0399 v4l2_device_unregister_subdev(sd);
0400 v4l2_ctrl_handler_free(&t->hdl);
0401 return 0;
0402 }
0403
0404 static const struct i2c_device_id tda7432_id[] = {
0405 { "tda7432", 0 },
0406 { }
0407 };
0408 MODULE_DEVICE_TABLE(i2c, tda7432_id);
0409
0410 static struct i2c_driver tda7432_driver = {
0411 .driver = {
0412 .name = "tda7432",
0413 },
0414 .probe = tda7432_probe,
0415 .remove = tda7432_remove,
0416 .id_table = tda7432_id,
0417 };
0418
0419 module_i2c_driver(tda7432_driver);