aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/wm8739.c188
1 files changed, 106 insertions, 82 deletions
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index 54ac3fe26ec2..12a31e7a5f6d 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -28,7 +28,7 @@
28#include <linux/i2c.h> 28#include <linux/i2c.h>
29#include <linux/i2c-id.h> 29#include <linux/i2c-id.h>
30#include <linux/videodev2.h> 30#include <linux/videodev2.h>
31#include <media/v4l2-common.h> 31#include <media/v4l2-device.h>
32#include <media/v4l2-chip-ident.h> 32#include <media/v4l2-chip-ident.h>
33#include <media/v4l2-i2c-drv.h> 33#include <media/v4l2-i2c-drv.h>
34 34
@@ -52,6 +52,7 @@ enum {
52}; 52};
53 53
54struct wm8739_state { 54struct wm8739_state {
55 struct v4l2_subdev sd;
55 u32 clock_freq; 56 u32 clock_freq;
56 u8 muted; 57 u8 muted;
57 u16 volume; 58 u16 volume;
@@ -60,43 +61,49 @@ struct wm8739_state {
60 u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */ 61 u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
61}; 62};
62 63
64static inline struct wm8739_state *to_state(struct v4l2_subdev *sd)
65{
66 return container_of(sd, struct wm8739_state, sd);
67}
68
63/* ------------------------------------------------------------------------ */ 69/* ------------------------------------------------------------------------ */
64 70
65static int wm8739_write(struct i2c_client *client, int reg, u16 val) 71static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val)
66{ 72{
73 struct i2c_client *client = v4l2_get_subdevdata(sd);
67 int i; 74 int i;
68 75
69 if (reg < 0 || reg >= TOT_REGS) { 76 if (reg < 0 || reg >= TOT_REGS) {
70 v4l_err(client, "Invalid register R%d\n", reg); 77 v4l2_err(sd, "Invalid register R%d\n", reg);
71 return -1; 78 return -1;
72 } 79 }
73 80
74 v4l_dbg(1, debug, client, "write: %02x %02x\n", reg, val); 81 v4l2_dbg(1, debug, sd, "write: %02x %02x\n", reg, val);
75 82
76 for (i = 0; i < 3; i++) 83 for (i = 0; i < 3; i++)
77 if (i2c_smbus_write_byte_data(client, 84 if (i2c_smbus_write_byte_data(client,
78 (reg << 1) | (val >> 8), val & 0xff) == 0) 85 (reg << 1) | (val >> 8), val & 0xff) == 0)
79 return 0; 86 return 0;
80 v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); 87 v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
81 return -1; 88 return -1;
82} 89}
83 90
84/* write regs to set audio volume etc */ 91/* write regs to set audio volume etc */
85static void wm8739_set_audio(struct i2c_client *client) 92static void wm8739_set_audio(struct v4l2_subdev *sd)
86{ 93{
87 struct wm8739_state *state = i2c_get_clientdata(client); 94 struct wm8739_state *state = to_state(sd);
88 u16 mute = state->muted ? 0x80 : 0; 95 u16 mute = state->muted ? 0x80 : 0;
89 96
90 /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB 97 /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
91 * Default setting: 0x17 = 0 dB 98 * Default setting: 0x17 = 0 dB
92 */ 99 */
93 wm8739_write(client, R0, (state->vol_l & 0x1f) | mute); 100 wm8739_write(sd, R0, (state->vol_l & 0x1f) | mute);
94 wm8739_write(client, R1, (state->vol_r & 0x1f) | mute); 101 wm8739_write(sd, R1, (state->vol_r & 0x1f) | mute);
95} 102}
96 103
97static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) 104static int wm8739_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
98{ 105{
99 struct wm8739_state *state = i2c_get_clientdata(client); 106 struct wm8739_state *state = to_state(sd);
100 107
101 switch (ctrl->id) { 108 switch (ctrl->id) {
102 case V4L2_CID_AUDIO_MUTE: 109 case V4L2_CID_AUDIO_MUTE:
@@ -117,9 +124,9 @@ static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
117 return 0; 124 return 0;
118} 125}
119 126
120static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) 127static int wm8739_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
121{ 128{
122 struct wm8739_state *state = i2c_get_clientdata(client); 129 struct wm8739_state *state = to_state(sd);
123 unsigned int work_l, work_r; 130 unsigned int work_l, work_r;
124 131
125 switch (ctrl->id) { 132 switch (ctrl->id) {
@@ -147,7 +154,7 @@ static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
147 state->vol_r = (long)work_r * 31 / 65535; 154 state->vol_r = (long)work_r * 31 / 65535;
148 155
149 /* set audio volume etc. */ 156 /* set audio volume etc. */
150 wm8739_set_audio(client); 157 wm8739_set_audio(sd);
151 return 0; 158 return 0;
152} 159}
153 160
@@ -186,77 +193,89 @@ static struct v4l2_queryctrl wm8739_qctrl[] = {
186 193
187/* ------------------------------------------------------------------------ */ 194/* ------------------------------------------------------------------------ */
188 195
189static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg) 196static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq)
190{ 197{
191 struct wm8739_state *state = i2c_get_clientdata(client); 198 struct wm8739_state *state = to_state(sd);
192 199
193 switch (cmd) { 200 state->clock_freq = audiofreq;
194 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 201 /* de-activate */
195 { 202 wm8739_write(sd, R9, 0x000);
196 u32 audiofreq = *(u32 *)arg; 203 switch (audiofreq) {
197 204 case 44100:
198 state->clock_freq = audiofreq; 205 /* 256fps, fs=44.1k */
199 /* de-activate */ 206 wm8739_write(sd, R8, 0x020);
200 wm8739_write(client, R9, 0x000); 207 break;
201 switch (audiofreq) { 208 case 48000:
202 case 44100: 209 /* 256fps, fs=48k */
203 /* 256fps, fs=44.1k */ 210 wm8739_write(sd, R8, 0x000);
204 wm8739_write(client, R8, 0x020); 211 break;
205 break; 212 case 32000:
206 case 48000: 213 /* 256fps, fs=32k */
207 /* 256fps, fs=48k */ 214 wm8739_write(sd, R8, 0x018);
208 wm8739_write(client, R8, 0x000); 215 break;
209 break; 216 default:
210 case 32000:
211 /* 256fps, fs=32k */
212 wm8739_write(client, R8, 0x018);
213 break;
214 default:
215 break;
216 }
217 /* activate */
218 wm8739_write(client, R9, 0x001);
219 break; 217 break;
220 } 218 }
219 /* activate */
220 wm8739_write(sd, R9, 0x001);
221 return 0;
222}
221 223
222 case VIDIOC_G_CTRL: 224static int wm8739_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
223 return wm8739_get_ctrl(client, arg); 225{
224 226 int i;
225 case VIDIOC_S_CTRL:
226 return wm8739_set_ctrl(client, arg);
227 227
228 case VIDIOC_QUERYCTRL: 228 for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++)
229 { 229 if (qc->id && qc->id == wm8739_qctrl[i].id) {
230 struct v4l2_queryctrl *qc = arg; 230 memcpy(qc, &wm8739_qctrl[i], sizeof(*qc));
231 int i; 231 return 0;
232 232 }
233 for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++) 233 return -EINVAL;
234 if (qc->id && qc->id == wm8739_qctrl[i].id) { 234}
235 memcpy(qc, &wm8739_qctrl[i], sizeof(*qc));
236 return 0;
237 }
238 return -EINVAL;
239 }
240 235
241 case VIDIOC_G_CHIP_IDENT: 236static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
242 return v4l2_chip_ident_i2c_client(client, 237{
243 arg, V4L2_IDENT_WM8739, 0); 238 struct i2c_client *client = v4l2_get_subdevdata(sd);
244 239
245 case VIDIOC_LOG_STATUS: 240 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8739, 0);
246 v4l_info(client, "Frequency: %u Hz\n", state->clock_freq); 241}
247 v4l_info(client, "Volume L: %02x%s\n", state->vol_l & 0x1f,
248 state->muted ? " (muted)" : "");
249 v4l_info(client, "Volume R: %02x%s\n", state->vol_r & 0x1f,
250 state->muted ? " (muted)" : "");
251 break;
252 242
253 default: 243static int wm8739_log_status(struct v4l2_subdev *sd)
254 return -EINVAL; 244{
255 } 245 struct wm8739_state *state = to_state(sd);
256 246
247 v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq);
248 v4l2_info(sd, "Volume L: %02x%s\n", state->vol_l & 0x1f,
249 state->muted ? " (muted)" : "");
250 v4l2_info(sd, "Volume R: %02x%s\n", state->vol_r & 0x1f,
251 state->muted ? " (muted)" : "");
257 return 0; 252 return 0;
258} 253}
259 254
255static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg)
256{
257 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
258}
259
260/* ----------------------------------------------------------------------- */
261
262static const struct v4l2_subdev_core_ops wm8739_core_ops = {
263 .log_status = wm8739_log_status,
264 .g_chip_ident = wm8739_g_chip_ident,
265 .queryctrl = wm8739_queryctrl,
266 .g_ctrl = wm8739_g_ctrl,
267 .s_ctrl = wm8739_s_ctrl,
268};
269
270static const struct v4l2_subdev_audio_ops wm8739_audio_ops = {
271 .s_clock_freq = wm8739_s_clock_freq,
272};
273
274static const struct v4l2_subdev_ops wm8739_ops = {
275 .core = &wm8739_core_ops,
276 .audio = &wm8739_audio_ops,
277};
278
260/* ------------------------------------------------------------------------ */ 279/* ------------------------------------------------------------------------ */
261 280
262/* i2c implementation */ 281/* i2c implementation */
@@ -265,6 +284,7 @@ static int wm8739_probe(struct i2c_client *client,
265 const struct i2c_device_id *id) 284 const struct i2c_device_id *id)
266{ 285{
267 struct wm8739_state *state; 286 struct wm8739_state *state;
287 struct v4l2_subdev *sd;
268 288
269 /* Check if the adapter supports the needed features */ 289 /* Check if the adapter supports the needed features */
270 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 290 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -276,6 +296,8 @@ static int wm8739_probe(struct i2c_client *client,
276 state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); 296 state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
277 if (state == NULL) 297 if (state == NULL)
278 return -ENOMEM; 298 return -ENOMEM;
299 sd = &state->sd;
300 v4l2_i2c_subdev_init(sd, client, &wm8739_ops);
279 state->vol_l = 0x17; /* 0dB */ 301 state->vol_l = 0x17; /* 0dB */
280 state->vol_r = 0x17; /* 0dB */ 302 state->vol_r = 0x17; /* 0dB */
281 state->muted = 0; 303 state->muted = 0;
@@ -283,31 +305,33 @@ static int wm8739_probe(struct i2c_client *client,
283 /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */ 305 /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */
284 state->volume = ((long)state->vol_l + 1) * 65535 / 31; 306 state->volume = ((long)state->vol_l + 1) * 65535 / 31;
285 state->clock_freq = 48000; 307 state->clock_freq = 48000;
286 i2c_set_clientdata(client, state);
287 308
288 /* Initialize wm8739 */ 309 /* Initialize wm8739 */
289 310
290 /* reset */ 311 /* reset */
291 wm8739_write(client, R15, 0x00); 312 wm8739_write(sd, R15, 0x00);
292 /* filter setting, high path, offet clear */ 313 /* filter setting, high path, offet clear */
293 wm8739_write(client, R5, 0x000); 314 wm8739_write(sd, R5, 0x000);
294 /* ADC, OSC, Power Off mode Disable */ 315 /* ADC, OSC, Power Off mode Disable */
295 wm8739_write(client, R6, 0x000); 316 wm8739_write(sd, R6, 0x000);
296 /* Digital Audio interface format: 317 /* Digital Audio interface format:
297 Enable Master mode, 24 bit, MSB first/left justified */ 318 Enable Master mode, 24 bit, MSB first/left justified */
298 wm8739_write(client, R7, 0x049); 319 wm8739_write(sd, R7, 0x049);
299 /* sampling control: normal, 256fs, 48KHz sampling rate */ 320 /* sampling control: normal, 256fs, 48KHz sampling rate */
300 wm8739_write(client, R8, 0x000); 321 wm8739_write(sd, R8, 0x000);
301 /* activate */ 322 /* activate */
302 wm8739_write(client, R9, 0x001); 323 wm8739_write(sd, R9, 0x001);
303 /* set volume/mute */ 324 /* set volume/mute */
304 wm8739_set_audio(client); 325 wm8739_set_audio(sd);
305 return 0; 326 return 0;
306} 327}
307 328
308static int wm8739_remove(struct i2c_client *client) 329static int wm8739_remove(struct i2c_client *client)
309{ 330{
310 kfree(i2c_get_clientdata(client)); 331 struct v4l2_subdev *sd = i2c_get_clientdata(client);
332
333 v4l2_device_unregister_subdev(sd);
334 kfree(to_state(sd));
311 return 0; 335 return 0;
312} 336}
313 337