mbox series

[v2,00/19] Qualcomm 8x16 Camera Subsystem driver

Message ID 1497883719-12410-1-git-send-email-todor.tomov@linaro.org
Headers show
Series Qualcomm 8x16 Camera Subsystem driver | expand

Message

Todor Tomov June 19, 2017, 2:48 p.m. UTC
This patchset adds basic support for the Qualcomm Camera Subsystem found
on Qualcomm MSM8916 and APQ8016 processors.

The driver implements V4L2, Media controller and V4L2 subdev interfaces.
Camera sensor using V4L2 subdev interface in the kernel is supported.

The driver is implemented using as a reference the Qualcomm Camera
Subsystem driver for Android as found in Code Aurora [1].

The driver is tested on Dragonboard 410C (APQ8016) with one and two
OV5645 camera sensors. media-ctl [2] and yavta [3] applications were
used for testing. Also Gstreamer 1.10.4 with v4l2src plugin is supported.

More information is present in the document added by the third patch.

-------------------------------------------------------------------------------

Patchset Changelog:

Version 2:
- patches 01-10 are updated from v1 following the review received and bugs
  and limitaitons found after v1 was posted. The updates include:
  - return buffers on unsuccessful stream on;
  - fill device capabilities in struct video_device;
  - simplify v4l2 file handle usage - no custom struct for file handle;
  - use vb2_fop_poll and vb2_fop_mmap v4l2 file operations;
  - add support for read/write I/O;
  - add support for DMABUF streaming I/O;
  - add support for EXPBUF and PREPARE_BUF ioctl;
  - avoid a race condition between device unbind and userspace access
    to the video node;
  - use non-contiguous memory for video buffers;
  - switch to V4L2 multi-planar API;
  - add useful error messages in case of an overflow in ISPIF;
  - other small and style fixes.

- patches 11-19 are new (they were not ready/posted with v1). I'm including
  these in this patchset as they add valuable features and may be desired
  for a real world usage of the driver.

-------------------------------------------------------------------------------

The patchset depends on:
v4l: Add packed Bayer raw12 pixel formats [4]

-------------------------------------------------------------------------------

V4L2 compliance test result:

$ v4l2-compliance -s -d /dev/video0 
v4l2-compliance SHA   : ce237eefc1f6dafafc0e1fe3a5fd9f075d3fd066

Driver Info:
        Driver name   : qcom-camss
        Card type     : Qualcomm Camera Subsystem
        Bus info      : platform:1b0ac00.camss
        Driver version: 4.9.27
        Capabilities  : 0x85201000
                Video Capture Multiplanar
                Read/Write
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x05201000
                Video Capture Multiplanar
                Read/Write
                Streaming
                Extended Pix Format

Compliance test for device /dev/video0 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK
        test for unlimited opens: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 1 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

Test input 0:

        Control ioctls:
                test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
                test VIDIOC_QUERYCTRL: OK (Not Supported)
                test VIDIOC_G/S_CTRL: OK (Not Supported)
                test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 0 Private Controls: 0

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK (Not Supported)
                test VIDIOC_G_FBUF: OK (Not Supported)
                test VIDIOC_G_FMT: OK
                test VIDIOC_TRY_FMT: OK
                test VIDIOC_S_FMT: OK
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
                test Cropping: OK (Not Supported)
                test Composing: OK (Not Supported)
                test Scaling: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                test VIDIOC_EXPBUF: OK

Test input 0:

Streaming ioctls:
        test read/write: OK
        test MMAP: OK                                     
        test USERPTR: OK (Not Supported)
        test DMABUF: Cannot test, specify --expbuf-device


Total: 46, Succeeded: 46, Failed: 0, Warnings: 0

-------------------------------------------------------------------------------

[1] https://source.codeaurora.org/quic/la/kernel/msm-3.10/
[2] https://git.linuxtv.org//v4l-utils.git
[3] http://git.ideasonboard.org/yavta.git
[4] https://git.linuxtv.org/sailus/media_tree.git/commit/?h=packed12-postponed&id=549c02da6eed8dc4566632a9af9233bf99ba99d8

Todor Tomov (19):
  doc: DT: camss: Binding document for Qualcomm Camera subsystem driver
  MAINTAINERS: Add Qualcomm Camera subsystem driver
  doc: media/v4l-drivers: Add Qualcomm Camera Subsystem driver document
  media: camss: Add CSIPHY files
  media: camss: Add CSID files
  media: camss: Add ISPIF files
  media: camss: Add VFE files
  media: camss: Add files which handle the video device nodes
  media: camms: Add core files
  media: camss: Enable building
  camss: vfe: Format conversion support using PIX interface
  doc: media/v4l-drivers: Qualcomm Camera Subsystem - PIX Interface
  camss: vfe: Support for frame padding
  camss: vfe: Add interface for scaling
  camss: vfe: Configure scaler module in VFE
  camss: vfe: Add interface for cropping
  camss: vfe: Configure crop module in VFE
  doc: media/v4l-drivers: Qualcomm Camera Subsystem - Scale and crop
  camss: Use optimal clock frequency rates

 .../devicetree/bindings/media/qcom,camss.txt       |  196 ++
 Documentation/media/v4l-drivers/qcom_camss.rst     |  157 +
 MAINTAINERS                                        |    8 +
 drivers/media/platform/Kconfig                     |    6 +
 drivers/media/platform/Makefile                    |    2 +
 drivers/media/platform/qcom/camss-8x16/Makefile    |   11 +
 drivers/media/platform/qcom/camss-8x16/camss.c     |  724 +++++
 drivers/media/platform/qcom/camss-8x16/camss.h     |  105 +
 drivers/media/platform/qcom/camss-8x16/csid.c      | 1141 ++++++++
 drivers/media/platform/qcom/camss-8x16/csid.h      |   82 +
 drivers/media/platform/qcom/camss-8x16/csiphy.c    |  821 ++++++
 drivers/media/platform/qcom/camss-8x16/csiphy.h    |   77 +
 drivers/media/platform/qcom/camss-8x16/ispif.c     | 1137 ++++++++
 drivers/media/platform/qcom/camss-8x16/ispif.h     |   85 +
 drivers/media/platform/qcom/camss-8x16/vfe.c       | 3046 ++++++++++++++++++++
 drivers/media/platform/qcom/camss-8x16/vfe.h       |  123 +
 drivers/media/platform/qcom/camss-8x16/video.c     |  842 ++++++
 drivers/media/platform/qcom/camss-8x16/video.h     |   72 +
 18 files changed, 8635 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/qcom,camss.txt
 create mode 100644 Documentation/media/v4l-drivers/qcom_camss.rst
 create mode 100644 drivers/media/platform/qcom/camss-8x16/Makefile
 create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.c
 create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.h
 create mode 100644 drivers/media/platform/qcom/camss-8x16/csid.c
 create mode 100644 drivers/media/platform/qcom/camss-8x16/csid.h
 create mode 100644 drivers/media/platform/qcom/camss-8x16/csiphy.c
 create mode 100644 drivers/media/platform/qcom/camss-8x16/csiphy.h
 create mode 100644 drivers/media/platform/qcom/camss-8x16/ispif.c
 create mode 100644 drivers/media/platform/qcom/camss-8x16/ispif.h
 create mode 100644 drivers/media/platform/qcom/camss-8x16/vfe.c
 create mode 100644 drivers/media/platform/qcom/camss-8x16/vfe.h
 create mode 100644 drivers/media/platform/qcom/camss-8x16/video.c
 create mode 100644 drivers/media/platform/qcom/camss-8x16/video.h

