[GIT,PULL,FOR,3.5] s5p-fimc driver updates

Message ID 4FB17B79.2000207@gmail.com (mailing list archive)
State Rejected, archived
Headers

Commit Message

Sylwester Nawrocki May 14, 2012, 9:39 p.m. UTC
  On 05/10/2012 10:48 AM, Sylwester Nawrocki wrote:
> On 05/04/2012 05:31 PM, Sylwester Nawrocki wrote:
>> Hi Mauro,
>>
>> The following changes since commit 34b2debaa62bfa384ef91b61cf2c40c48e86a5e2:
>>
>>    s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-04 17:07:24 +0200)
>>
>> are available in the git repository at:
>>
>>    git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
>>
>> for you to fetch changes up to bab96b068afa07105139be09d3830cc9ed580382:
>>
>>    s5p-fimc: Use selection API in place of crop operations (2012-05-04 17:18:38 +0200)
> 
> Mauro,
> 
> I've found a few issues in this series afterwards and re-edited 3 commits there.
> Here is an updated pull request:
> 
> The following changes since commit ae45d3e9aea0ab951dbbca2238fbfbf3993f1e7f:
> 
>    s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-09 16:07:49 +0200)
> 
> are available in the git repository at:
> 
>    git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
> 
> for you to fetch changes up to 5feefe6656583de6fd4ef1d53b19031dd5efeec1:
> 
>    s5p-fimc: Use selection API in place of crop operations (2012-05-09 16:11:29 +0200)
> 
> ----------------------------------------------------------------
> Sylwester Nawrocki (14):
>        V4L: Extend V4L2_CID_COLORFX with more image effects
>        s5p-fimc: Avoid crash with null platform_data
>        s5p-fimc: Move m2m node driver into separate file

It seems there is a conflict now with this patch:
http://git.linuxtv.org/media_tree.git/commit/5126f2590bee412e3053de851cb07f531e4be36a

Attached are updated versions of the two conflicting patches, the others 
don't need touching.

I could provide rebased version of the whole change set tomorrow - if needed.

Kind regards,
Sylwester

>        s5p-fimc: Use v4l2_subdev internal ops to register video nodes
>        s5p-fimc: Refactor the register interface functions
>        s5p-fimc: Add FIMC-LITE register definitions
>        s5p-fimc: Rework the video pipeline control functions
>        s5p-fimc: Prefix format enumerations with FIMC_FMT_
>        s5p-fimc: Minor cleanups
>        s5p-fimc: Make sure an interrupt is properly requested
>        s5p-fimc: Add support for Exynos4x12 FIMC-LITE
>        s5p-fimc: Update copyright notices
>        s5p-fimc: Add color effect control
>        s5p-fimc: Use selection API in place of crop operations
  

Comments

Mauro Carvalho Chehab May 20, 2012, 12:39 p.m. UTC | #1
Em 14-05-2012 18:39, Sylwester Nawrocki escreveu:
> On 05/10/2012 10:48 AM, Sylwester Nawrocki wrote:
>> On 05/04/2012 05:31 PM, Sylwester Nawrocki wrote:
>>> Hi Mauro,
>>>
>>> The following changes since commit 34b2debaa62bfa384ef91b61cf2c40c48e86a5e2:
>>>
>>>    s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-04 17:07:24 +0200)
>>>
>>> are available in the git repository at:
>>>
>>>    git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
>>>
>>> for you to fetch changes up to bab96b068afa07105139be09d3830cc9ed580382:
>>>
>>>    s5p-fimc: Use selection API in place of crop operations (2012-05-04 17:18:38 +0200)
>>
>> Mauro,
>>
>> I've found a few issues in this series afterwards and re-edited 3 commits there.
>> Here is an updated pull request:
>>
>> The following changes since commit ae45d3e9aea0ab951dbbca2238fbfbf3993f1e7f:
>>
>>    s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-09 16:07:49 +0200)
>>
>> are available in the git repository at:
>>
>>    git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
>>
>> for you to fetch changes up to 5feefe6656583de6fd4ef1d53b19031dd5efeec1:
>>
>>    s5p-fimc: Use selection API in place of crop operations (2012-05-09 16:11:29 +0200)
>>
>> ----------------------------------------------------------------
>> Sylwester Nawrocki (14):
>>        V4L: Extend V4L2_CID_COLORFX with more image effects
>>        s5p-fimc: Avoid crash with null platform_data
>>        s5p-fimc: Move m2m node driver into separate file
> 
> It seems there is a conflict now with this patch:
> http://git.linuxtv.org/media_tree.git/commit/5126f2590bee412e3053de851cb07f531e4be36a
> 
> Attached are updated versions of the two conflicting patches, the others 
> don't need touching.
> 
> I could provide rebased version of the whole change set tomorrow - if needed.

