1 /* 2 * tlv320aic23b - driver version 0.0.1 3 * 4 * Copyright (C) 2006 Scott Alfter <salfter@ssai.us> 5 * 6 * Based on wm8775 driver 7 * 8 * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to> 9 * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 */ 21 22 #include <linux/module.h> 23 #include <linux/types.h> 24 #include <linux/slab.h> 25 #include <linux/ioctl.h> 26 #include <linux/uaccess.h> 27 #include <linux/i2c.h> 28 #include <linux/videodev2.h> 29 #include <media/v4l2-device.h> 30 #include <media/v4l2-ctrls.h> 31 32 MODULE_DESCRIPTION("tlv320aic23b driver"); 33 MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); 34 MODULE_LICENSE("GPL"); 35 36 37 /* ----------------------------------------------------------------------- */ 38 39 struct tlv320aic23b_state { 40 struct v4l2_subdev sd; 41 struct v4l2_ctrl_handler hdl; 42 }; 43 44 static inline struct tlv320aic23b_state *to_state(struct v4l2_subdev *sd) 45 { 46 return container_of(sd, struct tlv320aic23b_state, sd); 47 } 48 49 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 50 { 51 return &container_of(ctrl->handler, struct tlv320aic23b_state, hdl)->sd; 52 } 53 54 static int tlv320aic23b_write(struct v4l2_subdev *sd, int reg, u16 val) 55 { 56 struct i2c_client *client = v4l2_get_subdevdata(sd); 57 int i; 58 59 if ((reg < 0 || reg > 9) && (reg != 15)) { 60 v4l2_err(sd, "Invalid register R%d\n", reg); 61 return -1; 62 } 63 64 for (i = 0; i < 3; i++) 65 if (i2c_smbus_write_byte_data(client, 66 (reg << 1) | (val >> 8), val & 0xff) == 0) 67 return 0; 68 v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg); 69 return -1; 70 } 71 72 static int tlv320aic23b_s_clock_freq(struct v4l2_subdev *sd, u32 freq) 73 { 74 switch (freq) { 75 case 32000: /* set sample rate to 32 kHz */ 76 tlv320aic23b_write(sd, 8, 0x018); 77 break; 78 case 44100: /* set sample rate to 44.1 kHz */ 79 tlv320aic23b_write(sd, 8, 0x022); 80 break; 81 case 48000: /* set sample rate to 48 kHz */ 82 tlv320aic23b_write(sd, 8, 0x000); 83 break; 84 default: 85 return -EINVAL; 86 } 87 return 0; 88 } 89 90 static int tlv320aic23b_s_ctrl(struct v4l2_ctrl *ctrl) 91 { 92 struct v4l2_subdev *sd = to_sd(ctrl); 93 94 switch (ctrl->id) { 95 case V4L2_CID_AUDIO_MUTE: 96 tlv320aic23b_write(sd, 0, 0x180); /* mute both channels */ 97 /* set gain on both channels to +3.0 dB */ 98 if (!ctrl->val) 99 tlv320aic23b_write(sd, 0, 0x119); 100 return 0; 101 } 102 return -EINVAL; 103 } 104 105 static int tlv320aic23b_log_status(struct v4l2_subdev *sd) 106 { 107 struct tlv320aic23b_state *state = to_state(sd); 108 109 v4l2_ctrl_handler_log_status(&state->hdl, sd->name); 110 return 0; 111 } 112 113 /* ----------------------------------------------------------------------- */ 114 115 static const struct v4l2_ctrl_ops tlv320aic23b_ctrl_ops = { 116 .s_ctrl = tlv320aic23b_s_ctrl, 117 }; 118 119 static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = { 120 .log_status = tlv320aic23b_log_status, 121 }; 122 123 static const struct v4l2_subdev_audio_ops tlv320aic23b_audio_ops = { 124 .s_clock_freq = tlv320aic23b_s_clock_freq, 125 }; 126 127 static const struct v4l2_subdev_ops tlv320aic23b_ops = { 128 .core = &tlv320aic23b_core_ops, 129 .audio = &tlv320aic23b_audio_ops, 130 }; 131 132 /* ----------------------------------------------------------------------- */ 133 134 /* i2c implementation */ 135 136 /* 137 * Generic i2c probe 138 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 139 */ 140 141 static int tlv320aic23b_probe(struct i2c_client *client, 142 const struct i2c_device_id *id) 143 { 144 struct tlv320aic23b_state *state; 145 struct v4l2_subdev *sd; 146 147 /* Check if the adapter supports the needed features */ 148 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 149 return -EIO; 150 151 v4l_info(client, "chip found @ 0x%x (%s)\n", 152 client->addr << 1, client->adapter->name); 153 154 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); 155 if (state == NULL) 156 return -ENOMEM; 157 sd = &state->sd; 158 v4l2_i2c_subdev_init(sd, client, &tlv320aic23b_ops); 159 160 /* Initialize tlv320aic23b */ 161 162 /* RESET */ 163 tlv320aic23b_write(sd, 15, 0x000); 164 /* turn off DAC & mic input */ 165 tlv320aic23b_write(sd, 6, 0x00A); 166 /* left-justified, 24-bit, master mode */ 167 tlv320aic23b_write(sd, 7, 0x049); 168 /* set gain on both channels to +3.0 dB */ 169 tlv320aic23b_write(sd, 0, 0x119); 170 /* set sample rate to 48 kHz */ 171 tlv320aic23b_write(sd, 8, 0x000); 172 /* activate digital interface */ 173 tlv320aic23b_write(sd, 9, 0x001); 174 175 v4l2_ctrl_handler_init(&state->hdl, 1); 176 v4l2_ctrl_new_std(&state->hdl, &tlv320aic23b_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); 183 return err; 184 } 185 v4l2_ctrl_handler_setup(&state->hdl); 186 return 0; 187 } 188 189 static int tlv320aic23b_remove(struct i2c_client *client) 190 { 191 struct v4l2_subdev *sd = i2c_get_clientdata(client); 192 struct tlv320aic23b_state *state = to_state(sd); 193 194 v4l2_device_unregister_subdev(sd); 195 v4l2_ctrl_handler_free(&state->hdl); 196 return 0; 197 } 198 199 /* ----------------------------------------------------------------------- */ 200 201 static const struct i2c_device_id tlv320aic23b_id[] = { 202 { "tlv320aic23b", 0 }, 203 { } 204 }; 205 MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id); 206 207 static struct i2c_driver tlv320aic23b_driver = { 208 .driver = { 209 .name = "tlv320aic23b", 210 }, 211 .probe = tlv320aic23b_probe, 212 .remove = tlv320aic23b_remove, 213 .id_table = tlv320aic23b_id, 214 }; 215 216 module_i2c_driver(tlv320aic23b_driver); 217