-- 
1.9.1

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

Comments

Sakari Ailus June 29, 2017, 6:33 a.m. UTC | #1
Hi Todor,

On Mon, Jun 19, 2017 at 05:48:29PM +0300, Todor Tomov wrote:
> These files implement the platform driver code.

> 

> Signed-off-by: Todor Tomov <todor.tomov@linaro.org>

> ---

>  drivers/media/platform/qcom/camss-8x16/camss.c | 630 +++++++++++++++++++++++++

>  drivers/media/platform/qcom/camss-8x16/camss.h |  96 ++++

>  2 files changed, 726 insertions(+)

>  create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.c

>  create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.h

> 

> diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c

> new file mode 100644

> index 0000000..a8798d1

> --- /dev/null

> +++ b/drivers/media/platform/qcom/camss-8x16/camss.c

> @@ -0,0 +1,630 @@

> +/*

> + * camss.c

> + *

> + * Qualcomm MSM Camera Subsystem - Core

> + *

> + * Copyright (c) 2015, The Linux Foundation. All rights reserved.

> + * Copyright (C) 2015-2016 Linaro Ltd.

> + *

> + * This program is free software; you can redistribute it and/or modify

> + * it under the terms of the GNU General Public License version 2 and

> + * only version 2 as published by the Free Software Foundation.

> + *

> + * 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.

> + */

> +#include <linux/clk.h>

> +#include <linux/media-bus-format.h>

> +#include <linux/module.h>

> +#include <linux/platform_device.h>

> +#include <linux/of.h>

> +#include <linux/slab.h>

> +

> +#include <media/media-device.h>

> +#include <media/v4l2-async.h>

> +#include <media/v4l2-device.h>

> +#include <media/v4l2-mc.h>

> +#include <media/v4l2-of.h>

> +

> +#include "camss.h"

> +

> +static struct resources csiphy_res[] = {

> +	/* CSIPHY0 */

> +	{

> +		.regulator = { NULL },

> +		.clock = { "camss_top_ahb_clk", "ispif_ahb_clk",

> +			   "camss_ahb_clk", "csiphy0_timer_clk" },

> +		.clock_rate = { 0, 0, 0, 200000000 },

> +		.reg = { "csiphy0", "csiphy0_clk_mux" },

> +		.interrupt = { "csiphy0" }

> +	},

> +

> +	/* CSIPHY1 */

> +	{

> +		.regulator = { NULL },

> +		.clock = { "camss_top_ahb_clk", "ispif_ahb_clk",

> +			   "camss_ahb_clk", "csiphy1_timer_clk" },

> +		.clock_rate = { 0, 0, 0, 200000000 },

> +		.reg = { "csiphy1", "csiphy1_clk_mux" },

> +		.interrupt = { "csiphy1" }

> +	}

> +};

> +

> +static struct resources csid_res[] = {

> +	/* CSID0 */

> +	{

> +		.regulator = { "vdda" },

> +		.clock = { "camss_top_ahb_clk", "ispif_ahb_clk",

> +			   "csi0_ahb_clk", "camss_ahb_clk",

> +			   "csi0_clk", "csi0_phy_clk",

> +			   "csi0_pix_clk", "csi0_rdi_clk" },

> +		.clock_rate = { 0, 0, 0, 0, 200000000, 0, 0, 0 },

> +		.reg = { "csid0" },

> +		.interrupt = { "csid0" }

> +	},

> +

> +	/* CSID1 */

> +	{

> +		.regulator = { "vdda" },

> +		.clock = { "camss_top_ahb_clk", "ispif_ahb_clk",

> +			   "csi1_ahb_clk", "camss_ahb_clk",

> +			   "csi1_clk", "csi1_phy_clk",

> +			   "csi1_pix_clk", "csi1_rdi_clk" },

> +		.clock_rate = { 0, 0, 0, 0, 200000000, 0, 0, 0 },

> +		.reg = { "csid1" },

> +		.interrupt = { "csid1" }

> +	},

> +};

> +

> +static struct resources_ispif ispif_res = {

> +	/* ISPIF */

> +	.clock = { "camss_top_ahb_clk", "camss_ahb_clk", "ispif_ahb_clk",

> +		   "csi0_clk", "csi0_pix_clk", "csi0_rdi_clk",

> +		   "csi1_clk", "csi1_pix_clk", "csi1_rdi_clk" },

> +	.clock_for_reset = { "camss_vfe_vfe_clk", "camss_csi_vfe_clk" },

> +	.reg = { "ispif", "csi_clk_mux" },

> +	.interrupt = "ispif"

> +

> +};

> +

