diff options
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 1 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 1 | ||||
| -rw-r--r-- | drivers/media/video/ivtv/ivtv-gpio.c | 77 |
3 files changed, 38 insertions, 41 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index f72e9d1cee09..53ea31aab155 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
| @@ -1386,6 +1386,7 @@ static void ivtv_remove(struct pci_dev *pdev) | |||
| 1386 | printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name); | 1386 | printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name); |
| 1387 | 1387 | ||
| 1388 | v4l2_device_unregister(&itv->v4l2_dev); | 1388 | v4l2_device_unregister(&itv->v4l2_dev); |
| 1389 | v4l2_ctrl_handler_free(&itv->hdl_gpio); | ||
| 1389 | kfree(itv); | 1390 | kfree(itv); |
| 1390 | } | 1391 | } |
| 1391 | 1392 | ||
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 102071246218..d2260de4c812 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
| @@ -632,6 +632,7 @@ struct ivtv { | |||
| 632 | 632 | ||
| 633 | struct v4l2_device v4l2_dev; | 633 | struct v4l2_device v4l2_dev; |
| 634 | struct v4l2_subdev sd_gpio; /* GPIO sub-device */ | 634 | struct v4l2_subdev sd_gpio; /* GPIO sub-device */ |
| 635 | struct v4l2_ctrl_handler hdl_gpio; | ||
| 635 | u16 instance; | 636 | u16 instance; |
| 636 | 637 | ||
| 637 | /* High-level state info */ | 638 | /* High-level state info */ |
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index aede061cae5d..8f0d07789053 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "ivtv-gpio.h" | 24 | #include "ivtv-gpio.h" |
| 25 | #include "tuner-xc2028.h" | 25 | #include "tuner-xc2028.h" |
| 26 | #include <media/tuner.h> | 26 | #include <media/tuner.h> |
| 27 | #include <media/v4l2-ctrls.h> | ||
| 27 | 28 | ||
| 28 | /* | 29 | /* |
| 29 | * GPIO assignment of Yuan MPG600/MPG160 | 30 | * GPIO assignment of Yuan MPG600/MPG160 |
| @@ -149,16 +150,10 @@ static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd) | |||
| 149 | return container_of(sd, struct ivtv, sd_gpio); | 150 | return container_of(sd, struct ivtv, sd_gpio); |
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | static struct v4l2_queryctrl gpio_ctrl_mute = { | 153 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) |
| 153 | .id = V4L2_CID_AUDIO_MUTE, | 154 | { |
| 154 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 155 | return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio; |
| 155 | .name = "Mute", | 156 | } |
| 156 | .minimum = 0, | ||
| 157 | .maximum = 1, | ||
| 158 | .step = 1, | ||
| 159 | .default_value = 1, | ||
| 160 | .flags = 0, | ||
| 161 | }; | ||
| 162 | 157 | ||
| 163 | static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | 158 | static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq) |
| 164 | { | 159 | { |
| @@ -262,40 +257,24 @@ static int subdev_s_audio_routing(struct v4l2_subdev *sd, | |||
| 262 | return 0; | 257 | return 0; |
| 263 | } | 258 | } |
| 264 | 259 | ||
| 265 | static int subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 260 | static int subdev_s_ctrl(struct v4l2_ctrl *ctrl) |
| 266 | { | 261 | { |
| 262 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
| 267 | struct ivtv *itv = sd_to_ivtv(sd); | 263 | struct ivtv *itv = sd_to_ivtv(sd); |
| 268 | u16 mask, data; | 264 | u16 mask, data; |
| 269 | 265 | ||
| 270 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) | 266 | switch (ctrl->id) { |
| 271 | return -EINVAL; | 267 | case V4L2_CID_AUDIO_MUTE: |
| 272 | mask = itv->card->gpio_audio_mute.mask; | 268 | mask = itv->card->gpio_audio_mute.mask; |
| 273 | data = itv->card->gpio_audio_mute.mute; | 269 | data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0; |
| 274 | ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; | 270 | if (mask) |
| 275 | return 0; | 271 | write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | |
| 276 | } | 272 | (data & mask), IVTV_REG_GPIO_OUT); |
| 277 | 273 | return 0; | |
| 278 | static int subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 274 | } |
| 279 | { | 275 | return -EINVAL; |
| 280 | struct ivtv *itv = sd_to_ivtv(sd); | ||
| 281 | u16 mask, data; | ||
| 282 | |||
| 283 | if (ctrl->id != V4L2_CID_AUDIO_MUTE) | ||
| 284 | return -EINVAL; | ||
| 285 | mask = itv->card->gpio_audio_mute.mask; | ||
| 286 | data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; | ||
| 287 | if (mask) | ||
| 288 | write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); | ||
| 289 | return 0; | ||
| 290 | } | 276 | } |
| 291 | 277 | ||
| 292 | static int subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
| 293 | { | ||
| 294 | if (qc->id != V4L2_CID_AUDIO_MUTE) | ||
| 295 | return -EINVAL; | ||
| 296 | *qc = gpio_ctrl_mute; | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | 278 | ||
| 300 | static int subdev_log_status(struct v4l2_subdev *sd) | 279 | static int subdev_log_status(struct v4l2_subdev *sd) |
| 301 | { | 280 | { |
| @@ -304,6 +283,7 @@ static int subdev_log_status(struct v4l2_subdev *sd) | |||
| 304 | IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", | 283 | IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", |
| 305 | read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), | 284 | read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), |
| 306 | read_reg(IVTV_REG_GPIO_IN)); | 285 | read_reg(IVTV_REG_GPIO_IN)); |
| 286 | v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name); | ||
| 307 | return 0; | 287 | return 0; |
| 308 | } | 288 | } |
| 309 | 289 | ||
| @@ -327,11 +307,19 @@ static int subdev_s_video_routing(struct v4l2_subdev *sd, | |||
| 327 | return 0; | 307 | return 0; |
| 328 | } | 308 | } |
| 329 | 309 | ||
| 310 | static const struct v4l2_ctrl_ops gpio_ctrl_ops = { | ||
| 311 | .s_ctrl = subdev_s_ctrl, | ||
| 312 | }; | ||
| 313 | |||
| 330 | static const struct v4l2_subdev_core_ops subdev_core_ops = { | 314 | static const struct v4l2_subdev_core_ops subdev_core_ops = { |
| 331 | .log_status = subdev_log_status, | 315 | .log_status = subdev_log_status, |
| 332 | .g_ctrl = subdev_g_ctrl, | 316 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
| 333 | .s_ctrl = subdev_s_ctrl, | 317 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, |
| 334 | .queryctrl = subdev_queryctrl, | 318 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, |
| 319 | .g_ctrl = v4l2_subdev_g_ctrl, | ||
| 320 | .s_ctrl = v4l2_subdev_s_ctrl, | ||
| 321 | .queryctrl = v4l2_subdev_queryctrl, | ||
| 322 | .querymenu = v4l2_subdev_querymenu, | ||
| 335 | }; | 323 | }; |
| 336 | 324 | ||
| 337 | static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { | 325 | static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { |
| @@ -375,5 +363,12 @@ int ivtv_gpio_init(struct ivtv *itv) | |||
| 375 | v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); | 363 | v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); |
| 376 | snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name); | 364 | snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name); |
| 377 | itv->sd_gpio.grp_id = IVTV_HW_GPIO; | 365 | itv->sd_gpio.grp_id = IVTV_HW_GPIO; |
| 366 | v4l2_ctrl_handler_init(&itv->hdl_gpio, 1); | ||
| 367 | v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops, | ||
| 368 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); | ||
| 369 | if (itv->hdl_gpio.error) | ||
| 370 | return itv->hdl_gpio.error; | ||
| 371 | itv->sd_gpio.ctrl_handler = &itv->hdl_gpio; | ||
| 372 | v4l2_ctrl_handler_setup(&itv->hdl_gpio); | ||
| 378 | return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio); | 373 | return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio); |
| 379 | } | 374 | } |