Please do that, as this patch doesn't apply as-is.

Regards,
Mauro

$ quilt push
Applying patch patches/lmml_11243_git_pull_for_3_5_s5p_fimc_driver_updates.patch
patching file drivers/media/video/s5p-fimc/fimc-capture.c
Hunk #1 FAILED at 993.
Hunk #2 FAILED at 1489.
Hunk #3 FAILED at 1554.
Hunk #4 FAILED at 1572.
Hunk #5 FAILED at 1580.
Hunk #6 FAILED at 1616.
Hunk #7 FAILED at 1636.
7 out of 7 hunks FAILED -- rejects in file drivers/media/video/s5p-fimc/fimc-capture.c
patching file drivers/media/video/s5p-fimc/fimc-core.c
Hunk #1 FAILED at 842.
Hunk #2 FAILED at 851.
Hunk #3 FAILED at 866.
Hunk #4 FAILED at 953.
4 out of 4 hunks FAILED -- rejects in file drivers/media/video/s5p-fimc/fimc-core.c
patching file drivers/media/video/s5p-fimc/fimc-core.h
Hunk #1 FAILED at 331.
Hunk #2 FAILED at 737.
2 out of 2 hunks FAILED -- rejects in file drivers/media/video/s5p-fimc/fimc-core.h
patching file drivers/media/video/s5p-fimc/fimc-m2m.c
Hunk #1 FAILED at 777.
Hunk #2 FAILED at 789.
2 out of 2 hunks FAILED -- rejects in file drivers/media/video/s5p-fimc/fimc-m2m.c
patching file drivers/media/video/s5p-fimc/fimc-mdevice.c
Hunk #1 FAILED at 304.
Hunk #2 FAILED at 313.
Hunk #3 FAILED at 401.
Hunk #4 FAILED at 420.
Hunk #5 FAILED at 479.
Hunk #6 FAILED at 588.
Hunk #7 FAILED at 817.
7 out of 7 hunks FAILED -- rejects in file drivers/media/video/s5p-fimc/fimc-mdevice.c
patching file drivers/media/video/s5p-fimc/fimc-mdevice.h
Hunk #1 FAILED at 24.
1 out of 1 hunk FAILED -- rejects in file drivers/media/video/s5p-fimc/fimc-mdevice.h
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
Sylwester Nawrocki May 20, 2012, 2:05 p.m. UTC | #2
On 05/20/2012 02:39 PM, Mauro Carvalho Chehab wrote:
> Em 14-05-2012 18:39, Sylwester Nawrocki escreveu:
>> On 05/10/2012 10:48 AM, Sylwester Nawrocki wrote:
>>> On 05/04/2012 05:31 PM, Sylwester Nawrocki wrote:
...
>>> The following changes since commit ae45d3e9aea0ab951dbbca2238fbfbf3993f1e7f:
>>>
>>>     s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-09 16:07:49 +0200)
>>>
>>> are available in the git repository at:
>>>
>>>     git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
>>>
>>> for you to fetch changes up to 5feefe6656583de6fd4ef1d53b19031dd5efeec1:
>>>
>>>     s5p-fimc: Use selection API in place of crop operations (2012-05-09 16:11:29 +0200)
>>>
>>> ----------------------------------------------------------------
>>> Sylwester Nawrocki (14):
>>>         V4L: Extend V4L2_CID_COLORFX with more image effects
>>>         s5p-fimc: Avoid crash with null platform_data
>>>         s5p-fimc: Move m2m node driver into separate file
>>
>> It seems there is a conflict now with this patch:
>> http://git.linuxtv.org/media_tree.git/commit/5126f2590bee412e3053de851cb07f531e4be36a
>>
>> Attached are updated versions of the two conflicting patches, the others
>> don't need touching.
>>
>> I could provide rebased version of the whole change set tomorrow - if needed.
> 
> Please do that, as this patch doesn't apply as-is.