> +static struct resources vfe_res = {

> +	/* VFE0 */

> +	.regulator = { NULL },

> +	.clock = { "camss_top_ahb_clk", "camss_vfe_vfe_clk",

> +		   "camss_csi_vfe_clk", "iface_clk",

> +		   "bus_clk", "camss_ahb_clk" },

> +	.clock_rate = { 0, 320000000, 0, 0, 0, 0, 0, 0 },

> +	.reg = { "vfe0" },

> +	.interrupt = { "vfe0" }

> +};


Could these be const?

> +

> +/*

> + * camss_enable_clocks - Enable multiple clocks

> + * @nclocks: Number of clocks in clock array

> + * @clock: Clock array

> + * @dev: Device

> + *

> + * Return 0 on success or a negative error code otherwise

> + */

> +int camss_enable_clocks(int nclocks, struct clk **clock, struct device *dev)

> +{

> +	int ret;

> +	int i;

> +

> +	for (i = 0; i < nclocks; i++) {

> +		ret = clk_prepare_enable(clock[i]);

> +		if (ret) {

> +			dev_err(dev, "clock enable failed\n");

> +			goto error;

> +		}

> +	}

> +

> +	return 0;

> +

> +error:

> +	for (i--; i >= 0; i--)

> +		clk_disable_unprepare(clock[i]);

> +

> +	return ret;

> +}

> +

> +/*

> + * camss_disable_clocks - Disable multiple clocks

> + * @nclocks: Number of clocks in clock array

> + * @clock: Clock array

> + */

> +void camss_disable_clocks(int nclocks, struct clk **clock)

> +{

> +	int i;

> +

> +	for (i = nclocks - 1; i >= 0; i--)

> +		clk_disable_unprepare(clock[i]);

> +}

> +

> +/*

> + * camss_of_parse_endpoint_node - Parse port endpoint node

> + * @dev: Device

> + * @node: Device node to be parsed

> + * @csd: Parsed data from port endpoint node

> + *

> + * Return 0 on success or a negative error code on failure

> + */

> +static int camss_of_parse_endpoint_node(struct device *dev,

> +					struct device_node *node,

> +					struct camss_async_subdev *csd)

> +{

> +	struct csiphy_lanes_cfg *lncfg = &csd->interface.csi2.lane_cfg;

> +	int *settle_cnt = &csd->interface.csi2.settle_cnt;

> +	struct v4l2_of_bus_mipi_csi2 *mipi_csi2;

> +	struct v4l2_of_endpoint vep = { { 0 } };


Could you rebase on the current media-tree master?

The V4L2 OF framework has been replaced by the V4L2 fwnode framework, with
similar functionality. Mostly changes required are just switching from
v4l2_of_ to v4l2_fwnode_.

> +	unsigned int i;

> +

> +	v4l2_of_parse_endpoint(node, &vep);

> +

> +	csd->interface.csiphy_id = vep.base.port;

> +

> +	mipi_csi2 = &vep.bus.mipi_csi2;

> +	lncfg->clk.pos = mipi_csi2->clock_lane;

> +	lncfg->clk.pol = mipi_csi2->lane_polarities[0];

> +	lncfg->num_data = mipi_csi2->num_data_lanes;

> +

> +	lncfg->data = devm_kzalloc(dev, lncfg->num_data * sizeof(*lncfg->data),

> +				   GFP_KERNEL);

> +	if (!lncfg->data)

> +		return -ENOMEM;

> +

> +	for (i = 0; i < lncfg->num_data; i++) {

> +		lncfg->data[i].pos = mipi_csi2->data_lanes[i];

> +		lncfg->data[i].pol = mipi_csi2->lane_polarities[i + 1];

> +	}

> +

> +	of_property_read_u32(node, "qcom,settle-cnt", settle_cnt);


Isn't this something that depends on the CSI-2 bus speed, for instance?
Could you calculate it instead of putting it to DT?

> +

> +	return 0;

> +}

> +

> +/*

> + * camss_of_parse_ports - Parse ports node

> + * @dev: Device

> + * @notifier: v4l2_device notifier data

> + *

> + * Return number of "port" nodes found in "ports" node

> + */

> +static int camss_of_parse_ports(struct device *dev,

> +				struct v4l2_async_notifier *notifier)

> +{

> +	struct device_node *node = NULL;

> +	unsigned int size, i;

> +	int ret;

> +

> +	while ((node = of_graph_get_next_endpoint(dev->of_node, node)))

> +		if (of_device_is_available(node))

> +			notifier->num_subdevs++;

> +

> +	size = sizeof(*notifier->subdevs) * notifier->num_subdevs;

> +	notifier->subdevs = devm_kzalloc(dev, size, GFP_KERNEL);

> +	if (!notifier->subdevs) {

> +		dev_err(dev, "Failed to allocate memory\n");

> +		return -ENOMEM;

> +	}

> +

> +	i = 0;

> +	while ((node = of_graph_get_next_endpoint(dev->of_node, node))) {

> +		struct camss_async_subdev *csd;

> +

> +		if (!of_device_is_available(node))

> +			continue;

> +

> +		csd = devm_kzalloc(dev, sizeof(*csd), GFP_KERNEL);

> +		if (!csd) {

> +			of_node_put(node);

> +			dev_err(dev, "Failed to allocate memory\n");

> +			return -ENOMEM;

> +		}

> +

> +		notifier->subdevs[i++] = &csd->asd;

> +

> +		ret = camss_of_parse_endpoint_node(dev, node, csd);

> +		if (ret < 0) {

> +			of_node_put(node);

> +			return ret;

> +		}

> +

> +		csd->asd.match.of.node = of_graph_get_remote_port_parent(node);

> +		of_node_put(node);

> +		if (!csd->asd.match.of.node) {

> +			dev_err(dev, "Bad remote port parent\n");

> +			return -EINVAL;

> +		}

> +

> +		csd->asd.match_type = V4L2_ASYNC_MATCH_OF;

> +	}

> +

> +	return notifier->num_subdevs;

> +}

> +

> +/*

> + * camss_init_subdevices - Initialize subdev structures and resources

> + * @camss: CAMSS device

> + *

> + * Return 0 on success or a negative error code on failure

> + */

> +static int camss_init_subdevices(struct camss *camss)

