Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.25 177 lines 4.7 kB view raw
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 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 */ 25 26#include <linux/module.h> 27#include <linux/types.h> 28#include <linux/ioctl.h> 29#include <asm/uaccess.h> 30#include <linux/i2c.h> 31#include <linux/i2c-id.h> 32#include <linux/videodev.h> 33#include <media/v4l2-common.h> 34#include <media/v4l2-i2c-drv-legacy.h> 35 36MODULE_DESCRIPTION("tlv320aic23b driver"); 37MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); 38MODULE_LICENSE("GPL"); 39 40static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; 41 42 43I2C_CLIENT_INSMOD; 44 45/* ----------------------------------------------------------------------- */ 46 47struct tlv320aic23b_state { 48 u8 muted; 49}; 50 51static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val) 52{ 53 int i; 54 55 if ((reg < 0 || reg > 9) && (reg != 15)) { 56 v4l_err(client, "Invalid register R%d\n", reg); 57 return -1; 58 } 59 60 for (i = 0; i < 3; i++) 61 if (i2c_smbus_write_byte_data(client, 62 (reg << 1) | (val >> 8), val & 0xff) == 0) 63 return 0; 64 v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); 65 return -1; 66} 67 68static int tlv320aic23b_command(struct i2c_client *client, 69 unsigned int cmd, void *arg) 70{ 71 struct tlv320aic23b_state *state = i2c_get_clientdata(client); 72 struct v4l2_control *ctrl = arg; 73 u32 *freq = arg; 74 75 switch (cmd) { 76 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 77 switch (*freq) { 78 case 32000: /* set sample rate to 32 kHz */ 79 tlv320aic23b_write(client, 8, 0x018); 80 break; 81 case 44100: /* set sample rate to 44.1 kHz */ 82 tlv320aic23b_write(client, 8, 0x022); 83 break; 84 case 48000: /* set sample rate to 48 kHz */ 85 tlv320aic23b_write(client, 8, 0x000); 86 break; 87 default: 88 return -EINVAL; 89 } 90 break; 91 92 case VIDIOC_G_CTRL: 93 if (ctrl->id != V4L2_CID_AUDIO_MUTE) 94 return -EINVAL; 95 ctrl->value = state->muted; 96 break; 97 98 case VIDIOC_S_CTRL: 99 if (ctrl->id != V4L2_CID_AUDIO_MUTE) 100 return -EINVAL; 101 state->muted = ctrl->value; 102 tlv320aic23b_write(client, 0, 0x180); /* mute both channels */ 103 /* set gain on both channels to +3.0 dB */ 104 if (!state->muted) 105 tlv320aic23b_write(client, 0, 0x119); 106 break; 107 108 case VIDIOC_LOG_STATUS: 109 v4l_info(client, "Input: %s\n", 110 state->muted ? "muted" : "active"); 111 break; 112 113 default: 114 return -EINVAL; 115 } 116 return 0; 117} 118 119/* ----------------------------------------------------------------------- */ 120 121/* i2c implementation */ 122 123/* 124 * Generic i2c probe 125 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' 126 */ 127 128static int tlv320aic23b_probe(struct i2c_client *client) 129{ 130 struct tlv320aic23b_state *state; 131 132 /* Check if the adapter supports the needed features */ 133 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 134 return -EIO; 135 136 v4l_info(client, "chip found @ 0x%x (%s)\n", 137 client->addr << 1, client->adapter->name); 138 139 state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); 140 if (state == NULL) 141 return -ENOMEM; 142 state->muted = 0; 143 i2c_set_clientdata(client, state); 144 145 /* Initialize tlv320aic23b */ 146 147 /* RESET */ 148 tlv320aic23b_write(client, 15, 0x000); 149 /* turn off DAC & mic input */ 150 tlv320aic23b_write(client, 6, 0x00A); 151 /* left-justified, 24-bit, master mode */ 152 tlv320aic23b_write(client, 7, 0x049); 153 /* set gain on both channels to +3.0 dB */ 154 tlv320aic23b_write(client, 0, 0x119); 155 /* set sample rate to 48 kHz */ 156 tlv320aic23b_write(client, 8, 0x000); 157 /* activate digital interface */ 158 tlv320aic23b_write(client, 9, 0x001); 159 return 0; 160} 161 162static int tlv320aic23b_remove(struct i2c_client *client) 163{ 164 kfree(i2c_get_clientdata(client)); 165 return 0; 166} 167 168/* ----------------------------------------------------------------------- */ 169 170 171static struct v4l2_i2c_driver_data v4l2_i2c_data = { 172 .name = "tlv320aic23b", 173 .driverid = I2C_DRIVERID_TLV320AIC23B, 174 .command = tlv320aic23b_command, 175 .probe = tlv320aic23b_probe, 176 .remove = tlv320aic23b_remove, 177};