diff options
Diffstat (limited to 'drivers/media/usb/cx231xx')
-rw-r--r-- | drivers/media/usb/cx231xx/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-417.c | 33 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-cards.c | 144 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-core.c | 13 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-dvb.c | 71 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-video.c | 176 | ||||
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx.h | 21 |
7 files changed, 352 insertions, 107 deletions
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 173c0e287a08..0cced3e5b040 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -47,6 +47,7 @@ config VIDEO_CX231XX_DVB select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 3f295b4d1a3d..983ea8339154 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1868,13 +1868,9 @@ void cx231xx_417_unregister(struct cx231xx *dev) dprintk(1, "%s()\n", __func__); dprintk(3, "%s()\n", __func__); - if (dev->v4l_device) { - if (-1 != dev->v4l_device->minor) - video_unregister_device(dev->v4l_device); - else - video_device_release(dev->v4l_device); + if (video_is_registered(&dev->v4l_device)) { + video_unregister_device(&dev->v4l_device); v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl); - dev->v4l_device = NULL; } } @@ -1911,25 +1907,21 @@ static struct cx2341x_handler_ops cx231xx_ops = { .s_video_encoding = cx231xx_s_video_encoding, }; -static struct video_device *cx231xx_video_dev_alloc( +static void cx231xx_video_dev_init( struct cx231xx *dev, struct usb_device *usbdev, - struct video_device *template, - char *type) + struct video_device *vfd, + const struct video_device *template, + const char *type) { - struct video_device *vfd; - dprintk(1, "%s()\n", __func__); - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; *vfd = *template; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx231xx_boards[dev->model].name); vfd->v4l2_dev = &dev->v4l2_dev; vfd->lock = &dev->lock; - vfd->release = video_device_release; + vfd->release = video_device_release_empty; vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl; video_set_drvdata(vfd, dev); if (dev->tuner_type == TUNER_ABSENT) { @@ -1938,9 +1930,6 @@ static struct video_device *cx231xx_video_dev_alloc( v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); } - - return vfd; - } int cx231xx_417_register(struct cx231xx *dev) @@ -1983,9 +1972,9 @@ int cx231xx_417_register(struct cx231xx *dev) cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, false); /* Allocate and initialize V4L video device */ - dev->v4l_device = cx231xx_video_dev_alloc(dev, - dev->udev, &cx231xx_mpeg_template, "mpeg"); - err = video_register_device(dev->v4l_device, + cx231xx_video_dev_init(dev, dev->udev, + &dev->v4l_device, &cx231xx_mpeg_template, "mpeg"); + err = video_register_device(&dev->v4l_device, VFL_TYPE_GRABBER, -1); if (err < 0) { dprintk(3, "%s: can't register mpeg device\n", dev->name); @@ -1994,7 +1983,7 @@ int cx231xx_417_register(struct cx231xx *dev) } dprintk(3, "%s: registered device video%d [mpeg]\n", - dev->name, dev->v4l_device->num); + dev->name, dev->v4l_device.num); return 0; } diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index da03733690bd..fe00da105e77 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -776,6 +776,45 @@ struct cx231xx_board cx231xx_boards[] = { .gpio = NULL, } }, }, + [CX231XX_BOARD_HAUPPAUGE_955Q] = { + .name = "Hauppauge WinTV-HVR-955Q (111401)", + .tuner_type = TUNER_ABSENT, + .tuner_addr = 0x60, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .output_mode = OUT_MODE_VIP11, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = I2C_1_MUX_3, + .demod_i2c_master = I2C_2, + .has_dvb = 1, + .demod_addr = 0x0e, + .norm = V4L2_STD_NTSC, + + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = NULL, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = NULL, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = NULL, + } }, + }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); @@ -805,6 +844,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, {USB_DEVICE(0x2040, 0xb120), .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, + {USB_DEVICE(0x2040, 0xb123), + .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q}, {USB_DEVICE(0x2040, 0xb130), .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx}, {USB_DEVICE(0x2040, 0xb131), @@ -912,9 +953,6 @@ static inline void cx231xx_set_model(struct cx231xx *dev) */ void cx231xx_pre_card_setup(struct cx231xx *dev) { - - cx231xx_set_model(dev); - dev_info(dev->dev, "Identified as %s (card=%d)\n", dev->board.name, dev->model); @@ -1052,6 +1090,7 @@ void cx231xx_card_setup(struct cx231xx *dev) switch (dev->model) { case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: + case CX231XX_BOARD_HAUPPAUGE_955Q: { struct tveeprom tvee; static u8 eeprom[256]; @@ -1092,6 +1131,17 @@ void cx231xx_config_i2c(struct cx231xx *dev) call_all(dev, video, s_stream, 1); } +static void cx231xx_unregister_media_device(struct cx231xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + if (dev->media_dev) { + media_device_unregister(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; + } +#endif +} + /* * cx231xx_realease_resources() * unregisters the v4l2,i2c and usb devices @@ -1099,6 +1149,8 @@ void cx231xx_config_i2c(struct cx231xx *dev) */ void cx231xx_release_resources(struct cx231xx *dev) { + cx231xx_unregister_media_device(dev); + cx231xx_release_analog_resources(dev); cx231xx_remove_from_devlist(dev); @@ -1117,6 +1169,74 @@ void cx231xx_release_resources(struct cx231xx *dev) clear_bit(dev->devno, &cx231xx_devused); } +static void cx231xx_media_device_register(struct cx231xx *dev, + struct usb_device *udev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev; + int ret; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return; + + mdev->dev = dev->dev; + strlcpy(mdev->model, dev->board.name, sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + strcpy(mdev->bus_info, udev->devpath); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + ret = media_device_register(mdev); + if (ret) { + dev_err(dev->dev, + "Couldn't create a media device. Error: %d\n", + ret); + kfree(mdev); + return; + } + + dev->media_dev = mdev; +#endif +} + +static void cx231xx_create_media_graph(struct cx231xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct media_entity *entity; + struct media_entity *tuner = NULL, *decoder = NULL; + + if (!mdev) + return; + + media_device_for_each_entity(entity, mdev) { + switch (entity->type) { + case MEDIA_ENT_T_V4L2_SUBDEV_TUNER: + tuner = entity; + break; + case MEDIA_ENT_T_V4L2_SUBDEV_DECODER: + decoder = entity; + break; + } + } + + /* Analog setup, using tuner as a link */ + + if (!decoder) + return; + + if (tuner) + media_entity_create_link(tuner, 0, decoder, 0, + MEDIA_LNK_FL_ENABLED); + media_entity_create_link(decoder, 1, &dev->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + media_entity_create_link(decoder, 2, &dev->vbi_dev.entity, 0, + MEDIA_LNK_FL_ENABLED); +#endif +} + /* * cx231xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device @@ -1225,10 +1345,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, } retval = cx231xx_register_analog_devices(dev); - if (retval) { - cx231xx_release_analog_resources(dev); + if (retval) goto err_analog; - } cx231xx_ir_init(dev); @@ -1236,6 +1354,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, return 0; err_analog: + cx231xx_unregister_media_device(dev); + cx231xx_release_analog_resources(dev); cx231xx_remove_from_devlist(dev); err_dev_init: cx231xx_dev_uninit(dev); @@ -1438,6 +1558,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, dev->video_mode.alt = -1; dev->dev = d; + cx231xx_set_model(dev); + dev->interface_count++; /* reset gpio dir and value */ dev->gpio_dir = 0; @@ -1502,7 +1624,13 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); + /* Register the media controller */ + cx231xx_media_device_register(dev, udev); + /* Create v4l2 device */ +#ifdef CONFIG_MEDIA_CONTROLLER + dev->v4l2_dev.mdev = dev->media_dev; +#endif retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { dev_err(d, "v4l2_device_register failed\n"); @@ -1568,6 +1696,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* load other modules required */ request_modules(dev); + cx231xx_create_media_graph(dev); + return 0; err_video_alt: /* cx231xx_uninit_dev: */ @@ -1618,7 +1748,7 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (dev->users) { dev_warn(dev->dev, "device %s is open! Deregistration and memory deallocation are deferred on close.\n", - video_device_node_name(dev->vdev)); + video_device_node_name(&dev->vdev)); /* Even having users, it is safe to remove the RC i2c driver */ cx231xx_ir_exit(dev); diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index 4a3f28c4e8d3..e42bde081cd7 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c @@ -176,16 +176,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, saddr_len = req_data->saddr_len; /* Set wValue */ - if (saddr_len == 1) /* need check saddr_len == 0 */ - ven_req.wValue = - req_data-> - dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 | - _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; - else - ven_req.wValue = - req_data-> - dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 | - _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; + ven_req.wValue = (req_data->dev_addr << 9 | _i2c_period << 4 | + saddr_len << 2 | _i2c_nostop << 1 | I2C_SYNC | + _i2c_reserve << 6); /* set channel number */ if (req_data->direction & I2C_M_RD) { diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index dd600b994e69..610d5675bde6 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -34,6 +34,7 @@ #include "si2165.h" #include "mb86a20s.h" #include "si2157.h" +#include "lgdt3306a.h" MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); @@ -160,6 +161,18 @@ static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = { .ref_freq_Hz = 24000000, }; +static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { + .i2c_addr = 0x59, + .qam_if_khz = 4000, + .vsb_if_khz = 3250, + .deny_i2c_rptr = 1, + .spectral_inversion = 1, + .mpeg_mode = LGDT3306A_MPEG_SERIAL, + .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, + .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, + .xtalMHz = 25, +}; + static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -455,6 +468,7 @@ static int register_dvb(struct cx231xx_dvb *dvb, mutex_init(&dvb->lock); + /* register adapter */ result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, adapter_nr); @@ -464,6 +478,7 @@ static int register_dvb(struct cx231xx_dvb *dvb, dev->name, result); goto fail_adapter; } + dvb_register_media_controller(&dvb->adapter, dev->media_dev); /* Ensure all frontends negotiate bus access */ dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; @@ -536,6 +551,8 @@ static int register_dvb(struct cx231xx_dvb *dvb, /* register network adapter */ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + dvb_create_media_graph(&dvb->adapter); + return 0; fail_fe_conn: @@ -807,7 +824,61 @@ static int dvb_init(struct cx231xx *dev) dev->dvb->i2c_client_tuner = client; break; } + case CX231XX_BOARD_HAUPPAUGE_955Q: + { + struct i2c_client *client; + struct i2c_board_info info; + struct si2157_config si2157_config; + + memset(&info, 0, sizeof(struct i2c_board_info)); + + dev->dvb->frontend = dvb_attach(lgdt3306a_attach, + &hauppauge_955q_lgdt3306a_config, + tuner_i2c + ); + + if (dev->dvb->frontend == NULL) { + dev_err(dev->dev, + "Failed to attach LGDT3306A frontend.\n"); + result = -EINVAL; + goto out_free; + } + + dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = dev->dvb->frontend; + si2157_config.inversion = true; + strlcpy(info.type, "si2157", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module("si2157"); + client = i2c_new_device( + tuner_i2c, + &info); + if (client == NULL || client->dev.driver == NULL) { + dvb_frontend_detach(dev->dvb->frontend); + result = -ENODEV; + goto out_free; + } + + if (!try_module_get(client->dev.driver->owner)) { + i2c_unregister_device(client); + dvb_frontend_detach(dev->dvb->frontend); + result = -ENODEV; + goto out_free; + } + + dev->cx231xx_reset_analog_tuner = NULL; + + dev->dvb->i2c_client_tuner = client; + break; + } case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index ecea76fe07f6..c261e160c158 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -100,6 +100,75 @@ static struct cx231xx_fmt format[] = { }; +static int cx231xx_enable_analog_tuner(struct cx231xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct media_entity *entity, *decoder = NULL, *source; + struct media_link *link, *found_link = NULL; + int i, ret, active_links = 0; + + if (!mdev) + return 0; + + /* + * This will find the tuner that is connected into the decoder. + * Technically, this is not 100% correct, as the device may be + * using an analog input instead of the tuner. However, as we can't + * do DVB streaming while the DMA engine is being used for V4L2, + * this should be enough for the actual needs. + */ + media_device_for_each_entity(entity, mdev) { + if (entity->type == MEDIA_ENT_T_V4L2_SUBDEV_DECODER) { + decoder = entity; + break; + } + } + if (!decoder) + return 0; + + for (i = 0; i < decoder->num_links; i++) { + link = &decoder->links[i]; + if (link->sink->entity == decoder) { + found_link = link; + if (link->flags & MEDIA_LNK_FL_ENABLED) + active_links++; + break; + } + } + + if (active_links == 1 || !found_link) + return 0; + + source = found_link->source->entity; + for (i = 0; i < source->num_links; i++) { + struct media_entity *sink; + int flags = 0; + + link = &source->links[i]; + sink = link->sink->entity; + + if (sink == entity) + flags = MEDIA_LNK_FL_ENABLED; + + ret = media_entity_setup_link(link, flags); + if (ret) { + dev_err(dev->dev, + "Couldn't change link %s->%s to %s. Error %d\n", + source->name, sink->name, + flags ? "enabled" : "disabled", + ret); + return ret; + } else + dev_dbg(dev->dev, + "link %s->%s was %s\n", + source->name, sink->name, + flags ? "ENABLED" : "disabled"); + } +#endif + return 0; +} + /* ------------------------------------------------------------------ Video buffer and parser functions ------------------------------------------------------------------*/ @@ -667,6 +736,9 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) if (*count < CX231XX_MIN_BUF) *count = CX231XX_MIN_BUF; + + cx231xx_enable_analog_tuner(dev); + return 0; } @@ -756,6 +828,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, } buf->vb.state = VIDEOBUF_PREPARED; + return 0; fail: @@ -1056,7 +1129,7 @@ int cx231xx_enum_input(struct file *file, void *priv, (CX231XX_VMUX_CABLE == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; - i->std = dev->vdev->tvnorms; + i->std = dev->vdev.tvnorms; /* If they are asking about the active input, read signal status */ if (n == dev->video_input) { @@ -1451,7 +1524,7 @@ int cx231xx_querycap(struct file *file, void *priv, cap->capabilities = cap->device_caps | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; - if (dev->radio_dev) + if (video_is_registered(&dev->radio_dev)) cap->capabilities |= V4L2_CAP_RADIO; return 0; @@ -1729,34 +1802,21 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) /*FIXME: I2C IR should be disconnected */ - if (dev->radio_dev) { - if (video_is_registered(dev->radio_dev)) - video_unregister_device(dev->radio_dev); - else - video_device_release(dev->radio_dev); - dev->radio_dev = NULL; - } - if (dev->vbi_dev) { + if (video_is_registered(&dev->radio_dev)) + video_unregister_device(&dev->radio_dev); + if (video_is_registered(&dev->vbi_dev)) { dev_info(dev->dev, "V4L2 device %s deregistered\n", - video_device_node_name(dev->vbi_dev)); - if (video_is_registered(dev->vbi_dev)) - video_unregister_device(dev->vbi_dev); - else - video_device_release(dev->vbi_dev); - dev->vbi_dev = NULL; + video_device_node_name(&dev->vbi_dev)); + video_unregister_device(&dev->vbi_dev); } - if (dev->vdev) { + if (video_is_registered(&dev->vdev)) { dev_info(dev->dev, "V4L2 device %s deregistered\n", - video_device_node_name(dev->vdev)); + video_device_node_name(&dev->vdev)); if (dev->board.has_417) cx231xx_417_unregister(dev); - if (video_is_registered(dev->vdev)) - video_unregister_device(dev->vdev); - else - video_device_release(dev->vdev); - dev->vdev = NULL; + video_unregister_device(&dev->vdev); } v4l2_ctrl_handler_free(&dev->ctrl_handler); v4l2_ctrl_handler_free(&dev->radio_ctrl_handler); @@ -2013,7 +2073,7 @@ static struct video_device cx231xx_vbi_template; static const struct video_device cx231xx_video_template = { .fops = &cx231xx_v4l_fops, - .release = video_device_release, + .release = video_device_release_empty, .ioctl_ops = &video_ioctl_ops, .tvnorms = V4L2_STD_ALL, }; @@ -2049,19 +2109,14 @@ static struct video_device cx231xx_radio_template = { /******************************** usb interface ******************************/ -static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, - const struct video_device - *template, const char *type_name) +static void cx231xx_vdev_init(struct cx231xx *dev, + struct video_device *vfd, + const struct video_device *template, + const char *type_name) { - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - *vfd = *template; vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; + vfd->release = video_device_release_empty; vfd->lock = &dev->lock; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); @@ -2073,7 +2128,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER); v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER); } - return vfd; } int cx231xx_register_analog_devices(struct cx231xx *dev) @@ -2116,15 +2170,16 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) /* write code here... */ /* allocate and fill video video_device struct */ - dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video"); - if (!dev->vdev) { - dev_err(dev->dev, "cannot allocate video_device.\n"); - return -ENODEV; - } - - dev->vdev->ctrl_handler = &dev->ctrl_handler; + cx231xx_vdev_init(dev, &dev->vdev, &cx231xx_video_template, "video"); +#if defined(CONFIG_MEDIA_CONTROLLER) + dev->video_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_init(&dev->vdev.entity, 1, &dev->video_pad, 0); + if (ret < 0) + dev_err(dev->dev, "failed to initialize video media entity!\n"); +#endif + dev->vdev.ctrl_handler = &dev->ctrl_handler; /* register v4l2 video video_device */ - ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, + ret = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]); if (ret) { dev_err(dev->dev, @@ -2134,22 +2189,24 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) } dev_info(dev->dev, "Registered video device %s [v4l2]\n", - video_device_node_name(dev->vdev)); + video_device_node_name(&dev->vdev)); /* Initialize VBI template */ cx231xx_vbi_template = cx231xx_video_template; strcpy(cx231xx_vbi_template.name, "cx231xx-vbi"); /* Allocate and fill vbi video_device struct */ - dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi"); + cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi"); - if (!dev->vbi_dev) { - dev_err(dev->dev, "cannot allocate video_device.\n"); - return -ENODEV; - } - dev->vbi_dev->ctrl_handler = &dev->ctrl_handler; +#if defined(CONFIG_MEDIA_CONTROLLER) + dev->vbi_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad, 0); + if (ret < 0) + dev_err(dev->dev, "failed to initialize vbi media entity!\n"); +#endif + dev->vbi_dev.ctrl_handler = &dev->ctrl_handler; /* register v4l2 vbi video_device */ - ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + ret = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]); if (ret < 0) { dev_err(dev->dev, "unable to register vbi device\n"); @@ -2157,18 +2214,13 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) } dev_info(dev->dev, "Registered VBI device %s\n", - video_device_node_name(dev->vbi_dev)); + video_device_node_name(&dev->vbi_dev)); if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { - dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, - "radio"); - if (!dev->radio_dev) { - dev_err(dev->dev, - "cannot allocate video_device.\n"); - return -ENODEV; - } - dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler; - ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, + cx231xx_vdev_init(dev, &dev->radio_dev, + &cx231xx_radio_template, "radio"); + dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler; + ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO, radio_nr[dev->devno]); if (ret < 0) { dev_err(dev->dev, @@ -2176,7 +2228,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) return ret; } dev_info(dev->dev, "Registered radio device as %s\n", - video_device_node_name(dev->radio_dev)); + video_device_node_name(&dev->radio_dev)); } return 0; diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 6d6f3ee812f6..00d3bce9a690 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -76,6 +76,7 @@ #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19 #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20 +#define CX231XX_BOARD_HAUPPAUGE_955Q 21 /* Limits minimum and default number of buffers */ #define CX231XX_MIN_BUF 4 @@ -633,7 +634,7 @@ struct cx231xx { /* video for linux */ int users; /* user count for exclusive use */ - struct video_device *vdev; /* video for linux device struct */ + struct video_device vdev; /* video for linux device struct */ v4l2_std_id norm; /* selected tv norm */ int ctl_freq; /* selected frequency */ unsigned int ctl_ainput; /* selected audio input */ @@ -655,8 +656,13 @@ struct cx231xx { struct mutex ctrl_urb_lock; /* protects urb_buf */ struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; - struct video_device *vbi_dev; - struct video_device *radio_dev; + struct video_device vbi_dev; + struct video_device radio_dev; + +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_device *media_dev; + struct media_pad video_pad, vbi_pad; +#endif unsigned char eedata[256]; @@ -718,7 +724,7 @@ struct cx231xx { u8 USE_ISO; struct cx231xx_tvnorm encodernorm; struct cx231xx_tsport ts1, ts2; - struct video_device *v4l_device; + struct video_device v4l_device; atomic_t v4l_reader_count; u32 freq; unsigned int input; @@ -972,8 +978,11 @@ extern void cx231xx_417_unregister(struct cx231xx *dev); int cx231xx_ir_init(struct cx231xx *dev); void cx231xx_ir_exit(struct cx231xx *dev); #else -#define cx231xx_ir_init(dev) (0) -#define cx231xx_ir_exit(dev) (0) +static inline int cx231xx_ir_init(struct cx231xx *dev) +{ + return 0; +} +static inline void cx231xx_ir_exit(struct cx231xx *dev) {} #endif static inline unsigned int norm_maxw(struct cx231xx *dev) |