> +{

> +	unsigned int i;

> +	int ret;

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csiphy); i++) {

> +		ret = msm_csiphy_subdev_init(&camss->csiphy[i],

> +					     &csiphy_res[i], i);

> +		if (ret < 0) {

> +			dev_err(camss->dev,

> +				"Failed to init csiphy%d sub-device\n", i);

> +			return ret;

> +		}

> +	}

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csid); i++) {

> +		ret = msm_csid_subdev_init(&camss->csid[i],

> +					   &csid_res[i], i);

> +		if (ret < 0) {

> +			dev_err(camss->dev,

> +				"Failed to init csid%d sub-device\n", i);

> +			return ret;

> +		}

> +	}

> +

> +	ret = msm_ispif_subdev_init(&camss->ispif, &ispif_res);

> +	if (ret < 0) {

> +		dev_err(camss->dev, "Failed to init ispif sub-device\n");

> +		return ret;

> +	}

> +

> +	ret = msm_vfe_subdev_init(&camss->vfe, &vfe_res);

> +	if (ret < 0) {

> +		dev_err(camss->dev, "Fail to init vfe sub-device\n");

> +		return ret;

> +	}

> +

> +	return 0;

> +}

> +

> +/*

> + * camss_register_entities - Register subdev nodes and create links

> + * @camss: CAMSS device

> + *

> + * Return 0 on success or a negative error code on failure

> + */

> +static int camss_register_entities(struct camss *camss)

> +{

> +	int i, j;

> +	int ret;

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csiphy); i++) {

> +		ret = msm_csiphy_register_entity(&camss->csiphy[i],

> +						 &camss->v4l2_dev);

> +		if (ret < 0) {

> +			dev_err(camss->dev,

> +				"Failed to register csiphy%d entity\n", i);

> +			goto err_reg_csiphy;

> +		}

> +	}

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csid); i++) {

> +		ret = msm_csid_register_entity(&camss->csid[i],

> +					       &camss->v4l2_dev);

> +		if (ret < 0) {

> +			dev_err(camss->dev,

> +				"Failed to register csid%d entity\n", i);

> +			goto err_reg_csid;

> +		}

> +	}

> +

> +	ret = msm_ispif_register_entities(&camss->ispif, &camss->v4l2_dev);

> +	if (ret < 0) {

> +		dev_err(camss->dev, "Failed to register ispif entities\n");

> +		goto err_reg_ispif;

> +	}


Could you send the media graph (i.e. media-ctl --print-dot) for the device,
please? That'd help understanding the topoogy quite well.

> +

> +	ret = msm_vfe_register_entities(&camss->vfe, &camss->v4l2_dev);

> +	if (ret < 0) {

> +		dev_err(camss->dev, "Failed to register vfe entities\n");

> +		goto err_reg_vfe;

> +	}

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csiphy); i++) {

> +		for (j = 0; j < ARRAY_SIZE(camss->csid); j++) {

> +			ret = media_create_pad_link(

> +				&camss->csiphy[i].subdev.entity,

> +				MSM_CSIPHY_PAD_SRC,

> +				&camss->csid[j].subdev.entity,

> +				MSM_CSID_PAD_SINK,

> +				0);

> +			if (ret < 0) {

> +				dev_err(camss->dev,

> +					"Failed to link %s->%s entities\n",

> +					camss->csiphy[i].subdev.entity.name,

> +					camss->csid[j].subdev.entity.name);

> +				goto err_link;

> +			}

> +		}

> +	}

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csid); i++) {

> +		for (j = 0; j < ARRAY_SIZE(camss->ispif.line); j++) {

> +			ret = media_create_pad_link(

> +				&camss->csid[i].subdev.entity,

> +				MSM_CSID_PAD_SRC,

> +				&camss->ispif.line[j].subdev.entity,

> +				MSM_ISPIF_PAD_SINK,

> +				0);

> +			if (ret < 0) {

> +				dev_err(camss->dev,

> +					"Failed to link %s->%s entities\n",

> +					camss->csid[i].subdev.entity.name,

> +					camss->ispif.line[j].subdev.entity.name

> +					);

> +				goto err_link;

> +			}

> +		}

> +	}

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->ispif.line); i++) {

> +		for (j = 0; j < ARRAY_SIZE(camss->vfe.line); j++) {

> +			ret = media_create_pad_link(

> +				&camss->ispif.line[i].subdev.entity,

> +				MSM_ISPIF_PAD_SRC,

> +				&camss->vfe.line[j].subdev.entity,

> +				MSM_VFE_PAD_SINK,

> +				0);

> +			if (ret < 0) {

> +				dev_err(camss->dev,

> +					"Failed to link %s->%s entities\n",

> +					camss->ispif.line[i].subdev.entity.name,

> +					camss->vfe.line[j].subdev.entity.name);

> +				goto err_link;

> +			}

> +		}

> +	}

> +

> +	return 0;

> +

> +err_link:

> +	msm_vfe_unregister_entities(&camss->vfe);

> +err_reg_vfe:

> +	msm_ispif_unregister_entities(&camss->ispif);

> +err_reg_ispif:

> +

> +	i = ARRAY_SIZE(camss->csid);

> +err_reg_csid:

> +	for (i--; i >= 0; i--)

> +		msm_csid_unregister_entity(&camss->csid[i]);

> +

> +	i = ARRAY_SIZE(camss->csiphy);

> +err_reg_csiphy:

> +	for (i--; i >= 0; i--)

> +		msm_csiphy_unregister_entity(&camss->csiphy[i]);

> +

> +	return ret;

> +}

> +

> +/*

> + * camss_unregister_entities - Unregister subdev nodes

> + * @camss: CAMSS device

> + *

> + * Return 0 on success or a negative error code on failure

> + */

> +static void camss_unregister_entities(struct camss *camss)

> +{

> +	unsigned int i;

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csiphy); i++)

> +		msm_csiphy_unregister_entity(&camss->csiphy[i]);

> +

> +	for (i = 0; i < ARRAY_SIZE(camss->csid); i++)

> +		msm_csid_unregister_entity(&camss->csid[i]);

> +

> +	msm_ispif_unregister_entities(&camss->ispif);

> +	msm_vfe_unregister_entities(&camss->vfe);

> +}

> +