I guess there is no intervention from my side needed, since you already applied
those updated patches to the media tree (since I pushed the rebased patch to
git.infradead.org a few days ago already) ?

However, there is going to be conflicts now with my patch from Sakari's pull
request: http://patchwork.linuxtv.org/patch/11336.

As we talked in #v4l IRC, even if the API is experimental, any changes to it
must not cause build breaks. I didn't discuss that yet with Sakari.  I have 
now reworked the renaming patch, so it now includes backward compatibility 
definitions like this:

#define V4L2_SEL_TGT_CROP_ACTIVE	V4L2_SEL_TGT_CROP
#define V4L2_SEL_TGT_COMPOSE_ACTIVE	V4L2_SEL_TGT_COMPOSE 

I would then make a patch for Documentation/feature-removal-schedule.txt
to indicate those aliases will be removed after two kernel releases.

Does it sound like a right thing to do ?


Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
Mauro Carvalho Chehab May 20, 2012, 3:30 p.m. UTC | #3
Em 20-05-2012 11:05, Sylwester Nawrocki escreveu:
> On 05/20/2012 02:39 PM, Mauro Carvalho Chehab wrote:
>> Em 14-05-2012 18:39, Sylwester Nawrocki escreveu:
>>> On 05/10/2012 10:48 AM, Sylwester Nawrocki wrote:
>>>> On 05/04/2012 05:31 PM, Sylwester Nawrocki wrote:
> ...
>>>> The following changes since commit ae45d3e9aea0ab951dbbca2238fbfbf3993f1e7f:
>>>>
>>>>     s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-09 16:07:49 +0200)
>>>>
>>>> are available in the git repository at:
>>>>
>>>>     git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
>>>>
>>>> for you to fetch changes up to 5feefe6656583de6fd4ef1d53b19031dd5efeec1:
>>>>
>>>>     s5p-fimc: Use selection API in place of crop operations (2012-05-09 16:11:29 +0200)
>>>>
>>>> ----------------------------------------------------------------
>>>> Sylwester Nawrocki (14):
>>>>         V4L: Extend V4L2_CID_COLORFX with more image effects
>>>>         s5p-fimc: Avoid crash with null platform_data
>>>>         s5p-fimc: Move m2m node driver into separate file
>>>
>>> It seems there is a conflict now with this patch:
>>> http://git.linuxtv.org/media_tree.git/commit/5126f2590bee412e3053de851cb07f531e4be36a
>>>
>>> Attached are updated versions of the two conflicting patches, the others
>>> don't need touching.
>>>
>>> I could provide rebased version of the whole change set tomorrow - if needed.
>>
>> Please do that, as this patch doesn't apply as-is.
> 
> I guess there is no intervention from my side needed, since you already applied
> those updated patches to the media tree (since I pushed the rebased patch to
> git.infradead.org a few days ago already) ?
> 
> However, there is going to be conflicts now with my patch from Sakari's pull
> request: http://patchwork.linuxtv.org/patch/11336.

Yes. I didn't apply that patch. It needs rework.

> 
> As we talked in #v4l IRC, even if the API is experimental, any changes to it
> must not cause build breaks. I didn't discuss that yet with Sakari.  I have 
> now reworked the renaming patch, so it now includes backward compatibility 
> definitions like this:
> 
> #define V4L2_SEL_TGT_CROP_ACTIVE	V4L2_SEL_TGT_CROP
> #define V4L2_SEL_TGT_COMPOSE_ACTIVE	V4L2_SEL_TGT_COMPOSE 
> 
> I would then make a patch for Documentation/feature-removal-schedule.txt
> to indicate those aliases will be removed after two kernel releases.
> 
> Does it sound like a right thing to do ?

_If_ 3.5 is the first kernel with the selection API, we can fix it without 
a backward compat, but I think that the selection API went into 3.4 kernel
series.

