diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-12-12 05:53:28 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:31:49 -0400 |
commit | 34a078da8e20ca40a09bfa635ff2c4e2c4b648b1 (patch) | |
tree | 9f32132ef3c55226b3f251f32cce7556772c9ee2 /drivers/media/video/cs5345.c | |
parent | 1f075d1f1bfb7101be9a651a4d087193b4f05b23 (diff) |
[media] cs5345: use the control framework
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cs5345.c')
-rw-r--r-- | drivers/media/video/cs5345.c | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 9358fe77e562..5909f2557ab4 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <media/v4l2-device.h> | 26 | #include <media/v4l2-device.h> |
27 | #include <media/v4l2-chip-ident.h> | 27 | #include <media/v4l2-chip-ident.h> |
28 | #include <media/v4l2-ctrls.h> | ||
28 | 29 | ||
29 | MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); | 30 | MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); |
30 | MODULE_AUTHOR("Hans Verkuil"); | 31 | MODULE_AUTHOR("Hans Verkuil"); |
@@ -36,6 +37,20 @@ module_param(debug, bool, 0644); | |||
36 | 37 | ||
37 | MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); | 38 | MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); |
38 | 39 | ||
40 | struct cs5345_state { | ||
41 | struct v4l2_subdev sd; | ||
42 | struct v4l2_ctrl_handler hdl; | ||
43 | }; | ||
44 | |||
45 | static inline struct cs5345_state *to_state(struct v4l2_subdev *sd) | ||
46 | { | ||
47 | return container_of(sd, struct cs5345_state, sd); | ||
48 | } | ||
49 | |||
50 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
51 | { | ||
52 | return &container_of(ctrl->handler, struct cs5345_state, hdl)->sd; | ||
53 | } | ||
39 | 54 | ||
40 | /* ----------------------------------------------------------------------- */ | 55 | /* ----------------------------------------------------------------------- */ |
41 | 56 | ||
@@ -65,33 +80,20 @@ static int cs5345_s_routing(struct v4l2_subdev *sd, | |||
65 | return 0; | 80 | return 0; |
66 | } | 81 | } |
67 | 82 | ||
68 | static int cs5345_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 83 | static int cs5345_s_ctrl(struct v4l2_ctrl *ctrl) |
69 | { | 84 | { |
70 | if (ctrl->id == V4L2_CID_AUDIO_MUTE) { | 85 | struct v4l2_subdev *sd = to_sd(ctrl); |
71 | ctrl->value = (cs5345_read(sd, 0x04) & 0x08) != 0; | ||
72 | return 0; | ||
73 | } | ||
74 | if (ctrl->id != V4L2_CID_AUDIO_VOLUME) | ||
75 | return -EINVAL; | ||
76 | ctrl->value = cs5345_read(sd, 0x07) & 0x3f; | ||
77 | if (ctrl->value >= 32) | ||
78 | ctrl->value = ctrl->value - 64; | ||
79 | return 0; | ||
80 | } | ||
81 | 86 | ||
82 | static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 87 | switch (ctrl->id) { |
83 | { | 88 | case V4L2_CID_AUDIO_MUTE: |
84 | if (ctrl->id == V4L2_CID_AUDIO_MUTE) { | 89 | cs5345_write(sd, 0x04, ctrl->val ? 0x80 : 0); |
85 | cs5345_write(sd, 0x04, ctrl->value ? 0x80 : 0); | 90 | return 0; |
91 | case V4L2_CID_AUDIO_VOLUME: | ||
92 | cs5345_write(sd, 0x07, ((u8)ctrl->val) & 0x3f); | ||
93 | cs5345_write(sd, 0x08, ((u8)ctrl->val) & 0x3f); | ||
86 | return 0; | 94 | return 0; |
87 | } | 95 | } |
88 | if (ctrl->id != V4L2_CID_AUDIO_VOLUME) | 96 | return -EINVAL; |
89 | return -EINVAL; | ||
90 | if (ctrl->value > 24 || ctrl->value < -24) | ||
91 | return -EINVAL; | ||
92 | cs5345_write(sd, 0x07, ((u8)ctrl->value) & 0x3f); | ||
93 | cs5345_write(sd, 0x08, ((u8)ctrl->value) & 0x3f); | ||
94 | return 0; | ||
95 | } | 97 | } |
96 | 98 | ||
97 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 99 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -144,11 +146,20 @@ static int cs5345_log_status(struct v4l2_subdev *sd) | |||
144 | 146 | ||
145 | /* ----------------------------------------------------------------------- */ | 147 | /* ----------------------------------------------------------------------- */ |
146 | 148 | ||
149 | static const struct v4l2_ctrl_ops cs5345_ctrl_ops = { | ||
150 | .s_ctrl = cs5345_s_ctrl, | ||
151 | }; | ||
152 | |||
147 | static const struct v4l2_subdev_core_ops cs5345_core_ops = { | 153 | static const struct v4l2_subdev_core_ops cs5345_core_ops = { |
148 | .log_status = cs5345_log_status, | 154 | .log_status = cs5345_log_status, |
149 | .g_chip_ident = cs5345_g_chip_ident, | 155 | .g_chip_ident = cs5345_g_chip_ident, |
150 | .g_ctrl = cs5345_g_ctrl, | 156 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
151 | .s_ctrl = cs5345_s_ctrl, | 157 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, |
158 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, | ||
159 | .g_ctrl = v4l2_subdev_g_ctrl, | ||
160 | .s_ctrl = v4l2_subdev_s_ctrl, | ||
161 | .queryctrl = v4l2_subdev_queryctrl, | ||
162 | .querymenu = v4l2_subdev_querymenu, | ||
152 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 163 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
153 | .g_register = cs5345_g_register, | 164 | .g_register = cs5345_g_register, |
154 | .s_register = cs5345_s_register, | 165 | .s_register = cs5345_s_register, |
@@ -169,6 +180,7 @@ static const struct v4l2_subdev_ops cs5345_ops = { | |||
169 | static int cs5345_probe(struct i2c_client *client, | 180 | static int cs5345_probe(struct i2c_client *client, |
170 | const struct i2c_device_id *id) | 181 | const struct i2c_device_id *id) |
171 | { | 182 | { |
183 | struct cs5345_state *state; | ||
172 | struct v4l2_subdev *sd; | 184 | struct v4l2_subdev *sd; |
173 | 185 | ||
174 | /* Check if the adapter supports the needed features */ | 186 | /* Check if the adapter supports the needed features */ |
@@ -178,11 +190,28 @@ static int cs5345_probe(struct i2c_client *client, | |||
178 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 190 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
179 | client->addr << 1, client->adapter->name); | 191 | client->addr << 1, client->adapter->name); |
180 | 192 | ||
181 | sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); | 193 | state = kzalloc(sizeof(struct cs5345_state), GFP_KERNEL); |
182 | if (sd == NULL) | 194 | if (state == NULL) |
183 | return -ENOMEM; | 195 | return -ENOMEM; |
196 | sd = &state->sd; | ||
184 | v4l2_i2c_subdev_init(sd, client, &cs5345_ops); | 197 | v4l2_i2c_subdev_init(sd, client, &cs5345_ops); |
185 | 198 | ||
199 | v4l2_ctrl_handler_init(&state->hdl, 2); | ||
200 | v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops, | ||
201 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); | ||
202 | v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops, | ||
203 | V4L2_CID_AUDIO_VOLUME, -24, 24, 1, 0); | ||
204 | sd->ctrl_handler = &state->hdl; | ||
205 | if (state->hdl.error) { | ||
206 | int err = state->hdl.error; | ||
207 | |||
208 | v4l2_ctrl_handler_free(&state->hdl); | ||
209 | kfree(state); | ||
210 | return err; | ||
211 | } | ||
212 | /* set volume/mute */ | ||
213 | v4l2_ctrl_handler_setup(&state->hdl); | ||
214 | |||
186 | cs5345_write(sd, 0x02, 0x00); | 215 | cs5345_write(sd, 0x02, 0x00); |
187 | cs5345_write(sd, 0x04, 0x01); | 216 | cs5345_write(sd, 0x04, 0x01); |
188 | cs5345_write(sd, 0x09, 0x01); | 217 | cs5345_write(sd, 0x09, 0x01); |
@@ -194,9 +223,11 @@ static int cs5345_probe(struct i2c_client *client, | |||
194 | static int cs5345_remove(struct i2c_client *client) | 223 | static int cs5345_remove(struct i2c_client *client) |
195 | { | 224 | { |
196 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 225 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
226 | struct cs5345_state *state = to_state(sd); | ||
197 | 227 | ||
198 | v4l2_device_unregister_subdev(sd); | 228 | v4l2_device_unregister_subdev(sd); |
199 | kfree(sd); | 229 | v4l2_ctrl_handler_free(&state->hdl); |
230 | kfree(state); | ||
200 | return 0; | 231 | return 0; |
201 | } | 232 | } |
202 | 233 | ||