From patchwork Wed Jan 9 13:41:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prabhakar X-Patchwork-Id: 1952771 Return-Path: X-Original-To: patchwork-davinci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by patchwork1.kernel.org (Postfix) with ESMTP id D11663FC5A for ; Wed, 9 Jan 2013 13:46:05 +0000 (UTC) Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id r09Dg1ZI024759; Wed, 9 Jan 2013 07:42:01 -0600 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id r09Dg1dD013456; Wed, 9 Jan 2013 07:42:01 -0600 Received: from dlelxv23.itg.ti.com (172.17.1.198) by dfle72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.1.323.3; Wed, 9 Jan 2013 07:42:00 -0600 Received: from linux.omap.com (dlelxs01.itg.ti.com [157.170.227.31]) by dlelxv23.itg.ti.com (8.13.8/8.13.8) with ESMTP id r09Dg02d001717; Wed, 9 Jan 2013 07:42:00 -0600 Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 6DB9980628; Wed, 9 Jan 2013 07:42:00 -0600 (CST) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp52.itg.ti.com (dflp52.itg.ti.com [128.247.22.96]) by linux.omap.com (Postfix) with ESMTP id 35BED80626 for ; Wed, 9 Jan 2013 07:41:59 -0600 (CST) Received: from medina.ext.ti.com (medina.ext.ti.com [192.91.81.31]) by dflp52.itg.ti.com (8.13.7/8.13.8) with ESMTP id r09DfxQr026119 for ; Wed, 9 Jan 2013 07:41:59 -0600 (CST) Received: from psmtp.com (na3sys009amx231.postini.com [74.125.149.115]) by medina.ext.ti.com (8.13.7/8.13.7) with SMTP id r09Dfwjq008125 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 9 Jan 2013 07:41:58 -0600 Received: from mail-pb0-f44.google.com ([209.85.160.44]) (using TLSv1) by na3sys009amx231.postini.com ([74.125.148.10]) with SMTP; Wed, 09 Jan 2013 13:41:58 GMT Received: by mail-pb0-f44.google.com with SMTP id uo1so962192pbc.3 for ; Wed, 09 Jan 2013 05:41:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=1QxvUwezyyyT2Ktk+295AfvYijxEl9xtSJlXMRI6B6A=; b=awOb4yyvFdmhu5c5IViBdCcb8hPGtD/doBuJHPQkWJ3plG0llzSFT7mSnbgIAMWnzG vlTLzkcpP1zk+WrkF1MeDEt1DUe4rgspgXCQFEyDC1ipjKeF0Q0kB6KdhGCcwvFAJ9eH v2QXZ2ZlblDTAXruIVNmisyOC0gt7LhXuwgp2U1jqPghFUvuck30E/Y1igUSUla6UXe2 8lgaUjP4NN9JQQxsV5/Aq3jUy6HRHeTgXP2fmsNJ6VoQ/7DkZHS8+dKV2ioSjhKNh9nD KYerFC6E9X7rdF9RxD5GTyDr0FasBXlzRLCi9ThPlZhrk6YvAkojN1q0BVZH5rjnjgzH /vFQ== X-Received: by 10.68.129.40 with SMTP id nt8mr209417118pbb.113.1357738917586; Wed, 09 Jan 2013 05:41:57 -0800 (PST) Received: from localhost.localdomain ([122.166.13.141]) by mx.google.com with ESMTPS id k4sm42842184paz.26.2013.01.09.05.41.51 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 09 Jan 2013 05:41:56 -0800 (PST) From: "Lad, Prabhakar" To: LMML Subject: [PATCH RFC 1/3] davinci: vpif: capture: add V4L2-async support Date: Wed, 9 Jan 2013 19:11:25 +0530 Message-ID: <1357738887-8701-2-git-send-email-prabhakar.lad@ti.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1357738887-8701-1-git-send-email-prabhakar.lad@ti.com> References: <1357738887-8701-1-git-send-email-prabhakar.lad@ti.com> X-pstn-neptune: 0/0/0.00/0 X-pstn-levels: (S:59.16647/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) X-pstn-dkim: 1 skipped:no-policies X-pstn-settings: 2 (0.5000:0.0050) s cv GT3 gt2 gt1 r p m c X-pstn-addresses: from [82/3] CC: DLOS , Mauro Carvalho Chehab , LKML , Mauro Carvalho Chehab , Hans Verkuil , Sakari Ailus , Guennadi Liakhovetski , LAK X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com Add support for asynchronous subdevice probing, using the v4l2-async API. The legacy synchronous mode is still supported too, which allows to gradually update drivers and platforms. The selected approach adds a notifier for each struct soc_camera_device instance, i.e. for each video device node, even when there are multiple such instances registered with a single soc-camera host simultaneously. Signed-off-by: Lad, Prabhakar Cc: Guennadi Liakhovetski Cc: Hans Verkuil Cc: Laurent Pinchart Cc: Sakari Ailus Cc: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 171 ++++++++++++++++++------- drivers/media/platform/davinci/vpif_capture.h | 2 + include/media/davinci/vpif_types.h | 2 + 3 files changed, 128 insertions(+), 47 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 5892d2b..a8b6588 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -34,6 +34,8 @@ #include #include #include + +#include #include #include #include @@ -2054,6 +2056,96 @@ vpif_init_free_channel_objects: return err; } +int vpif_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev_list *asdl) +{ + int i = 0; + + if (!asdl->subdev) { + v4l2_err(vpif_dev->driver, + "%s(): Subdevice driver hasn't set subdev pointer!\n", + __func__); + return -EINVAL; + } + v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", + asdl->subdev->name); + + for (i = 0; i < vpif_obj.config->subdev_count; i++) + if (!strcmp(vpif_obj.config->subdev_info[i].name, + asdl->subdev->name)) { + vpif_obj.sd[i] = asdl->subdev; + break; + } + + if (i >= vpif_obj.config->subdev_count) + return -EINVAL; + + return 0; +} + +static int vpif_probe_complete(void) +{ + struct common_obj *common; + struct channel_obj *ch; + int i, j, err, k; + + for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { + ch = vpif_obj.dev[j]; + ch->channel_id = j; + common = &(ch->common[VPIF_VIDEO_INDEX]); + spin_lock_init(&common->irqlock); + mutex_init(&common->lock); + ch->video_dev->lock = &common->lock; + /* Initialize prio member of channel object */ + v4l2_prio_init(&ch->prio); + video_set_drvdata(ch->video_dev, ch); + + /* select input 0 */ + err = vpif_set_input(vpif_obj.config, ch, 0); + if (err) + goto probe_out; + + err = video_register_device(ch->video_dev, + VFL_TYPE_GRABBER, (j ? 1 : 0)); + if (err) + goto probe_out; + } + + v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); + return 0; + +probe_out: + for (k = 0; k < j; k++) { + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[k]; + /* Unregister video device */ + video_unregister_device(ch->video_dev); + } + kfree(vpif_obj.sd); + for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { + ch = vpif_obj.dev[i]; + /* Note: does nothing if ch->video_dev == NULL */ + video_device_release(ch->video_dev); + } + v4l2_device_unregister(&vpif_obj.v4l2_dev); + + return err; +} + +int vpif_async_complete(struct v4l2_async_notifier *notifier) +{ + return vpif_probe_complete(); +} + +void vpif_async_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev_list *asdl) +{ + /*FIXME: Do we need this callback ? */ + v4l2_info(&vpif_obj.v4l2_dev, "unregistered sub device %s\n", + asdl->subdev->name); + return; +} + /** * vpif_probe : This function probes the vpif capture driver * @pdev: platform device pointer @@ -2064,12 +2156,10 @@ vpif_init_free_channel_objects: static __init int vpif_probe(struct platform_device *pdev) { struct vpif_subdev_info *subdevdata; - struct vpif_capture_config *config; - int i, j, k, err; + int i, j, err; int res_idx = 0; struct i2c_adapter *i2c_adap; struct channel_obj *ch; - struct common_obj *common; struct video_device *vfd; struct resource *res; int subdev_count; @@ -2146,10 +2236,9 @@ static __init int vpif_probe(struct platform_device *pdev) } } - i2c_adap = i2c_get_adapter(1); - config = pdev->dev.platform_data; + vpif_obj.config = pdev->dev.platform_data; - subdev_count = config->subdev_count; + subdev_count = vpif_obj.config->subdev_count; vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, GFP_KERNEL); if (vpif_obj.sd == NULL) { @@ -2158,53 +2247,41 @@ static __init int vpif_probe(struct platform_device *pdev) goto vpif_sd_error; } - for (i = 0; i < subdev_count; i++) { - subdevdata = &config->subdev_info[i]; - vpif_obj.sd[i] = - v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, - i2c_adap, - &subdevdata->board_info, - NULL); + if (!vpif_obj.config->asd_sizes) { + i2c_adap = i2c_get_adapter(1); + for (i = 0; i < subdev_count; i++) { + subdevdata = &vpif_obj.config->subdev_info[i]; + vpif_obj.sd[i] = + v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, + i2c_adap, + &subdevdata->board_info, + NULL); - if (!vpif_obj.sd[i]) { - vpif_err("Error registering v4l2 subdevice\n"); - goto probe_subdev_out; + if (!vpif_obj.sd[i]) { + vpif_err("Error registering v4l2 subdevice\n"); + goto probe_subdev_out; + } + v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", + subdevdata->name); + } + vpif_probe_complete(); + } else { + vpif_obj.notifier.subdev = vpif_obj.config->asd; + vpif_obj.notifier.subdev_num = vpif_obj.config->asd_sizes[0]; + vpif_obj.notifier.bound = vpif_async_bound; + vpif_obj.notifier.complete = vpif_async_complete; + vpif_obj.notifier.unbind = vpif_async_unbind; + err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, + &vpif_obj.notifier); + if (err) { + vpif_err("Error registering async notifier\n"); + err = -EINVAL; + goto vpif_sd_error; } - v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", - subdevdata->name); } - for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { - ch = vpif_obj.dev[j]; - ch->channel_id = j; - common = &(ch->common[VPIF_VIDEO_INDEX]); - spin_lock_init(&common->irqlock); - mutex_init(&common->lock); - ch->video_dev->lock = &common->lock; - /* Initialize prio member of channel object */ - v4l2_prio_init(&ch->prio); - video_set_drvdata(ch->video_dev, ch); - - /* select input 0 */ - err = vpif_set_input(config, ch, 0); - if (err) - goto probe_out; - - err = video_register_device(ch->video_dev, - VFL_TYPE_GRABBER, (j ? 1 : 0)); - if (err) - goto probe_out; - } - v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); return 0; -probe_out: - for (k = 0; k < j; k++) { - /* Get the pointer to the channel object */ - ch = vpif_obj.dev[k]; - /* Unregister video device */ - video_unregister_device(ch->video_dev); - } probe_subdev_out: /* free sub devices memory */ kfree(vpif_obj.sd); diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 3d3c1e5..1be47ab 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -145,6 +145,8 @@ struct vpif_device { struct v4l2_device v4l2_dev; struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; struct v4l2_subdev **sd; + struct v4l2_async_notifier notifier; + struct vpif_capture_config *config; }; struct vpif_config_params { diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h index 3882e06..e08bcde 100644 --- a/include/media/davinci/vpif_types.h +++ b/include/media/davinci/vpif_types.h @@ -81,5 +81,7 @@ struct vpif_capture_config { struct vpif_subdev_info *subdev_info; int subdev_count; const char *card_name; + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ + int *asd_sizes; /* 0-terminated array of asd group sizes */ }; #endif /* _VPIF_TYPES_H */