Regards,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
Sylwester Nawrocki May 20, 2012, 5:33 p.m. UTC | #4
On 05/20/2012 05:30 PM, Mauro Carvalho Chehab wrote:
> Em 20-05-2012 11:05, Sylwester Nawrocki escreveu:
>> On 05/20/2012 02:39 PM, Mauro Carvalho Chehab wrote:
>>> Em 14-05-2012 18:39, Sylwester Nawrocki escreveu:
>>>> On 05/10/2012 10:48 AM, Sylwester Nawrocki wrote:
>>>>> On 05/04/2012 05:31 PM, Sylwester Nawrocki wrote:
>> ...
>>>>> The following changes since commit ae45d3e9aea0ab951dbbca2238fbfbf3993f1e7f:
>>>>>
>>>>>      s5p-fimc: Correct memory allocation for VIDIOC_CREATE_BUFS (2012-05-09 16:07:49 +0200)
>>>>>
>>>>> are available in the git repository at:
>>>>>
>>>>>      git://git.infradead.org/users/kmpark/linux-samsung v4l-fimc-exynos4x12
>>>>>
>>>>> for you to fetch changes up to 5feefe6656583de6fd4ef1d53b19031dd5efeec1:
>>>>>
>>>>>      s5p-fimc: Use selection API in place of crop operations (2012-05-09 16:11:29 +0200)
>>>>>
>>>>> ----------------------------------------------------------------
>>>>> Sylwester Nawrocki (14):
>>>>>          V4L: Extend V4L2_CID_COLORFX with more image effects
>>>>>          s5p-fimc: Avoid crash with null platform_data
>>>>>          s5p-fimc: Move m2m node driver into separate file
>>>>
>>>> It seems there is a conflict now with this patch:
>>>> http://git.linuxtv.org/media_tree.git/commit/5126f2590bee412e3053de851cb07f531e4be36a
>>>>
>>>> Attached are updated versions of the two conflicting patches, the others
>>>> don't need touching.
>>>>
>>>> I could provide rebased version of the whole change set tomorrow - if needed.
>>>
>>> Please do that, as this patch doesn't apply as-is.
>>
>> I guess there is no intervention from my side needed, since you already applied
>> those updated patches to the media tree (since I pushed the rebased patch to
>> git.infradead.org a few days ago already) ?
>>
>> However, there is going to be conflicts now with my patch from Sakari's pull
>> request: http://patchwork.linuxtv.org/patch/11336.
> 
> Yes. I didn't apply that patch. It needs rework.
> 
>>
>> As we talked in #v4l IRC, even if the API is experimental, any changes to it
>> must not cause build breaks. I didn't discuss that yet with Sakari.  I have
>> now reworked the renaming patch, so it now includes backward compatibility
>> definitions like this:
>>
>> #define V4L2_SEL_TGT_CROP_ACTIVE	V4L2_SEL_TGT_CROP
>> #define V4L2_SEL_TGT_COMPOSE_ACTIVE	V4L2_SEL_TGT_COMPOSE
>>
>> I would then make a patch for Documentation/feature-removal-schedule.txt
>> to indicate those aliases will be removed after two kernel releases.
>>
>> Does it sound like a right thing to do ?
> 
> _If_ 3.5 is the first kernel with the selection API, we can fix it without
> a backward compat, but I think that the selection API went into 3.4 kernel
> series.

Yeah, only the selection API for subdevs is first appearing in kernel 3.5, 
and it's been already two stable kernel releases since the selection API 
was introduced:

$ git log --oneline v3.0..v3.3 -- Documentation/DocBook/media/v4l/vidioc-g-selection.xml
8af4922 [media] doc: v4l: add documentation for selection API 

So some backward compatibility code seems to be needed. It's not really
a big deal and would saved users headaches.

--
Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  

Patch

From 610f467a3cb02ca34ce48bb8d6cc3f2409571f93 Mon Sep 17 00:00:00 2001
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
Date: Mon, 14 May 2012 23:15:21 +0200
Subject: [PATCH 2/2] s5p-fimc: Use v4l2_subdev internal ops to register video nodes

