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

[media] cs5345: use the control framework

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
34a078da 1f075d1f

+59 -28
+59 -28
drivers/media/video/cs5345.c
··· 25 25 #include <linux/slab.h> 26 26 #include <media/v4l2-device.h> 27 27 #include <media/v4l2-chip-ident.h> 28 + #include <media/v4l2-ctrls.h> 28 29 29 30 MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); 30 31 MODULE_AUTHOR("Hans Verkuil"); ··· 37 36 38 37 MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); 39 38 39 + struct cs5345_state { 40 + struct v4l2_subdev sd; 41 + struct v4l2_ctrl_handler hdl; 42 + }; 43 + 44 + static inline struct cs5345_state *to_state(struct v4l2_subdev *sd) 45 + { 46 + return container_of(sd, struct cs5345_state, sd); 47 + } 48 + 49 + static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 50 + { 51 + return &container_of(ctrl->handler, struct cs5345_state, hdl)->sd; 52 + } 40 53 41 54 /* ----------------------------------------------------------------------- */ 42 55 ··· 80 65 return 0; 81 66 } 82 67 83 - static int cs5345_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 68 + static int cs5345_s_ctrl(struct v4l2_ctrl *ctrl) 84 69 { 85 - if (ctrl->id == V4L2_CID_AUDIO_MUTE) { 86 - ctrl->value = (cs5345_read(sd, 0x04) & 0x08) != 0; 87 - return 0; 88 - } 89 - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) 90 - return -EINVAL; 91 - ctrl->value = cs5345_read(sd, 0x07) & 0x3f; 92 - if (ctrl->value >= 32) 93 - ctrl->value = ctrl->value - 64; 94 - return 0; 95 - } 70 + struct v4l2_subdev *sd = to_sd(ctrl); 96 71 97 - static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 98 - { 99 - if (ctrl->id == V4L2_CID_AUDIO_MUTE) { 100 - cs5345_write(sd, 0x04, ctrl->value ? 0x80 : 0); 72 + switch (ctrl->id) { 73 + case V4L2_CID_AUDIO_MUTE: 74 + cs5345_write(sd, 0x04, ctrl->val ? 0x80 : 0); 75 + return 0; 76 + case V4L2_CID_AUDIO_VOLUME: 77 + cs5345_write(sd, 0x07, ((u8)ctrl->val) & 0x3f); 78 + cs5345_write(sd, 0x08, ((u8)ctrl->val) & 0x3f); 101 79 return 0; 102 80 } 103 - if (ctrl->id != V4L2_CID_AUDIO_VOLUME) 104 - return -EINVAL; 105 - if (ctrl->value > 24 || ctrl->value < -24) 106 - return -EINVAL; 107 - cs5345_write(sd, 0x07, ((u8)ctrl->value) & 0x3f); 108 - cs5345_write(sd, 0x08, ((u8)ctrl->value) & 0x3f); 109 - return 0; 81 + return -EINVAL; 110 82 } 111 83 112 84 #ifdef CONFIG_VIDEO_ADV_DEBUG ··· 146 144 147 145 /* ----------------------------------------------------------------------- */ 148 146 147 + static const struct v4l2_ctrl_ops cs5345_ctrl_ops = { 148 + .s_ctrl = cs5345_s_ctrl, 149 + }; 150 + 149 151 static const struct v4l2_subdev_core_ops cs5345_core_ops = { 150 152 .log_status = cs5345_log_status, 151 153 .g_chip_ident = cs5345_g_chip_ident, 152 - .g_ctrl = cs5345_g_ctrl, 153 - .s_ctrl = cs5345_s_ctrl, 154 + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, 155 + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, 156 + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, 157 + .g_ctrl = v4l2_subdev_g_ctrl, 158 + .s_ctrl = v4l2_subdev_s_ctrl, 159 + .queryctrl = v4l2_subdev_queryctrl, 160 + .querymenu = v4l2_subdev_querymenu, 154 161 #ifdef CONFIG_VIDEO_ADV_DEBUG 155 162 .g_register = cs5345_g_register, 156 163 .s_register = cs5345_s_register, ··· 180 169 static int cs5345_probe(struct i2c_client *client, 181 170 const struct i2c_device_id *id) 182 171 { 172 + struct cs5345_state *state; 183 173 struct v4l2_subdev *sd; 184 174 185 175 /* Check if the adapter supports the needed features */ ··· 190 178 v4l_info(client, "chip found @ 0x%x (%s)\n", 191 179 client->addr << 1, client->adapter->name); 192 180 193 - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); 194 - if (sd == NULL) 181 + state = kzalloc(sizeof(struct cs5345_state), GFP_KERNEL); 182 + if (state == NULL) 195 183 return -ENOMEM; 184 + sd = &state->sd; 196 185 v4l2_i2c_subdev_init(sd, client, &cs5345_ops); 186 + 187 + v4l2_ctrl_handler_init(&state->hdl, 2); 188 + v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops, 189 + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); 190 + v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops, 191 + V4L2_CID_AUDIO_VOLUME, -24, 24, 1, 0); 192 + sd->ctrl_handler = &state->hdl; 193 + if (state->hdl.error) { 194 + int err = state->hdl.error; 195 + 196 + v4l2_ctrl_handler_free(&state->hdl); 197 + kfree(state); 198 + return err; 199 + } 200 + /* set volume/mute */ 201 + v4l2_ctrl_handler_setup(&state->hdl); 197 202 198 203 cs5345_write(sd, 0x02, 0x00); 199 204 cs5345_write(sd, 0x04, 0x01); ··· 223 194 static int cs5345_remove(struct i2c_client *client) 224 195 { 225 196 struct v4l2_subdev *sd = i2c_get_clientdata(client); 197 + struct cs5345_state *state = to_state(sd); 226 198 227 199 v4l2_device_unregister_subdev(sd); 228 - kfree(sd); 200 + v4l2_ctrl_handler_free(&state->hdl); 201 + kfree(state); 229 202 return 0; 230 203 } 231 204