linux_dsm_epyc7002/drivers/media/platform/vimc/vimc-common.c

388 lines
9.1 KiB
C
Raw Normal View History

treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 157 Based on 3 normalized pattern(s): 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 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 [author] [kishon] [vijay] [abraham] [i] [kishon]@[ti] [com] 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 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 [author] [graeme] [gregory] [gg]@[slimlogic] [co] [uk] [author] [kishon] [vijay] [abraham] [i] [kishon]@[ti] [com] [based] [on] [twl6030]_[usb] [c] [author] [hema] [hk] [hemahk]@[ti] [com] 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 extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 1105 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Richard Fontana <rfontana@redhat.com> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070033.202006027@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-27 13:55:06 +07:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* vimc-common.c Virtual Media Controller Driver
*
* Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com>
*/
#include <linux/init.h>
#include <linux/module.h>
#include "vimc-common.h"
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
/*
* NOTE: non-bayer formats need to come first (necessary for enum_mbus_code
* in the scaler)
*/
static const struct vimc_pix_map vimc_pix_map_list[] = {
/* TODO: add all missing formats */
/* RGB formats */
{
.code = MEDIA_BUS_FMT_BGR888_1X24,
.pixelformat = V4L2_PIX_FMT_BGR24,
.bpp = 3,
.bayer = false,
},
{
.code = MEDIA_BUS_FMT_RGB888_1X24,
.pixelformat = V4L2_PIX_FMT_RGB24,
.bpp = 3,
.bayer = false,
},
{
.code = MEDIA_BUS_FMT_ARGB8888_1X32,
.pixelformat = V4L2_PIX_FMT_ARGB32,
.bpp = 4,
.bayer = false,
},
/* Bayer formats */
{
.code = MEDIA_BUS_FMT_SBGGR8_1X8,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGBRG8_1X8,
.pixelformat = V4L2_PIX_FMT_SGBRG8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGRBG8_1X8,
.pixelformat = V4L2_PIX_FMT_SGRBG8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SRGGB8_1X8,
.pixelformat = V4L2_PIX_FMT_SRGGB8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SBGGR10_1X10,
.pixelformat = V4L2_PIX_FMT_SBGGR10,
.bpp = 2,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGBRG10_1X10,
.pixelformat = V4L2_PIX_FMT_SGBRG10,
.bpp = 2,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGRBG10_1X10,
.pixelformat = V4L2_PIX_FMT_SGRBG10,
.bpp = 2,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SRGGB10_1X10,
.pixelformat = V4L2_PIX_FMT_SRGGB10,
.bpp = 2,
.bayer = true,
},
/* 10bit raw bayer a-law compressed to 8 bits */
{
.code = MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8,
.pixelformat = V4L2_PIX_FMT_SBGGR10ALAW8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8,
.pixelformat = V4L2_PIX_FMT_SGBRG10ALAW8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8,
.pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8,
.pixelformat = V4L2_PIX_FMT_SRGGB10ALAW8,
.bpp = 1,
.bayer = true,
},
/* 10bit raw bayer DPCM compressed to 8 bits */
{
.code = MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
.pixelformat = V4L2_PIX_FMT_SBGGR10DPCM8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
.pixelformat = V4L2_PIX_FMT_SGBRG10DPCM8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
.pixelformat = V4L2_PIX_FMT_SRGGB10DPCM8,
.bpp = 1,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SBGGR12_1X12,
.pixelformat = V4L2_PIX_FMT_SBGGR12,
.bpp = 2,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGBRG12_1X12,
.pixelformat = V4L2_PIX_FMT_SGBRG12,
.bpp = 2,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SGRBG12_1X12,
.pixelformat = V4L2_PIX_FMT_SGRBG12,
.bpp = 2,
.bayer = true,
},
{
.code = MEDIA_BUS_FMT_SRGGB12_1X12,
.pixelformat = V4L2_PIX_FMT_SRGGB12,
.bpp = 2,
.bayer = true,
},
};
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i)
{
if (i >= ARRAY_SIZE(vimc_pix_map_list))
return NULL;
return &vimc_pix_map_list[i];
}
const struct vimc_pix_map *vimc_pix_map_by_code(u32 code)
{
unsigned int i;
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
if (vimc_pix_map_list[i].code == code)
return &vimc_pix_map_list[i];
}
return NULL;
}
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat)
{
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
unsigned int i;
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) {
if (vimc_pix_map_list[i].pixelformat == pixelformat)
return &vimc_pix_map_list[i];
}
return NULL;
}
/* Helper function to allocate and initialize pads */
struct media_pad *vimc_pads_init(u16 num_pads, const unsigned long *pads_flag)
{
struct media_pad *pads;
unsigned int i;
/* Allocate memory for the pads */
pads = kcalloc(num_pads, sizeof(*pads), GFP_KERNEL);
if (!pads)
return ERR_PTR(-ENOMEM);
/* Initialize the pads */
for (i = 0; i < num_pads; i++) {
pads[i].index = i;
pads[i].flags = pads_flag[i];
}
return pads;
}
static int vimc_get_mbus_format(struct media_pad *pad,
struct v4l2_subdev_format *fmt)
{
if (is_media_entity_v4l2_subdev(pad->entity)) {
struct v4l2_subdev *sd =
media_entity_to_v4l2_subdev(pad->entity);
int ret;
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
fmt->pad = pad->index;
ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
if (ret)
return ret;
} else if (is_media_entity_v4l2_video_device(pad->entity)) {
struct video_device *vdev = container_of(pad->entity,
struct video_device,
entity);
struct vimc_ent_device *ved = video_get_drvdata(vdev);
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
const struct vimc_pix_map *vpix;
struct v4l2_pix_format vdev_fmt;
if (!ved->vdev_get_format)
return -ENOIOCTLCMD;
ved->vdev_get_format(ved, &vdev_fmt);
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
vpix = vimc_pix_map_by_pixelformat(vdev_fmt.pixelformat);
v4l2_fill_mbus_format(&fmt->format, &vdev_fmt, vpix->code);
} else {
return -EINVAL;
}
return 0;
}
int vimc_link_validate(struct media_link *link)
{
struct v4l2_subdev_format source_fmt, sink_fmt;
int ret;
ret = vimc_get_mbus_format(link->source, &source_fmt);
if (ret)
return ret;
ret = vimc_get_mbus_format(link->sink, &sink_fmt);
if (ret)
return ret;
pr_info("vimc link validate: "
"%s:src:%dx%d (0x%x, %d, %d, %d, %d) "
"%s:snk:%dx%d (0x%x, %d, %d, %d, %d)\n",
/* src */
link->source->entity->name,
source_fmt.format.width, source_fmt.format.height,
source_fmt.format.code, source_fmt.format.colorspace,
source_fmt.format.quantization, source_fmt.format.xfer_func,
source_fmt.format.ycbcr_enc,
/* sink */
link->sink->entity->name,
sink_fmt.format.width, sink_fmt.format.height,
sink_fmt.format.code, sink_fmt.format.colorspace,
sink_fmt.format.quantization, sink_fmt.format.xfer_func,
sink_fmt.format.ycbcr_enc);
/* The width, height and code must match. */
if (source_fmt.format.width != sink_fmt.format.width
|| source_fmt.format.height != sink_fmt.format.height
media: Revert "media: vimc: propagate pixel format in the stream" This reverts commit b6c61a6c37317efd7327199bfe24770af3d7e799. The requested pixelformat is being propagated from the capture to the tpg in the sensor. This was a bad design choice, as we start having the following issues: * We set a pixelformat in the capture; * We set matching media bus formats in the subdevices pads; * Link validate looks fine (sizes matches, media bus formats matches); * Issue: if some of the subdevice doesn't know how to generate the requested pixelformat in the capture, then stream_on fails. This is bad because capture says it supports that pixelformat, everything looks fine, but it is not, and there is no way to find it out through the links. This patch was implemented so we could request any pixelformat from the pipeline regardeless of the media bus format configured between pads. Not all pixelformat can be mapped into a media bus code (e.g. multiplanar formats), so with this patch we could request those pixelformats from the tpg. Solution: map pixelformats to media bus codes as before, and implement conversions to other pixelformats in the capture to support multiplanar. So first step to this solution is to revert this patch. Signed-off-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Lucas A. M. Magalhaes <lucmaga@gmail.com> Tested-by: André Almeida <andrealmeid@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-08-09 07:27:41 +07:00
|| source_fmt.format.code != sink_fmt.format.code)
return -EPIPE;
/*
* The field order must match, or the sink field order must be NONE
* to support interlaced hardware connected to bridges that support
* progressive formats only.
*/
if (source_fmt.format.field != sink_fmt.format.field &&
sink_fmt.format.field != V4L2_FIELD_NONE)
return -EPIPE;
/*
* If colorspace is DEFAULT, then assume all the colorimetry is also
* DEFAULT, return 0 to skip comparing the other colorimetry parameters
*/
if (source_fmt.format.colorspace == V4L2_COLORSPACE_DEFAULT
|| sink_fmt.format.colorspace == V4L2_COLORSPACE_DEFAULT)
return 0;
/* Colorspace must match. */
if (source_fmt.format.colorspace != sink_fmt.format.colorspace)
return -EPIPE;
/* Colorimetry must match if they are not set to DEFAULT */
if (source_fmt.format.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT
&& sink_fmt.format.ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT
&& source_fmt.format.ycbcr_enc != sink_fmt.format.ycbcr_enc)
return -EPIPE;
if (source_fmt.format.quantization != V4L2_QUANTIZATION_DEFAULT
&& sink_fmt.format.quantization != V4L2_QUANTIZATION_DEFAULT
&& source_fmt.format.quantization != sink_fmt.format.quantization)
return -EPIPE;
if (source_fmt.format.xfer_func != V4L2_XFER_FUNC_DEFAULT
&& sink_fmt.format.xfer_func != V4L2_XFER_FUNC_DEFAULT
&& source_fmt.format.xfer_func != sink_fmt.format.xfer_func)
return -EPIPE;
return 0;
}
static const struct media_entity_operations vimc_ent_sd_mops = {
.link_validate = vimc_link_validate,
};
int vimc_ent_sd_register(struct vimc_ent_device *ved,
struct v4l2_subdev *sd,
struct v4l2_device *v4l2_dev,
const char *const name,
u32 function,
u16 num_pads,
const unsigned long *pads_flag,
const struct v4l2_subdev_internal_ops *sd_int_ops,
const struct v4l2_subdev_ops *sd_ops)
{
int ret;
media: vimc: Fix gpf in rmmod path when stream is active If vimc module is removed while streaming is in progress, sensor subdev unregister runs into general protection fault when it tries to unregister media entities. This is a common subdev problem related to releasing pads from v4l2_device_unregister_subdev() before calling unregister. Unregister references pads during unregistering subdev. The sd release handler is the right place for releasing all sd resources including pads. The release handlers currently release all resources except the pads. Fix v4l2_device_unregister_subdev() not release pads and release pads from the sd_int_op release handlers. kernel: [ 4136.715839] general protection fault: 0000 [#1] SMP PTI kernel: [ 4136.715847] CPU: 2 PID: 1972 Comm: bash Not tainted 5.3.0-rc2+ #4 kernel: [ 4136.715850] Hardware name: Dell Inc. OptiPlex 790/0HY9JP, BIOS A18 09/24/2013 kernel: [ 4136.715858] RIP: 0010:media_gobj_destroy.part.16+0x1f/0x60 kernel: [ 4136.715863] Code: ff 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 fe 48 89 e5 53 48 89 fb 48 c7 c7 00 7f cf b0 e8 24 fa ff ff 48 8b 03 <48> 83 80 a0 00 00 00 01 48 8b 43 18 48 8b 53 10 48 89 42 08 48 89 kernel: [ 4136.715866] RSP: 0018:ffff9b2248fe3cb0 EFLAGS: 00010246 kernel: [ 4136.715870] RAX: bcf2bfbfa0d63c2f RBX: ffff88c3eb37e9c0 RCX: 00000000802a0018 kernel: [ 4136.715873] RDX: ffff88c3e4f6a078 RSI: ffff88c3eb37e9c0 RDI: ffffffffb0cf7f00 kernel: [ 4136.715876] RBP: ffff9b2248fe3cb8 R08: 0000000001000002 R09: ffffffffb0492b00 kernel: [ 4136.715879] R10: ffff9b2248fe3c28 R11: 0000000000000001 R12: 0000000000000038 kernel: [ 4136.715881] R13: ffffffffc09a1628 R14: ffff88c3e4f6a028 R15: fffffffffffffff2 kernel: [ 4136.715885] FS: 00007f8389647740(0000) GS:ffff88c465500000(0000) knlGS:0000000000000000 kernel: [ 4136.715888] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 kernel: [ 4136.715891] CR2: 000055d008f80fd8 CR3: 00000001996ec005 CR4: 00000000000606e0 kernel: [ 4136.715894] Call Trace: kernel: [ 4136.715903] media_gobj_destroy+0x14/0x20 kernel: [ 4136.715908] __media_device_unregister_entity+0xb3/0xe0 kernel: [ 4136.715915] media_device_unregister_entity+0x30/0x40 kernel: [ 4136.715920] v4l2_device_unregister_subdev+0xa8/0xe0 kernel: [ 4136.715928] vimc_ent_sd_unregister+0x1e/0x30 [vimc] kernel: [ 4136.715933] vimc_sen_rm+0x16/0x20 [vimc] kernel: [ 4136.715938] vimc_remove+0x3e/0xa0 [vimc] kernel: [ 4136.715945] platform_drv_remove+0x25/0x50 kernel: [ 4136.715951] device_release_driver_internal+0xe0/0x1b0 kernel: [ 4136.715956] device_driver_detach+0x14/0x20 kernel: [ 4136.715960] unbind_store+0xd1/0x130 kernel: [ 4136.715965] drv_attr_store+0x27/0x40 kernel: [ 4136.715971] sysfs_kf_write+0x48/0x60 kernel: [ 4136.715976] kernfs_fop_write+0x128/0x1b0 kernel: [ 4136.715982] __vfs_write+0x1b/0x40 kernel: [ 4136.715987] vfs_write+0xc3/0x1d0 kernel: [ 4136.715993] ksys_write+0xaa/0xe0 kernel: [ 4136.715999] __x64_sys_write+0x1a/0x20 kernel: [ 4136.716005] do_syscall_64+0x5a/0x130 kernel: [ 4136.716010] entry_SYSCALL_64_after_hwframe+0x4 Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> Acked-by: Helen Koike <helen.koike@collabora.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2019-09-17 23:35:09 +07:00
/* Allocate the pads. Should be released from the sd_int_op release */
ved->pads = vimc_pads_init(num_pads, pads_flag);
if (IS_ERR(ved->pads))
return PTR_ERR(ved->pads);
/* Fill the vimc_ent_device struct */
ved->ent = &sd->entity;
/* Initialize the subdev */
v4l2_subdev_init(sd, sd_ops);
sd->internal_ops = sd_int_ops;
sd->entity.function = function;
sd->entity.ops = &vimc_ent_sd_mops;
sd->owner = THIS_MODULE;
strscpy(sd->name, name, sizeof(sd->name));
v4l2_set_subdevdata(sd, ved);
/* Expose this subdev to user space */
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
if (sd->ctrl_handler)
sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
/* Initialize the media entity */
ret = media_entity_pads_init(&sd->entity, num_pads, ved->pads);
if (ret)
goto err_clean_pads;
/* Register the subdev with the v4l2 and the media framework */
ret = v4l2_device_register_subdev(v4l2_dev, sd);
if (ret) {
dev_err(v4l2_dev->dev,
"%s: subdev register failed (err=%d)\n",
name, ret);
goto err_clean_m_ent;
}
return 0;
err_clean_m_ent:
media_entity_cleanup(&sd->entity);
err_clean_pads:
vimc_pads_cleanup(ved->pads);
return ret;
}