In order to be able to select only FIMC-LITE support, which is added
with subsequent patches, the regular FIMC support is now contained
only in fimc-core.c, fimc-m2m.c and fimc-capture.c files. The graph
and pipeline management is now solely handled in fimc-mdevice.[ch].
This means the FIMC driver can now be excluded with Kconfig option,
leaving only FIMC-LITE and allowing this driver to be reused in SoCs
that have only FIMC-LITE and no regular FIMC IP.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/s5p-fimc/fimc-capture.c |  142 +++++++++++++++------------
 drivers/media/video/s5p-fimc/fimc-core.c    |   13 ++-
 drivers/media/video/s5p-fimc/fimc-core.h    |    7 +-
 drivers/media/video/s5p-fimc/fimc-m2m.c     |   18 +++-
 drivers/media/video/s5p-fimc/fimc-mdevice.c |   89 +++++++----------
 drivers/media/video/s5p-fimc/fimc-mdevice.h |    1 +
 6 files changed, 139 insertions(+), 131 deletions(-)

diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 2c7a4f8..51cb447 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -993,7 +993,7 @@  static int fimc_pipeline_validate(struct fimc_dev *fimc)
 		if (!(pad->flags & MEDIA_PAD_FL_SINK))
 			break;
 		/* Don't call FIMC subdev operation to avoid nested locking */
