From 3d3fd89aabd81c1e33baf3dcf16329457cd82c77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 21:02:10 +0100 Subject: v4l2-device: add a notify callback. From: Hans Verkuil Add a notify callback to v4l2_device to let sub-devices notify their parent of special events. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 10 ++++++++++ linux/include/media/v4l2-device.h | 3 +++ linux/include/media/v4l2-subdev.h | 5 +++++ 3 files changed, 18 insertions(+) (limited to 'linux') diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index accc376e9..1232f3066 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -93,6 +93,11 @@ The first 'dev' argument is normally the struct device pointer of a pci_dev, usb_device or platform_device. It is rare for dev to be NULL, but it happens with ISA devices, for example. +You can also supply a notify() callback that can be called by sub-devices to +notify you of events. Whether you need to set this depends on the sub-device. +Any notifications a sub-device supports must be defined in a header in +include/media/.h. + You unregister with: v4l2_device_unregister(struct v4l2_device *v4l2_dev); @@ -280,6 +285,11 @@ e.g. AUDIO_CONTROLLER and specify that as the group ID value when calling v4l2_device_call_all(). That ensures that it will only go to the subdev that needs it. +If the sub-device needs to notify its v4l2_device parent of an event, then +it can call v4l2_subdev_notify(sd, notification, arg). This macro checks +whether there is a notify() callback defined and returns -ENODEV if not. +Otherwise the result of the notify() call is returned. + The advantage of using v4l2_subdev is that it is a generic struct and does not contain any knowledge about the underlying hardware. So a driver might contain several subdevs that use an I2C bus, but also a subdev that is diff --git a/linux/include/media/v4l2-device.h b/linux/include/media/v4l2-device.h index 5d7146dc2..3d8e96f6c 100644 --- a/linux/include/media/v4l2-device.h +++ b/linux/include/media/v4l2-device.h @@ -44,6 +44,9 @@ struct v4l2_device { spinlock_t lock; /* unique device name, by default the driver name + bus ID */ char name[V4L2_DEVICE_NAME_SIZE]; + /* notify callback called by some sub-devices. */ + void (*notify)(struct v4l2_subdev *sd, + unsigned int notification, void *arg); }; /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev. diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index 05b69652e..1b97a2c33 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -191,4 +191,9 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd, (!(sd) ? -ENODEV : (((sd) && (sd)->ops->o && (sd)->ops->o->f) ? \ (sd)->ops->o->f((sd) , ##args) : -ENOIOCTLCMD)) +/* Send a notification to v4l2_device. */ +#define v4l2_subdev_notify(sd, notification, arg) \ + ((!(sd) || !(sd)->v4l2_dev || !(sd)->v4l2_dev->notify) ? -ENODEV : \ + (sd)->v4l2_dev->notify((sd), (notification), (arg))) + #endif -- cgit v1.2.3 From 70e434a0770289c85c4cf61a2956160e24d76bcf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 21:04:38 +0100 Subject: zoran/bt819: use new notify functionality. From: Hans Verkuil Bt819 needs the parent driver to drive a GPIO pin low and high in order to reset its fifo. Use the new notify callback for this. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt819.c | 14 +++++++++- linux/drivers/media/video/zoran/zoran_card.c | 22 +++++++++++++--- linux/drivers/media/video/zoran/zoran_device.c | 36 ++------------------------ linux/drivers/media/video/zoran/zoran_device.h | 3 --- linux/drivers/media/video/zoran/zoran_driver.c | 12 ++++----- linux/include/media/bt819.h | 33 +++++++++++++++++++++++ 6 files changed, 72 insertions(+), 48 deletions(-) create mode 100644 linux/include/media/bt819.h (limited to 'linux') diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index ec64197e9..a024783e5 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -32,13 +32,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include #include "compat.h" MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); @@ -256,7 +257,11 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) + v4l2_err(sd, "no notify found!\n"); + if (std & V4L2_STD_NTSC) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); bt819_setbit(decoder, 0x01, 0, 1); bt819_setbit(decoder, 0x01, 1, 0); bt819_setbit(decoder, 0x01, 5, 0); @@ -265,6 +270,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* bt819_setbit(decoder, 0x1a, 5, 1); */ timing = &timing_data[1]; } else if (std & V4L2_STD_PAL) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); bt819_setbit(decoder, 0x01, 0, 1); bt819_setbit(decoder, 0x01, 1, 1); bt819_setbit(decoder, 0x01, 5, 1); @@ -288,6 +294,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); bt819_write(decoder, 0x09, timing->hscale & 0xff); decoder->norm = std; + v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); return 0; } @@ -300,7 +307,11 @@ static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro if (route->input < 0 || route->input > 7) return -EINVAL; + if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) + v4l2_err(sd, "no notify found!\n"); + if (decoder->input != route->input) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); decoder->input = route->input; /* select mode */ if (decoder->input == 0) { @@ -310,6 +321,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro bt819_setbit(decoder, 0x0b, 6, 1); bt819_setbit(decoder, 0x1a, 1, 0); } + v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); } return 0; } diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 57cc62d82..4bd73d3ae 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -38,9 +38,7 @@ #include #include #include -#include "compat.h" #include -#include #include #include #include @@ -49,8 +47,10 @@ #include #include #include - -#include +#include +#include +#include +#include "compat.h" #include "videocodec.h" #include "zoran.h" @@ -1201,6 +1201,19 @@ zoran_setup_videocodec (struct zoran *zr, return m; } +static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct zoran *zr = to_zoran(sd->v4l2_dev); + + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (cmd == BT819_FIFO_RESET_LOW) + GPIO(zr, 7, 0); + else if (cmd == BT819_FIFO_RESET_HIGH) + GPIO(zr, 7, 1); + return 0; +} + /* * Scan for a Buz card (actually for the PCI controller ZR36057), * request the irq and map the io memory @@ -1235,6 +1248,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZORAN_NAME); return -ENOMEM; } + zr->v4l2_dev.notify = zoran_subdev_notify; if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) goto zr_free_mem; zr->pci_dev = pdev; diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index c2dfd4b67..409e0d5e1 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -1594,8 +1594,8 @@ zoran_init_hardware (struct zoran *zr) route.input = zr->card.input[zr->input].muxsel; decoder_call(zr, core, init, 0); - decoder_s_std(zr, zr->norm); - decoder_s_routing(zr, &route); + decoder_call(zr, tuner, s_std, zr->norm); + decoder_call(zr, video, s_routing, &route); encoder_call(zr, core, init, 0); encoder_call(zr, video, s_std_output, zr->norm); @@ -1660,35 +1660,3 @@ zr36057_init_vfe (struct zoran *zr) reg |= ZR36057_VDCR_Triton; btwrite(reg, ZR36057_VDCR); } - -/* - * Interface to decoder and encoder chips using i2c bus - */ - -int decoder_s_std(struct zoran *zr, v4l2_std_id std) -{ - int res; - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (zr->card.type == LML33) - GPIO(zr, 7, 0); - res = decoder_call(zr, tuner, s_std, std); - if (zr->card.type == LML33) - GPIO(zr, 7, 1); /* Pull #FRST high. */ - return res; -} - -int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route) -{ - int res; - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (zr->card.type == LML33) - GPIO(zr, 7, 0); - res = decoder_call(zr, video, s_routing, route); - if (zr->card.type == LML33) - GPIO(zr, 7, 1); /* Pull #FRST high. */ - return res; -} diff --git a/linux/drivers/media/video/zoran/zoran_device.h b/linux/drivers/media/video/zoran/zoran_device.h index 2eb645904..72d691567 100644 --- a/linux/drivers/media/video/zoran/zoran_device.h +++ b/linux/drivers/media/video/zoran/zoran_device.h @@ -98,7 +98,4 @@ extern int pass_through; #define encoder_call(zr, o, f, args...) \ v4l2_subdev_call(zr->encoder, o, f, ##args) -int decoder_s_std(struct zoran *zr, v4l2_std_id std); -int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route); - #endif /* __ZORAN_DEVICE_H__ */ diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 8eda83b06..e7b0aba57 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1525,7 +1525,7 @@ zoran_set_norm (struct zoran *zr, v4l2_std_id std = 0; decoder_call(zr, video, querystd, &std); - decoder_s_std(zr, std); + decoder_call(zr, tuner, s_std, std); /* let changes come into effect */ ssleep(2); @@ -1537,7 +1537,7 @@ zoran_set_norm (struct zoran *zr, "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ - decoder_s_std(zr, zr->norm); + decoder_call(zr, tuner, s_std, zr->norm); return -EIO; } @@ -1556,7 +1556,7 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_s_std(zr, norm); + decoder_call(zr, tuner, s_std, norm); encoder_call(zr, video, s_std_output, norm); if (on) @@ -1598,7 +1598,7 @@ zoran_set_input (struct zoran *zr, route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); return 0; } @@ -1843,7 +1843,7 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); /* sleep 1 second */ ssleep(1); @@ -1854,7 +1854,7 @@ jpgreqbuf_unlock_and_return: /* restore previous input and norm */ route.input = zr->card.input[zr->input].muxsel; - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); diff --git a/linux/include/media/bt819.h b/linux/include/media/bt819.h new file mode 100644 index 000000000..38f666bde --- /dev/null +++ b/linux/include/media/bt819.h @@ -0,0 +1,33 @@ +/* + bt819.h - bt819 notifications + + Copyright (C) 2009 Hans Verkuil (hverkuil@xs4all.nl) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BT819_H_ +#define _BT819_H_ + +#include + +/* v4l2_device notifications. */ + +/* Needed to reset the FIFO buffer when changing the input + or the video standard. */ +#define BT819_FIFO_RESET_LOW _IO('b', 0) +#define BT819_FIFO_RESET_HIGH _IO('b', 1) + +#endif -- cgit v1.2.3