> +static int camss_subdev_notifier_bound(struct v4l2_async_notifier *async,

> +				       struct v4l2_subdev *subdev,

> +				       struct v4l2_async_subdev *asd)

> +{

> +	struct camss *camss = container_of(async, struct camss, notifier);

> +	struct camss_async_subdev *csd =

> +		container_of(asd, struct camss_async_subdev, asd);

> +	u8 id = csd->interface.csiphy_id;

> +	struct csiphy_device *csiphy = &camss->csiphy[id];

> +

> +	csiphy->cfg.csi2 = &csd->interface.csi2;

> +	subdev->host_priv = csiphy;

> +

> +	return 0;

> +}

> +

> +static int camss_subdev_notifier_complete(struct v4l2_async_notifier *async)

> +{

> +	struct camss *camss = container_of(async, struct camss, notifier);

> +	struct v4l2_device *v4l2_dev = &camss->v4l2_dev;

> +	struct v4l2_subdev *sd;

> +	int ret;

> +

> +	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {

> +		if (sd->host_priv) {


if (!sd->host_priv)
	continue;

And you can unindent the rest of the loop. Up to you.

> +			struct media_entity *sensor = &sd->entity;

> +			struct csiphy_device *csiphy =

> +					(struct csiphy_device *) sd->host_priv;

> +			struct media_entity *input = &csiphy->subdev.entity;

> +			unsigned int i;

> +

> +			for (i = 0; i < sensor->num_pads; i++) {

> +				if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE)

> +					break;

> +			}

> +			if (i == sensor->num_pads) {

> +				dev_err(camss->dev,

> +					"No source pad in external entity\n");

> +				return -EINVAL;

> +			}

> +

> +			ret = media_create_pad_link(sensor, i,

> +				input, MSM_CSIPHY_PAD_SINK,

> +				MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);

> +			if (ret < 0) {

> +				dev_err(camss->dev,

> +					"Failed to link %s->%s entities\n",

> +					sensor->name, input->name);

> +				return ret;

> +			}

> +		}

> +	}

> +

> +	ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev);

> +	if (ret < 0)

> +		return ret;

> +

> +	return media_device_register(&camss->media_dev);

> +}

> +

> +static const struct media_device_ops camss_media_ops = {

> +	.link_notify = v4l2_pipeline_link_notify,

> +};

> +

> +/*

> + * camss_probe - Probe CAMSS platform device

> + * @pdev: Pointer to CAMSS platform device

> + *

> + * Return 0 on success or a negative error code on failure

> + */

> +static int camss_probe(struct platform_device *pdev)

> +{

> +	struct device *dev = &pdev->dev;

> +	struct camss *camss;

> +	int ret;

> +

> +	camss = kzalloc(sizeof(*camss), GFP_KERNEL);

> +	if (!camss)

> +		return -ENOMEM;

> +

> +	atomic_set(&camss->ref_count, 0);

> +	camss->dev = dev;

> +	platform_set_drvdata(pdev, camss);

> +

> +	ret = camss_of_parse_ports(dev, &camss->notifier);

> +	if (ret < 0)

> +		return ret;

> +

> +	ret = camss_init_subdevices(camss);

> +	if (ret < 0)

> +		return ret;

> +

> +	ret = dma_set_mask_and_coherent(dev, 0xffffffff);

> +	if (ret)

> +		return ret;

> +

> +	camss->media_dev.dev = camss->dev;

> +	strlcpy(camss->media_dev.model, "Qualcomm Camera Subsystem",

> +		sizeof(camss->media_dev.model));

> +	camss->media_dev.ops = &camss_media_ops;

> +	media_device_init(&camss->media_dev);

> +

> +	camss->v4l2_dev.mdev = &camss->media_dev;

> +	ret = v4l2_device_register(camss->dev, &camss->v4l2_dev);

> +	if (ret < 0) {

> +		dev_err(dev, "Failed to register V4L2 device\n");

> +		return ret;

> +	}

> +

> +	ret = camss_register_entities(camss);

> +	if (ret < 0)

> +		goto err_register_entities;

> +

> +	if (camss->notifier.num_subdevs) {

> +		camss->notifier.bound = camss_subdev_notifier_bound;

> +		camss->notifier.complete = camss_subdev_notifier_complete;

> +

> +		ret = v4l2_async_notifier_register(&camss->v4l2_dev,

> +						   &camss->notifier);

> +		if (ret) {

> +			dev_err(dev, "Failed to register async subdev nodes");

> +			goto err_register_subdevs;

> +		}

> +	} else {

> +		ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev);

> +		if (ret < 0) {

> +			dev_err(dev, "Failed to register subdev nodes");

> +			goto err_register_subdevs;

> +		}

> +

> +		ret = media_device_register(&camss->media_dev);

> +		if (ret < 0) {

> +			dev_err(dev, "Failed to register media device");

> +			goto err_register_subdevs;

> +		}

> +	}

> +

> +	return 0;

> +

> +err_register_subdevs:

> +	camss_unregister_entities(camss);

> +err_register_entities:

> +	v4l2_device_unregister(&camss->v4l2_dev);

> +

> +	return ret;

> +}

> +

> +void camss_delete(struct camss *camss)

> +{

> +	v4l2_device_unregister(&camss->v4l2_dev);

> +	media_device_unregister(&camss->media_dev);

> +	media_device_cleanup(&camss->media_dev);

> +

> +	kfree(camss);

> +}

> +

> +/*

> + * camss_remove - Remove CAMSS platform device

> + * @pdev: Pointer to CAMSS platform device

> + *

> + * Always returns 0.

> + */

> +static int camss_remove(struct platform_device *pdev)

> +{

> +	struct camss *camss = platform_get_drvdata(pdev);

> +

> +	msm_vfe_stop_streaming(&camss->vfe);

> +

> +	v4l2_async_notifier_unregister(&camss->notifier);

> +	camss_unregister_entities(camss);

> +

> +	if (atomic_read(&camss->ref_count) == 0)

> +		camss_delete(camss);

> +

> +	return 0;

> +}

> +

> +static const struct of_device_id camss_dt_match[] = {

> +	{ .compatible = "qcom,msm8916-camss" },

> +	{ }

> +};

> +

> +MODULE_DEVICE_TABLE(of, camss_dt_match);