-		if (sd == fimc->vid_cap.subdev) {
+		if (sd == &fimc->vid_cap.subdev) {
 			struct fimc_frame *ff = &vid_cap->ctx->s_frame;
 			sink_fmt.format.width = ff->f_width;
 			sink_fmt.format.height = ff->f_height;
@@ -1489,53 +1489,6 @@  static struct v4l2_subdev_ops fimc_subdev_ops = {
 	.pad = &fimc_subdev_pad_ops,
 };
 
-static int fimc_create_capture_subdev(struct fimc_dev *fimc,
-				      struct v4l2_device *v4l2_dev)
-{
-	struct v4l2_subdev *sd;
-	int ret;
-
-	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-	if (!sd)
-		return -ENOMEM;
-
-	v4l2_subdev_init(sd, &fimc_subdev_ops);
-	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
-	snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
-
-	fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-	fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-	ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
-				fimc->vid_cap.sd_pads, 0);
-	if (ret)
-		goto me_err;
-	ret = v4l2_device_register_subdev(v4l2_dev, sd);
-	if (ret)
-		goto sd_err;
-
-	fimc->vid_cap.subdev = sd;
-	v4l2_set_subdevdata(sd, fimc);
-	sd->entity.ops = &fimc_sd_media_ops;
-	return 0;
-sd_err:
-	media_entity_cleanup(&sd->entity);
-me_err:
-	kfree(sd);
-	return ret;
-}
-
-static void fimc_destroy_capture_subdev(struct fimc_dev *fimc)
-{
-	struct v4l2_subdev *sd = fimc->vid_cap.subdev;
-
-	if (!sd)
-		return;
-	media_entity_cleanup(&sd->entity);
-	v4l2_device_unregister_subdev(sd);
-	kfree(sd);
-	fimc->vid_cap.subdev = NULL;
-}
-
 /* Set default format at the sensor and host interface */
 static int fimc_capture_set_default_format(struct fimc_dev *fimc)
 {
@@ -1554,7 +1507,7 @@  static int fimc_capture_set_default_format(struct fimc_dev *fimc)
 }
 
 /* fimc->lock must be already initialized */
-int fimc_register_capture_device(struct fimc_dev *fimc,
+static int fimc_register_capture_device(struct fimc_dev *fimc,
 				 struct v4l2_device *v4l2_dev)
 {
 	struct video_device *vfd;
@@ -1572,7 +1525,7 @@  int fimc_register_capture_device(struct fimc_dev *fimc,
 	ctx->out_path	 = FIMC_DMA;
 	ctx->state	 = FIMC_CTX_CAP;
 	ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
-	ctx->d_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
+	ctx->d_frame.fmt = ctx->s_frame.fmt;
 
 	vfd = video_device_alloc();
 	if (!vfd) {
@@ -1580,8 +1533,7 @@  int fimc_register_capture_device(struct fimc_dev *fimc,
 		goto err_vd_alloc;
 	}
 
-	snprintf(vfd->name, sizeof(vfd->name), "%s.capture",
-		 dev_name(&fimc->pdev->dev));
+	snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id);
 
 	vfd->fops	= &fimc_capture_fops;
 	vfd->ioctl_ops	= &fimc_capture_ioctl_ops;
@@ -1616,18 +1568,22 @@  int fimc_register_capture_device(struct fimc_dev *fimc,
 
 	vb2_queue_init(q);
 
-	fimc->vid_cap.vd_pad.flags = MEDIA_PAD_FL_SINK;
-	ret = media_entity_init(&vfd->entity, 1, &fimc->vid_cap.vd_pad, 0);
+	vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
 	if (ret)
 		goto err_ent;
-	ret = fimc_create_capture_subdev(fimc, v4l2_dev);
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
 	if (ret)
-		goto err_sd_reg;
+		goto err_vd;
+
+	v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
+		  vfd->name, video_device_node_name(vfd));
 
 	vfd->ctrl_handler = &ctx->ctrl_handler;
 	return 0;
 
-err_sd_reg:
+err_vd:
 	media_entity_cleanup(&vfd->entity);
 err_ent:
 	video_device_release(vfd);
@@ -1636,17 +1592,73 @@  err_vd_alloc:
 	return ret;
 }
 
-void fimc_unregister_capture_device(struct fimc_dev *fimc)
+static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
 {
-	struct video_device *vfd = fimc->vid_cap.vfd;
+	struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+	int ret;
 
-	if (vfd) {
-		media_entity_cleanup(&vfd->entity);
-		/* Can also be called if video device was
-		   not registered */
-		video_unregister_device(vfd);
+	ret = fimc_register_m2m_device(fimc, sd->v4l2_dev);
+	if (ret)
+		return ret;
+
+	ret = fimc_register_capture_device(fimc, sd->v4l2_dev);
+	if (ret)
+		fimc_unregister_m2m_device(fimc);
+
+	return ret;
+}
+
+static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
+{
+	struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
+
+	if (fimc == NULL)
+		return;
+
+	fimc_unregister_m2m_device(fimc);
+
+	if (fimc->vid_cap.vfd) {
+		media_entity_cleanup(&fimc->vid_cap.vfd->entity);
+		video_unregister_device(fimc->vid_cap.vfd);
+		fimc->vid_cap.vfd = NULL;
 	}
-	fimc_destroy_capture_subdev(fimc);
+
 	kfree(fimc->vid_cap.ctx);
 	fimc->vid_cap.ctx = NULL;
 }
+
+static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = {
+	.registered = fimc_capture_subdev_registered,
+	.unregistered = fimc_capture_subdev_unregistered,
+};
+
+int fimc_initialize_capture_subdev(struct fimc_dev *fimc)
+{
+	struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
+	int ret;
+
+	v4l2_subdev_init(sd, &fimc_subdev_ops);
+	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
+
+	fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
+				fimc->vid_cap.sd_pads, 0);
+	if (ret)
+		return ret;
+
+	sd->entity.ops = &fimc_sd_media_ops;
+	sd->internal_ops = &fimc_capture_sd_internal_ops;
+	v4l2_set_subdevdata(sd, fimc);
+	return 0;
+}
+
+void fimc_unregister_capture_subdev(struct fimc_dev *fimc)
+{
+	struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
+
+	v4l2_device_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+	v4l2_set_subdevdata(sd, NULL);
+}
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 749db4d..add24cd 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -842,8 +842,6 @@  static int fimc_probe(struct platform_device *pdev)
 	clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
 	clk_enable(fimc->clock[CLK_BUS]);
 
-	platform_set_drvdata(pdev, fimc);
-
 	ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler,
 			       0, pdev->name, fimc);
 	if (ret) {
@@ -851,10 +849,15 @@  static int fimc_probe(struct platform_device *pdev)
 		goto err_clk;
 	}
 
+	ret = fimc_initialize_capture_subdev(fimc);
+	if (ret)
+		goto err_clk;
+
+	platform_set_drvdata(pdev, fimc);
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0)
-		goto err_clk;
+		goto err_sd;
 	/* Initialize contiguous memory allocator */
 	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
 	if (IS_ERR(fimc->alloc_ctx)) {
@@ -866,9 +869,10 @@  static int fimc_probe(struct platform_device *pdev)
 
 	pm_runtime_put(&pdev->dev);
 	return 0;
-
 err_pm:
 	pm_runtime_put(&pdev->dev);
+err_sd:
+	fimc_unregister_capture_subdev(fimc);
 err_clk:
 	fimc_clk_put(fimc);
 	return ret;
@@ -953,6 +957,7 @@  static int __devexit fimc_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
+	fimc_unregister_capture_subdev(fimc);
 	vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
 
 	clk_disable(fimc->clock[CLK_BUS]);
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 288631a..ef7c6a2 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -331,7 +331,7 @@  struct fimc_vid_cap {
 	struct fimc_ctx			*ctx;
 	struct vb2_alloc_ctx		*alloc_ctx;
 	struct video_device		*vfd;
-	struct v4l2_subdev		*subdev;
+	struct v4l2_subdev		subdev;
 	struct media_pad		vd_pad;
 	struct v4l2_mbus_framefmt	mf;
 	struct media_pad		sd_pads[FIMC_SD_PADS_NUM];
@@ -737,9 +737,8 @@  void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state);
 
 /* -----------------------------------------------------*/
 /* fimc-capture.c					*/
-int fimc_register_capture_device(struct fimc_dev *fimc,
-				 struct v4l2_device *v4l2_dev);
-void fimc_unregister_capture_device(struct fimc_dev *fimc);
+int fimc_initialize_capture_subdev(struct fimc_dev *fimc);
+void fimc_unregister_capture_subdev(struct fimc_dev *fimc);
 int fimc_capture_ctrls_create(struct fimc_dev *fimc);
 void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
 			void *arg);
diff --git a/drivers/media/video/s5p-fimc/fimc-m2m.c b/drivers/media/video/s5p-fimc/fimc-m2m.c
index 4a755ff..bb81126 100644
--- a/drivers/media/video/s5p-fimc/fimc-m2m.c
+++ b/drivers/media/video/s5p-fimc/fimc-m2m.c
@@ -777,7 +777,8 @@  int fimc_register_m2m_device(struct fimc_dev *fimc,
 	 * This driver needs auditing so that this flag can be removed.
 	 */
 	set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
-	snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev));
+
+	snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
 	video_set_drvdata(vfd, fimc);
 
 	fimc->m2m.vfd = vfd;
