Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver.
0004  * Copyright (C) 2005  Martin Vaughan
0005  *
0006  * Audio source switching for Adaptec AVC-2410 added by Trev Jackson
0007  */
0008 
0009 
0010 #include <linux/module.h>
0011 #include <linux/types.h>
0012 #include <linux/slab.h>
0013 #include <linux/ioctl.h>
0014 #include <linux/uaccess.h>
0015 #include <linux/i2c.h>
0016 #include <linux/videodev2.h>
0017 #include <media/v4l2-device.h>
0018 #include <media/v4l2-ctrls.h>
0019 
0020 MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
0021 MODULE_AUTHOR("Martin Vaughan");
0022 MODULE_LICENSE("GPL");
0023 
0024 static bool debug;
0025 
0026 module_param(debug, bool, 0644);
0027 
0028 MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
0029 
0030 
0031 struct cs53l32a_state {
0032     struct v4l2_subdev sd;
0033     struct v4l2_ctrl_handler hdl;
0034 };
0035 
0036 static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
0037 {
0038     return container_of(sd, struct cs53l32a_state, sd);
0039 }
0040 
0041 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
0042 {
0043     return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
0044 }
0045 
0046 /* ----------------------------------------------------------------------- */
0047 
0048 static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
0049 {
0050     struct i2c_client *client = v4l2_get_subdevdata(sd);
0051 
0052     return i2c_smbus_write_byte_data(client, reg, value);
0053 }
0054 
0055 static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg)
0056 {
0057     struct i2c_client *client = v4l2_get_subdevdata(sd);
0058 
0059     return i2c_smbus_read_byte_data(client, reg);
0060 }
0061 
0062 static int cs53l32a_s_routing(struct v4l2_subdev *sd,
0063                   u32 input, u32 output, u32 config)
0064 {
0065     /* There are 2 physical inputs, but the second input can be
0066        placed in two modes, the first mode bypasses the PGA (gain),
0067        the second goes through the PGA. Hence there are three
0068        possible inputs to choose from. */
0069     if (input > 2) {
0070         v4l2_err(sd, "Invalid input %d.\n", input);
0071         return -EINVAL;
0072     }
0073     cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
0074     return 0;
0075 }
0076 
0077 static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
0078 {
0079     struct v4l2_subdev *sd = to_sd(ctrl);
0080 
0081     switch (ctrl->id) {
0082     case V4L2_CID_AUDIO_MUTE:
0083         cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
0084         return 0;
0085     case V4L2_CID_AUDIO_VOLUME:
0086         cs53l32a_write(sd, 0x04, (u8)ctrl->val);
0087         cs53l32a_write(sd, 0x05, (u8)ctrl->val);
0088         return 0;
0089     }
0090     return -EINVAL;
0091 }
0092 
0093 static int cs53l32a_log_status(struct v4l2_subdev *sd)
0094 {
0095     struct cs53l32a_state *state = to_state(sd);
0096     u8 v = cs53l32a_read(sd, 0x01);
0097 
0098     v4l2_info(sd, "Input:  %d\n", (v >> 4) & 3);
0099     v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
0100     return 0;
0101 }
0102 
0103 /* ----------------------------------------------------------------------- */
0104 
0105 static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
0106     .s_ctrl = cs53l32a_s_ctrl,
0107 };
0108 
0109 static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
0110     .log_status = cs53l32a_log_status,
0111 };
0112 
0113 static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
0114     .s_routing = cs53l32a_s_routing,
0115 };
0116 
0117 static const struct v4l2_subdev_ops cs53l32a_ops = {
0118     .core = &cs53l32a_core_ops,
0119     .audio = &cs53l32a_audio_ops,
0120 };
0121 
0122 /* ----------------------------------------------------------------------- */
0123 
0124 /* i2c implementation */
0125 
0126 /*
0127  * Generic i2c probe
0128  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
0129  */
0130 
0131 static int cs53l32a_probe(struct i2c_client *client,
0132               const struct i2c_device_id *id)
0133 {
0134     struct cs53l32a_state *state;
0135     struct v4l2_subdev *sd;
0136     int i;
0137 
0138     /* Check if the adapter supports the needed features */
0139     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0140         return -EIO;
0141 
0142     if (!id)
0143         strscpy(client->name, "cs53l32a", sizeof(client->name));
0144 
0145     v4l_info(client, "chip found @ 0x%x (%s)\n",
0146             client->addr << 1, client->adapter->name);
0147 
0148     state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
0149     if (state == NULL)
0150         return -ENOMEM;
0151     sd = &state->sd;
0152     v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
0153 
0154     for (i = 1; i <= 7; i++) {
0155         u8 v = cs53l32a_read(sd, i);
0156 
0157         v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
0158     }
0159 
0160     v4l2_ctrl_handler_init(&state->hdl, 2);
0161     v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
0162             V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
0163     v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
0164             V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
0165     sd->ctrl_handler = &state->hdl;
0166     if (state->hdl.error) {
0167         int err = state->hdl.error;
0168 
0169         v4l2_ctrl_handler_free(&state->hdl);
0170         return err;
0171     }
0172 
0173     /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
0174 
0175     cs53l32a_write(sd, 0x01, 0x21);
0176     cs53l32a_write(sd, 0x02, 0x29);
0177     cs53l32a_write(sd, 0x03, 0x30);
0178     cs53l32a_write(sd, 0x04, 0x00);
0179     cs53l32a_write(sd, 0x05, 0x00);
0180     cs53l32a_write(sd, 0x06, 0x00);
0181     cs53l32a_write(sd, 0x07, 0x00);
0182 
0183     /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
0184 
0185     for (i = 1; i <= 7; i++) {
0186         u8 v = cs53l32a_read(sd, i);
0187 
0188         v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
0189     }
0190     return 0;
0191 }
0192 
0193 static int cs53l32a_remove(struct i2c_client *client)
0194 {
0195     struct v4l2_subdev *sd = i2c_get_clientdata(client);
0196     struct cs53l32a_state *state = to_state(sd);
0197 
0198     v4l2_device_unregister_subdev(sd);
0199     v4l2_ctrl_handler_free(&state->hdl);
0200     return 0;
0201 }
0202 
0203 static const struct i2c_device_id cs53l32a_id[] = {
0204     { "cs53l32a", 0 },
0205     { }
0206 };
0207 MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
0208 
0209 static struct i2c_driver cs53l32a_driver = {
0210     .driver = {
0211         .name   = "cs53l32a",
0212     },
0213     .probe      = cs53l32a_probe,
0214     .remove     = cs53l32a_remove,
0215     .id_table   = cs53l32a_id,
0216 };
0217 
0218 module_i2c_driver(cs53l32a_driver);