> +

> +static struct platform_driver qcom_camss_driver = {

> +	.probe = camss_probe,

> +	.remove = camss_remove,

> +	.driver = {

> +		.name = "qcom-camss",

> +		.of_match_table = camss_dt_match,

> +	},

> +};

> +

> +module_platform_driver(qcom_camss_driver);

> +

> +MODULE_ALIAS("platform:qcom-camss");

> +MODULE_DESCRIPTION("Qualcomm Camera Subsystem driver");

> +MODULE_LICENSE("GPL");


"GPL" or "GPL v2"?

> diff --git a/drivers/media/platform/qcom/camss-8x16/camss.h b/drivers/media/platform/qcom/camss-8x16/camss.h

> new file mode 100644

> index 0000000..e1a8b90

> --- /dev/null

> +++ b/drivers/media/platform/qcom/camss-8x16/camss.h

> @@ -0,0 +1,96 @@

> +/*

> + * camss.h

> + *

> + * Qualcomm MSM Camera Subsystem - Core

> + *

> + * Copyright (c) 2015, The Linux Foundation. All rights reserved.

> + * Copyright (C) 2015-2016 Linaro Ltd.

> + *

> + * This program is free software; you can redistribute it and/or modify

> + * it under the terms of the GNU General Public License version 2 and

> + * only version 2 as published by the Free Software Foundation.

> + *

> + * 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.

> + */

> +#ifndef QC_MSM_CAMSS_H

> +#define QC_MSM_CAMSS_H

> +

> +#include <linux/types.h>

> +#include <media/v4l2-async.h>

> +#include <media/v4l2-device.h>

> +#include <media/v4l2-subdev.h>

> +#include <media/media-device.h>

> +#include <media/media-entity.h>

> +#include <linux/device.h>

> +

> +#include "csid.h"

> +#include "csiphy.h"

> +#include "ispif.h"

> +#include "vfe.h"

> +

> +#define CAMSS_CSID_NUM 2

> +#define CAMSS_CSIPHY_NUM 2

> +

> +#define to_camss(ptr_module)	\

> +	container_of(ptr_module, struct camss, ptr_module)

> +

> +#define to_device(ptr_module)	\

> +	(to_camss(ptr_module)->dev)

> +

> +#define module_pointer(ptr_module, index)	\

> +	((const struct ptr_module##_device (*)[]) &(ptr_module[-(index)]))

> +

> +#define to_camss_index(ptr_module, index)	\

> +	container_of(module_pointer(ptr_module, index),	\

> +		     struct camss, ptr_module)

> +

> +#define to_device_index(ptr_module, index)	\

> +	(to_camss_index(ptr_module, index)->dev)

> +

> +#define CAMSS_RES_MAX 15

> +

> +struct resources {

> +	char *regulator[CAMSS_RES_MAX];

> +	char *clock[CAMSS_RES_MAX];

> +	s32 clock_rate[CAMSS_RES_MAX];

> +	char *reg[CAMSS_RES_MAX];

> +	char *interrupt[CAMSS_RES_MAX];

> +};

> +

> +struct resources_ispif {

> +	char *clock[CAMSS_RES_MAX];

> +	char *clock_for_reset[CAMSS_RES_MAX];

> +	char *reg[CAMSS_RES_MAX];

> +	char *interrupt;

> +};

> +

> +struct camss {

> +	struct v4l2_device v4l2_dev;

> +	struct v4l2_async_notifier notifier;

> +	struct media_device media_dev;

> +	struct device *dev;

> +	struct csiphy_device csiphy[CAMSS_CSIPHY_NUM];

> +	struct csid_device csid[CAMSS_CSID_NUM];

> +	struct ispif_device ispif;

> +	struct vfe_device vfe;

> +	atomic_t ref_count;

> +};

> +

> +struct camss_camera_interface {

> +	u8 csiphy_id;

> +	struct csiphy_csi2_cfg csi2;

> +};

> +

> +struct camss_async_subdev {

> +	struct camss_camera_interface interface;

> +	struct v4l2_async_subdev asd;

> +};

> +

> +int camss_enable_clocks(int nclocks, struct clk **clock, struct device *dev);

> +void camss_disable_clocks(int nclocks, struct clk **clock);

> +void camss_delete(struct camss *camss);

> +

> +#endif /* QC_MSM_CAMSS_H */


-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil July 3, 2017, 11:24 a.m. UTC | #2
On 06/19/2017 04:48 PM, Todor Tomov wrote:
> These files implement the platform driver code.

> 

> Signed-off-by: Todor Tomov <todor.tomov@linaro.org>

> ---

>   drivers/media/platform/qcom/camss-8x16/camss.c | 630 +++++++++++++++++++++++++

>   drivers/media/platform/qcom/camss-8x16/camss.h |  96 ++++

>   2 files changed, 726 insertions(+)

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.h

> 

> diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c

> new file mode 100644

> index 0000000..a8798d1

> --- /dev/null

> +++ b/drivers/media/platform/qcom/camss-8x16/camss.c

> @@ -0,0 +1,630 @@

> +/*

> + * camss.c

> + *

> + * Qualcomm MSM Camera Subsystem - Core

> + *

> + * Copyright (c) 2015, The Linux Foundation. All rights reserved.

> + * Copyright (C) 2015-2016 Linaro Ltd.

> + *

> + * This program is free software; you can redistribute it and/or modify

> + * it under the terms of the GNU General Public License version 2 and

> + * only version 2 as published by the Free Software Foundation.

> + *

> + * 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.

> + */

> +#include <linux/clk.h>

> +#include <linux/media-bus-format.h>

> +#include <linux/module.h>

> +#include <linux/platform_device.h>

> +#include <linux/of.h>

> +#include <linux/slab.h>

> +

> +#include <media/media-device.h>

> +#include <media/v4l2-async.h>

> +#include <media/v4l2-device.h>

> +#include <media/v4l2-mc.h>

> +#include <media/v4l2-of.h>


v4l2-of.h has been replaced by v4l2-fwnode.h. You need to rebase.

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil July 3, 2017, 11:36 a.m. UTC | #3
On 06/19/2017 04:48 PM, Todor Tomov wrote:
> This patchset adds basic support for the Qualcomm Camera Subsystem found

> on Qualcomm MSM8916 and APQ8016 processors.

> 

> The driver implements V4L2, Media controller and V4L2 subdev interfaces.

> Camera sensor using V4L2 subdev interface in the kernel is supported.

> 

> The driver is implemented using as a reference the Qualcomm Camera

> Subsystem driver for Android as found in Code Aurora [1].

> 

> The driver is tested on Dragonboard 410C (APQ8016) with one and two

> OV5645 camera sensors. media-ctl [2] and yavta [3] applications were

> used for testing. Also Gstreamer 1.10.4 with v4l2src plugin is supported.

> 

> More information is present in the document added by the third patch.

> 

> -------------------------------------------------------------------------------

> 

> Patchset Changelog:

> 

> Version 2:

> - patches 01-10 are updated from v1 following the review received and bugs

>    and limitaitons found after v1 was posted. The updates include:

>    - return buffers on unsuccessful stream on;

>    - fill device capabilities in struct video_device;

>    - simplify v4l2 file handle usage - no custom struct for file handle;

>    - use vb2_fop_poll and vb2_fop_mmap v4l2 file operations;

>    - add support for read/write I/O;

>    - add support for DMABUF streaming I/O;

>    - add support for EXPBUF and PREPARE_BUF ioctl;

>    - avoid a race condition between device unbind and userspace access

>      to the video node;

>    - use non-contiguous memory for video buffers;

>    - switch to V4L2 multi-planar API;

>    - add useful error messages in case of an overflow in ISPIF;

>    - other small and style fixes.

> 

> - patches 11-19 are new (they were not ready/posted with v1). I'm including

>    these in this patchset as they add valuable features and may be desired

>    for a real world usage of the driver.

> 

> -------------------------------------------------------------------------------

> 

> The patchset depends on:

> v4l: Add packed Bayer raw12 pixel formats [4]

> 

> -------------------------------------------------------------------------------

> 

> V4L2 compliance test result:

> 

> $ v4l2-compliance -s -d /dev/video0

> v4l2-compliance SHA   : ce237eefc1f6dafafc0e1fe3a5fd9f075d3fd066

> 

> Driver Info:

>          Driver name   : qcom-camss

>          Card type     : Qualcomm Camera Subsystem

>          Bus info      : platform:1b0ac00.camss

>          Driver version: 4.9.27

>          Capabilities  : 0x85201000

>                  Video Capture Multiplanar

>                  Read/Write

>                  Streaming

>                  Extended Pix Format

>                  Device Capabilities

>          Device Caps   : 0x05201000

>                  Video Capture Multiplanar

>                  Read/Write

>                  Streaming

>                  Extended Pix Format

> 

> Compliance test for device /dev/video0 (not using libv4l2):

> 

> Required ioctls:

>          test VIDIOC_QUERYCAP: OK

> 

> Allow for multiple opens:

>          test second video open: OK

>          test VIDIOC_QUERYCAP: OK

>          test VIDIOC_G/S_PRIORITY: OK

>          test for unlimited opens: OK

> 

> Debug ioctls:

>          test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)

>          test VIDIOC_LOG_STATUS: OK (Not Supported)

> 

> Input ioctls:

>          test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)

