Blame view

drivers/media/video/tlv320aic23b.c 5.76 KB
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /*
   * tlv320aic23b - driver version 0.0.1
   *
   * Copyright (C) 2006 Scott Alfter <salfter@ssai.us>
   *
   * Based on wm8775 driver
   *
   * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
   * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
   *
   * 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>
  #include <linux/ioctl.h>
  #include <asm/uaccess.h>
  #include <linux/i2c.h>
  #include <linux/i2c-id.h>
33b687cf1   Hans Verkuil   V4L/DVB (8487): v...
32
  #include <linux/videodev2.h>
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
33
  #include <media/v4l2-device.h>
6235168db   Hans Verkuil   V4L/DVB (6464): t...
34
  #include <media/v4l2-i2c-drv-legacy.h>
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
35
36
37
38
39
40
  
  MODULE_DESCRIPTION("tlv320aic23b driver");
  MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
  MODULE_LICENSE("GPL");
  
  static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
41
42
43
44
45
  I2C_CLIENT_INSMOD;
  
  /* ----------------------------------------------------------------------- */
  
  struct tlv320aic23b_state {
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
46
  	struct v4l2_subdev sd;
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
47
48
  	u8 muted;
  };
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
49
  static inline struct tlv320aic23b_state *to_state(struct v4l2_subdev *sd)
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
50
  {
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
51
52
53
54
55
56
  	return container_of(sd, struct tlv320aic23b_state, sd);
  }
  
  static int tlv320aic23b_write(struct v4l2_subdev *sd, int reg, u16 val)
  {
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
57
58
59
  	int i;
  
  	if ((reg < 0 || reg > 9) && (reg != 15)) {
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
60
61
  		v4l2_err(sd, "Invalid register R%d
  ", reg);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
62
63
  		return -1;
  	}
574dec611   Hans Verkuil   V4L/DVB (6740): t...
64
65
66
  	for (i = 0; i < 3; i++)
  		if (i2c_smbus_write_byte_data(client,
  				(reg << 1) | (val >> 8), val & 0xff) == 0)
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
67
  			return 0;
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
68
69
  	v4l2_err(sd, "I2C: cannot write %03x to register R%d
  ", val, reg);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
70
71
  	return -1;
  }
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
72
  static int tlv320aic23b_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
73
  {
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
74
75
76
  	switch (freq) {
  	case 32000: /* set sample rate to 32 kHz */
  		tlv320aic23b_write(sd, 8, 0x018);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
77
  		break;
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
78
79
  	case 44100: /* set sample rate to 44.1 kHz */
  		tlv320aic23b_write(sd, 8, 0x022);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
80
  		break;
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
81
82
  	case 48000: /* set sample rate to 48 kHz */
  		tlv320aic23b_write(sd, 8, 0x000);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
83
  		break;
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
84
85
86
87
88
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  static int tlv320aic23b_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
  {
  	struct tlv320aic23b_state *state = to_state(sd);
  
  	if (ctrl->id != V4L2_CID_AUDIO_MUTE)
  		return -EINVAL;
  	ctrl->value = state->muted;
  	return 0;
  }
  
  static int tlv320aic23b_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
  {
  	struct tlv320aic23b_state *state = to_state(sd);
  
  	if (ctrl->id != V4L2_CID_AUDIO_MUTE)
  		return -EINVAL;
  	state->muted = ctrl->value;
  	tlv320aic23b_write(sd, 0, 0x180); /* mute both channels */
  	/* set gain on both channels to +3.0 dB */
  	if (!state->muted)
  		tlv320aic23b_write(sd, 0, 0x119);
  	return 0;
  }
  
  static int tlv320aic23b_log_status(struct v4l2_subdev *sd)
  {
  	struct tlv320aic23b_state *state = to_state(sd);
  
  	v4l2_info(sd, "Input: %s
  ", state->muted ? "muted" : "active");
  	return 0;
  }
  
  static int tlv320aic23b_command(struct i2c_client *client, unsigned cmd, void *arg)
  {
  	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
  }
  
  /* ----------------------------------------------------------------------- */
  
  static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = {
  	.log_status = tlv320aic23b_log_status,
  	.g_ctrl = tlv320aic23b_g_ctrl,
  	.s_ctrl = tlv320aic23b_s_ctrl,
  };
  
  static const struct v4l2_subdev_audio_ops tlv320aic23b_audio_ops = {
  	.s_clock_freq = tlv320aic23b_s_clock_freq,
  };
  
  static const struct v4l2_subdev_ops tlv320aic23b_ops = {
  	.core = &tlv320aic23b_core_ops,
  	.audio = &tlv320aic23b_audio_ops,
  };
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
143
144
145
146
147
148
149
150
  /* ----------------------------------------------------------------------- */
  
  /* 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 ...
151
152
  static int tlv320aic23b_probe(struct i2c_client *client,
  			      const struct i2c_device_id *id)
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
153
  {
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
154
  	struct tlv320aic23b_state *state;
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
155
  	struct v4l2_subdev *sd;
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
156
157
  
  	/* Check if the adapter supports the needed features */
6235168db   Hans Verkuil   V4L/DVB (6464): t...
158
  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
188f3457c   Hans Verkuil   V4L/DVB (6465): U...
159
  		return -EIO;
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
160

574dec611   Hans Verkuil   V4L/DVB (6740): t...
161
162
163
  	v4l_info(client, "chip found @ 0x%x (%s)
  ",
  			client->addr << 1, client->adapter->name);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
164

6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
165
  	state = kzalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL);
574dec611   Hans Verkuil   V4L/DVB (6740): t...
166
  	if (state == NULL)
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
167
  		return -ENOMEM;
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
168
169
  	sd = &state->sd;
  	v4l2_i2c_subdev_init(sd, client, &tlv320aic23b_ops);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
170
  	state->muted = 0;
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
171

574dec611   Hans Verkuil   V4L/DVB (6740): t...
172
173
174
  	/* Initialize tlv320aic23b */
  
  	/* RESET */
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
175
  	tlv320aic23b_write(sd, 15, 0x000);
574dec611   Hans Verkuil   V4L/DVB (6740): t...
176
  	/* turn off DAC & mic input */
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
177
  	tlv320aic23b_write(sd, 6, 0x00A);
574dec611   Hans Verkuil   V4L/DVB (6740): t...
178
  	/* left-justified, 24-bit, master mode */
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
179
  	tlv320aic23b_write(sd, 7, 0x049);
574dec611   Hans Verkuil   V4L/DVB (6740): t...
180
  	/* set gain on both channels to +3.0 dB */
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
181
  	tlv320aic23b_write(sd, 0, 0x119);
574dec611   Hans Verkuil   V4L/DVB (6740): t...
182
  	/* set sample rate to 48 kHz */
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
183
  	tlv320aic23b_write(sd, 8, 0x000);
574dec611   Hans Verkuil   V4L/DVB (6740): t...
184
  	/* activate digital interface */
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
185
  	tlv320aic23b_write(sd, 9, 0x001);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
186
187
  	return 0;
  }
6235168db   Hans Verkuil   V4L/DVB (6464): t...
188
  static int tlv320aic23b_remove(struct i2c_client *client)
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
189
  {
6869ffe80   Hans Verkuil   V4L/DVB (9963): t...
190
191
192
193
  	struct v4l2_subdev *sd = i2c_get_clientdata(client);
  
  	v4l2_device_unregister_subdev(sd);
  	kfree(to_state(sd));
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
194
195
196
197
  	return 0;
  }
  
  /* ----------------------------------------------------------------------- */
ae429083e   Jean Delvare   i2c: Convert some...
198
199
200
201
202
  static const struct i2c_device_id tlv320aic23b_id[] = {
  	{ "tlv320aic23b", 0 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id);
88ca8ed0b   Scott Alfter   V4L/DVB (4048): A...
203

6235168db   Hans Verkuil   V4L/DVB (6464): t...
204
205
  static struct v4l2_i2c_driver_data v4l2_i2c_data = {
  	.name = "tlv320aic23b",
6235168db   Hans Verkuil   V4L/DVB (6464): t...
206
207
208
  	.command = tlv320aic23b_command,
  	.probe = tlv320aic23b_probe,
  	.remove = tlv320aic23b_remove,
ae429083e   Jean Delvare   i2c: Convert some...
209
  	.id_table = tlv320aic23b_id,
6235168db   Hans Verkuil   V4L/DVB (6464): t...
210
  };