@@ -789,9 +790,20 @@  int fimc_register_m2m_device(struct fimc_dev *fimc,
 	}
 
 	ret = media_entity_init(&vfd->entity, 0, NULL, 0);
-	if (!ret)
-		return 0;
+	if (ret)
+		goto err_me;
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+	if (ret)
+		goto err_vd;
+
+	v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
+		  vfd->name, video_device_node_name(vfd));
+	return 0;
 
+err_vd:
+	media_entity_cleanup(&vfd->entity);
+err_me:
 	v4l2_m2m_release(fimc->m2m.m2m_dev);
 err_init:
 	video_device_release(fimc->m2m.vfd);
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index f97ac02..c319842 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -304,8 +304,9 @@  static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
 static int fimc_register_callback(struct device *dev, void *p)
 {
 	struct fimc_dev *fimc = dev_get_drvdata(dev);
+	struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
 	struct fimc_md *fmd = p;
-	int ret;
+	int ret = 0;
 
 	if (!fimc || !fimc->pdev)
 		return 0;
@@ -313,12 +314,14 @@  static int fimc_register_callback(struct device *dev, void *p)
 		return 0;
 
 	fmd->fimc[fimc->pdev->id] = fimc;
-	ret = fimc_register_m2m_device(fimc, &fmd->v4l2_dev);
-	if (ret)
-		return ret;
-	ret = fimc_register_capture_device(fimc, &fmd->v4l2_dev);
-	if (!ret)
-		fimc->vid_cap.user_subdev_api = fmd->user_subdev_api;
+	sd->grp_id = FIMC_GROUP_ID;
+
+	ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+	if (ret) {
+		v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
+			 fimc->id, ret);
+	}
+
 	return ret;
 }
 
@@ -401,8 +404,7 @@  static void fimc_md_unregister_entities(struct fimc_md *fmd)
 	for (i = 0; i < FIMC_MAX_DEVS; i++) {
 		if (fmd->fimc[i] == NULL)
 			continue;
-		fimc_unregister_m2m_device(fmd->fimc[i]);
-		fimc_unregister_capture_device(fmd->fimc[i]);
+		v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
 		fmd->fimc[i] = NULL;
 	}
 	for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
@@ -420,35 +422,6 @@  static void fimc_md_unregister_entities(struct fimc_md *fmd)
 	}
 }
 