>          test VIDIOC_G/S_FREQUENCY: OK (Not Supported)

>          test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)

>          test VIDIOC_ENUMAUDIO: OK (Not Supported)

>          test VIDIOC_G/S/ENUMINPUT: OK

>          test VIDIOC_G/S_AUDIO: OK (Not Supported)

>          Inputs: 1 Audio Inputs: 0 Tuners: 0

> 

> Output ioctls:

>          test VIDIOC_G/S_MODULATOR: OK (Not Supported)

>          test VIDIOC_G/S_FREQUENCY: OK (Not Supported)

>          test VIDIOC_ENUMAUDOUT: OK (Not Supported)

>          test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)

>          test VIDIOC_G/S_AUDOUT: OK (Not Supported)

>          Outputs: 0 Audio Outputs: 0 Modulators: 0

> 

> Input/Output configuration ioctls:

>          test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)

>          test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)

>          test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)

>          test VIDIOC_G/S_EDID: OK (Not Supported)

> 

> Test input 0:

> 

>          Control ioctls:

>                  test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)

>                  test VIDIOC_QUERYCTRL: OK (Not Supported)

>                  test VIDIOC_G/S_CTRL: OK (Not Supported)

>                  test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)

>                  test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)

>                  test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)

>                  Standard Controls: 0 Private Controls: 0

> 

>          Format ioctls:

>                  test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK

>                  test VIDIOC_G/S_PARM: OK (Not Supported)

>                  test VIDIOC_G_FBUF: OK (Not Supported)

>                  test VIDIOC_G_FMT: OK

>                  test VIDIOC_TRY_FMT: OK

>                  test VIDIOC_S_FMT: OK

>                  test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

>                  test Cropping: OK (Not Supported)

>                  test Composing: OK (Not Supported)

>                  test Scaling: OK (Not Supported)

> 

>          Codec ioctls:

>                  test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)

>                  test VIDIOC_G_ENC_INDEX: OK (Not Supported)

>                  test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

> 

>          Buffer ioctls:

>                  test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK

>                  test VIDIOC_EXPBUF: OK

> 

> Test input 0:

> 

> Streaming ioctls:

>          test read/write: OK

>          test MMAP: OK

>          test USERPTR: OK (Not Supported)

>          test DMABUF: Cannot test, specify --expbuf-device

> 

> 

> Total: 46, Succeeded: 46, Failed: 0, Warnings: 0

> 

> -------------------------------------------------------------------------------

> 

> [1] https://source.codeaurora.org/quic/la/kernel/msm-3.10/

> [2] https://git.linuxtv.org//v4l-utils.git

> [3] http://git.ideasonboard.org/yavta.git

> [4] https://git.linuxtv.org/sailus/media_tree.git/commit/?h=packed12-postponed&id=549c02da6eed8dc4566632a9af9233bf99ba99d8

> 

> Todor Tomov (19):

>    doc: DT: camss: Binding document for Qualcomm Camera subsystem driver

