diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-11-29 11:02:26 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:38:43 -0500 |
commit | f1460e9771b2166ff5802cf95e81b7e00b055303 (patch) | |
tree | faaa8b396f1c57209e0591aace980d17012b6300 /drivers/media/video | |
parent | d9460f067e45a0099cfa9349361de3b19e8e8ceb (diff) |
V4L/DVB (9833): wm8739: convert to v4l2_subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/wm8739.c | 188 |
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 | ||
54 | struct wm8739_state { | 54 | struct 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 | ||
64 | static 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 | ||
65 | static int wm8739_write(struct i2c_client *client, int reg, u16 val) | 71 | static 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 */ |
85 | static void wm8739_set_audio(struct i2c_client *client) | 92 | static 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 | ||
97 | static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 104 | static 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 | ||
120 | static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 127 | static 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 | ||
189 | static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg) | 196 | static 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: | 224 | static 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: | 236 | static 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: | 243 | static 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 | ||
255 | static 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 | |||
262 | static 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 | |||
270 | static const struct v4l2_subdev_audio_ops wm8739_audio_ops = { | ||
271 | .s_clock_freq = wm8739_s_clock_freq, | ||
272 | }; | ||
273 | |||
274 | static 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 | ||
308 | static int wm8739_remove(struct i2c_client *client) | 329 | static 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 | ||