-static int fimc_md_register_video_nodes(struct fimc_md *fmd)
-{
-	struct video_device *vdev;
-	int i, ret = 0;
-
-	for (i = 0; i < FIMC_MAX_DEVS && !ret; i++) {
-		if (!fmd->fimc[i])
-			continue;
-
-		vdev = fmd->fimc[i]->m2m.vfd;
-		if (vdev) {
-			ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-			if (ret)
-				break;
-			v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n",
-				  vdev->name, video_device_node_name(vdev));
-		}
-
-		vdev = fmd->fimc[i]->vid_cap.vfd;
-		if (vdev == NULL)
-			continue;
-		ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-		v4l2_info(&fmd->v4l2_dev, "Registered %s as /dev/%s\n",
-			  vdev->name, video_device_node_name(vdev));
-	}
-
-	return ret;
-}
-
 /**
  * __fimc_md_create_fimc_links - create links to all FIMC entities
  * @fmd: fimc media device
@@ -479,7 +452,7 @@  static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
 			continue;
 
 		flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
-		sink = &fmd->fimc[i]->vid_cap.subdev->entity;
+		sink = &fmd->fimc[i]->vid_cap.subdev.entity;
 		ret = media_entity_create_link(source, pad, sink,
 					      FIMC_SD_PAD_SINK, flags);
 		if (ret)
@@ -588,7 +561,7 @@  static int fimc_md_create_links(struct fimc_md *fmd)
 	for (i = 0; i < FIMC_MAX_DEVS; i++) {
 		if (!fmd->fimc[i])
 			continue;
-		source = &fmd->fimc[i]->vid_cap.subdev->entity;
+		source = &fmd->fimc[i]->vid_cap.subdev.entity;
 		sink = &fmd->fimc[i]->vid_cap.vfd->entity;
 		ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
 					      sink, 0, flags);
@@ -817,42 +790,48 @@  static int fimc_md_probe(struct platform_device *pdev)
 	ret = media_device_register(&fmd->media_dev);
 	if (ret < 0) {
 		v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
-		goto err2;
+		goto err_md;
 	}
 	ret = fimc_md_get_clocks(fmd);
 	if (ret)
-		goto err3;
+		goto err_clk;
 
 	fmd->user_subdev_api = false;
+
+	/* Protect the media graph while we're registering entities */
+	mutex_lock(&fmd->media_dev.graph_mutex);
+
 	ret = fimc_md_register_platform_entities(fmd);
 	if (ret)
-		goto err3;
+		goto err_unlock;
 
 	if (pdev->dev.platform_data) {
 		ret = fimc_md_register_sensor_entities(fmd);
 		if (ret)
-			goto err3;
+			goto err_unlock;
 	}
 	ret = fimc_md_create_links(fmd);
 	if (ret)
-		goto err3;
+		goto err_unlock;
 	ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
 	if (ret)
-		goto err3;
-	ret = fimc_md_register_video_nodes(fmd);
-	if (ret)
-		goto err3;
+		goto err_unlock;
 
 	ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
-	if (!ret) {
-		platform_set_drvdata(pdev, fmd);
-		return 0;
-	}
-err3:
+	if (ret)
+		goto err_unlock;
+
+	platform_set_drvdata(pdev, fmd);
+	mutex_unlock(&fmd->media_dev.graph_mutex);
+	return 0;
+
+err_unlock:
+	mutex_unlock(&fmd->media_dev.graph_mutex);
+err_clk:
 	media_device_unregister(&fmd->media_dev);
 	fimc_md_put_clocks(fmd);
 	fimc_md_unregister_entities(fmd);
-err2:
+err_md:
 	v4l2_device_unregister(&fmd->v4l2_dev);
 	return ret;
 }
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.h b/drivers/media/video/s5p-fimc/fimc-mdevice.h
index da37808..4f3b69c 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.h
@@ -24,6 +24,7 @@ 
 #define SENSOR_GROUP_ID		(1 << 8)
 #define CSIS_GROUP_ID		(1 << 9)
 #define WRITEBACK_GROUP_ID	(1 << 10)
+#define FIMC_GROUP_ID		(1 << 11)
 
 #define FIMC_MAX_SENSORS	8
 #define FIMC_MAX_CAMCLKS	2
-- 
1.7.4.1