>    MAINTAINERS: Add Qualcomm Camera subsystem driver

>    doc: media/v4l-drivers: Add Qualcomm Camera Subsystem driver document

>    media: camss: Add CSIPHY files

>    media: camss: Add CSID files

>    media: camss: Add ISPIF files

>    media: camss: Add VFE files

>    media: camss: Add files which handle the video device nodes

>    media: camms: Add core files

>    media: camss: Enable building

>    camss: vfe: Format conversion support using PIX interface

>    doc: media/v4l-drivers: Qualcomm Camera Subsystem - PIX Interface

>    camss: vfe: Support for frame padding

>    camss: vfe: Add interface for scaling

>    camss: vfe: Configure scaler module in VFE

>    camss: vfe: Add interface for cropping

>    camss: vfe: Configure crop module in VFE

>    doc: media/v4l-drivers: Qualcomm Camera Subsystem - Scale and crop

>    camss: Use optimal clock frequency rates

> 

>   .../devicetree/bindings/media/qcom,camss.txt       |  196 ++

>   Documentation/media/v4l-drivers/qcom_camss.rst     |  157 +

>   MAINTAINERS                                        |    8 +

>   drivers/media/platform/Kconfig                     |    6 +

>   drivers/media/platform/Makefile                    |    2 +

>   drivers/media/platform/qcom/camss-8x16/Makefile    |   11 +

>   drivers/media/platform/qcom/camss-8x16/camss.c     |  724 +++++

>   drivers/media/platform/qcom/camss-8x16/camss.h     |  105 +

>   drivers/media/platform/qcom/camss-8x16/csid.c      | 1141 ++++++++

>   drivers/media/platform/qcom/camss-8x16/csid.h      |   82 +

>   drivers/media/platform/qcom/camss-8x16/csiphy.c    |  821 ++++++

>   drivers/media/platform/qcom/camss-8x16/csiphy.h    |   77 +

>   drivers/media/platform/qcom/camss-8x16/ispif.c     | 1137 ++++++++

>   drivers/media/platform/qcom/camss-8x16/ispif.h     |   85 +

>   drivers/media/platform/qcom/camss-8x16/vfe.c       | 3046 ++++++++++++++++++++

>   drivers/media/platform/qcom/camss-8x16/vfe.h       |  123 +

>   drivers/media/platform/qcom/camss-8x16/video.c     |  842 ++++++

>   drivers/media/platform/qcom/camss-8x16/video.h     |   72 +


Can you add a 'camss-' prefix to these filenames? Except for the camss.c/h of
course :-)

It's good practice to make the filenames unique.

Thanks,

	Hans

>   18 files changed, 8635 insertions(+)

>   create mode 100644 Documentation/devicetree/bindings/media/qcom,camss.txt

>   create mode 100644 Documentation/media/v4l-drivers/qcom_camss.rst

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/Makefile

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/camss.h

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/csid.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/csid.h

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/csiphy.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/csiphy.h

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/ispif.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/ispif.h

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/vfe.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/vfe.h

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/video.c

>   create mode 100644 drivers/media/platform/qcom/camss-8x16/video.h

> 


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sakari Ailus July 4, 2017, 5:43 a.m. UTC | #4
Hi Todor,

On Mon, Jul 03, 2017 at 05:03:40PM +0300, Todor Tomov wrote:
> >> +	unsigned int i;

> >> +

> >> +	v4l2_of_parse_endpoint(node, &vep);

> >> +

> >> +	csd->interface.csiphy_id = vep.base.port;

> >> +

> >> +	mipi_csi2 = &vep.bus.mipi_csi2;

> >> +	lncfg->clk.pos = mipi_csi2->clock_lane;

> >> +	lncfg->clk.pol = mipi_csi2->lane_polarities[0];

> >> +	lncfg->num_data = mipi_csi2->num_data_lanes;

> >> +

> >> +	lncfg->data = devm_kzalloc(dev, lncfg->num_data * sizeof(*lncfg->data),

> >> +				   GFP_KERNEL);

> >> +	if (!lncfg->data)

> >> +		return -ENOMEM;

> >> +

> >> +	for (i = 0; i < lncfg->num_data; i++) {

> >> +		lncfg->data[i].pos = mipi_csi2->data_lanes[i];

> >> +		lncfg->data[i].pol = mipi_csi2->lane_polarities[i + 1];

> >> +	}

> >> +

> >> +	of_property_read_u32(node, "qcom,settle-cnt", settle_cnt);

> > 

> > Isn't this something that depends on the CSI-2 bus speed, for instance?

> > Could you calculate it instead of putting it to DT?

> 

> Actually, after some digging into this, yes, I can calculate it. I can

> calculate the CSI-2 bus speed based on the sensor's output pixel clock

> and then calculate the settle time and this settle count value.

> So I already have the code to get the sensor's pixel clock using the

> standard v4l2 control V4L2_CID_PIXEL_RATE.


What we have currently in documentation on this is here:

<URL:https://www.linuxtv.org/downloads/v4l-dvb-apis/kapi/csi2.html>

I.e. both should be implemented. The link frequency is rather more relevant
for CSI-2 albeit you can derive one from the other in case of CSI-2. The
pixel rate documentation should probably be rather elsewhere.

> Now the question is what to do if the sensor driver doesn't support this

> control? Just return an error and refuse to work with this "limited"

> sensor driver?


If the sensor driver does not provide enough information to work with a
receiver, it's only fair not to proceed with streaming. That said, it might
be possible to manage with some sensible defaults in some cases but then again
you could have only some units working with this configuration. It'd be
much safer to require the information: not doing so hides the error and
makes it (more) difficult to debug.

...

> >> +struct camss {

> >> +	struct v4l2_device v4l2_dev;

> >> +	struct v4l2_async_notifier notifier;

> >> +	struct media_device media_dev;

> >> +	struct device *dev;

> >> +	struct csiphy_device csiphy[CAMSS_CSIPHY_NUM];

> >> +	struct csid_device csid[CAMSS_CSID_NUM];

> >> +	struct ispif_device ispif;

> >> +	struct vfe_device vfe;

> >> +	atomic_t ref_count;


If this is refcount, then you should use refcount_t instead.

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html