Re: [RFC v2 05/10] exynos5-fimc-is: Adds the sensor subdev

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri May 31 2013 15:03:23 Arun Kumar K wrote:
> FIMC-IS uses certain sensors which are exclusively controlled
> from the IS firmware. This patch adds the sensor subdev for the
> fimc-is sensors.
> 
> Signed-off-by: Arun Kumar K <arun.kk@xxxxxxxxxxx>
> Signed-off-by: Kilyeon Im <kilyeon.im@xxxxxxxxxxx>

Not surprisingly I really hate the idea of sensor drivers that are tied to
a specific SoC, since it completely destroys the reusability of such drivers.

I understand that you have little choice to do something special here, but
I was wondering whether there is a way of keeping things as generic as
possible.

I'm just brainstorming here, but as far as I can see this driver is basically
a partial sensor driver: it handles the clock, the format negotiation and
power management. Any sensor driver needs that.

What would be nice is if the fmic specific parts are replaced by callbacks
into the bridge driver using v4l2_subdev_notify().

The platform data (or DT) can also state if this sensor is firmware controlled
or not. If not, then the missing bits can be implemented in the future by
someone who needs that.

That way the driver itself remains independent from fimc.

And existing sensor drivers can be adapted to be usable with fimc as well by
adding support for the notify callback.

Would a scheme along those lines work?

Regards,

	Hans

> ---
>  drivers/media/platform/exynos5-is/fimc-is-sensor.c |  463 ++++++++++++++++++++
>  drivers/media/platform/exynos5-is/fimc-is-sensor.h |  168 +++++++
>  2 files changed, 631 insertions(+)
>  create mode 100644 drivers/media/platform/exynos5-is/fimc-is-sensor.c
>  create mode 100644 drivers/media/platform/exynos5-is/fimc-is-sensor.h
> 
> diff --git a/drivers/media/platform/exynos5-is/fimc-is-sensor.c b/drivers/media/platform/exynos5-is/fimc-is-sensor.c
> new file mode 100644
> index 0000000..b8fb834
> --- /dev/null
> +++ b/drivers/media/platform/exynos5-is/fimc-is-sensor.c
> @@ -0,0 +1,463 @@
> +/*
> + * Samsung EXYNOS5250 FIMC-IS (Imaging Subsystem) driver
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + * Arun Kumar K <arun.kk@xxxxxxxxxxx>
> + * Kil-yeon Lim <kilyeon.im@xxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/i2c.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <media/v4l2-of.h>
> +#include "fimc-is-sensor.h"
> +#include "fimc-is.h"
> +
> +#define DRIVER_NAME "fimc-is-sensor"
> +
> +static char *sensor_clock_name[] = {
> +	[SCLK_BAYER]	= "sclk_bayer",
> +	[SCLK_CAM0]	= "sclk_cam0",
> +	[SCLK_CAM1]	= "sclk_cam1",
> +};
> +
> +/* Sensor supported formats */
> +static struct v4l2_mbus_framefmt sensor_formats[FIMC_IS_MAX_SENSORS] = {
> +	[SENSOR_S5K4E5] = {
> +		.width          = SENSOR_4E5_WIDTH + 16,
> +		.height         = SENSOR_4E5_HEIGHT + 10,
> +		.code           = V4L2_MBUS_FMT_SGRBG10_1X10,
> +		.field          = V4L2_FIELD_NONE,
> +		.colorspace     = V4L2_COLORSPACE_SRGB,
> +	},
> +	[SENSOR_S5K6A3] = {
> +		.width          = SENSOR_6A3_WIDTH + 16,
> +		.height         = SENSOR_6A3_HEIGHT + 10,
> +		.code           = V4L2_MBUS_FMT_SGRBG10_1X10,
> +		.field          = V4L2_FIELD_NONE,
> +		.colorspace     = V4L2_COLORSPACE_SRGB,
> +	},
> +};
> +
> +static struct fimc_is_sensor *sd_to_fimc_is_sensor(struct v4l2_subdev *sd)
> +{
> +	return container_of(sd, struct fimc_is_sensor, subdev);
> +}
> +
> +static void sensor_clk_put(struct fimc_is_sensor *sensor)
> +{
> +	int i;
> +
> +	for (i = 0; i < SCLK_MAX_NUM; i++) {
> +		if (IS_ERR(sensor->clock[i]))
> +			continue;
> +		clk_unprepare(sensor->clock[i]);
> +		clk_put(sensor->clock[i]);
> +		sensor->clock[i] = ERR_PTR(-EINVAL);
> +	}
> +}
> +
> +static int sensor_clk_init(struct fimc_is_sensor *sensor)
> +{
> +	int i, ret;
> +
> +	/* Get CAM clocks */
> +	for (i = 0; i < SCLK_MAX_NUM; i++) {
> +		sensor->clock[i] = clk_get(NULL, sensor_clock_name[i]);
> +		if (IS_ERR(sensor->clock[i]))
> +			goto err;
> +		ret = clk_prepare(sensor->clock[i]);
> +		if (ret < 0) {
> +			clk_put(sensor->clock[i]);
> +			sensor->clock[i] = ERR_PTR(-EINVAL);
> +			goto err;
> +		}
> +	}
> +
> +	/* Set clock rates */
> +	ret = clk_set_rate(sensor->clock[SCLK_CAM0], 24 * 1000000);
> +	ret |= clk_set_rate(sensor->clock[SCLK_BAYER], 24 * 1000000);
> +	if (ret) {
> +		pr_err("Failed to set cam clock rates\n");
> +		goto err;
> +	}
> +	return 0;
> +err:
> +	sensor_clk_put(sensor);
> +	pr_err("Failed to init sensor clock\n");
> +	return -ENXIO;
> +}
> +
> +static int sensor_clk_enable(struct fimc_is_sensor *sensor)
> +{
> +	int ret = 0, i;
> +
> +	for (i = 0; i < SCLK_MAX_NUM; i++) {
> +		ret = clk_enable(sensor->clock[i]);
> +		if (ret)
> +			return ret;
> +	}
> +	return ret;
> +}
> +
> +static void sensor_clk_disable(struct fimc_is_sensor *sensor)
> +{
> +	int i;
> +
> +	for (i = 0; i < SCLK_MAX_NUM; i++)
> +		clk_disable(sensor->clock[i]);
> +}
> +
> +static int sensor_enum_mbus_code(struct v4l2_subdev *sd,
> +				  struct v4l2_subdev_fh *fh,
> +				  struct v4l2_subdev_mbus_code_enum *code)
> +{
> +	struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
> +	struct fimc_is_sensor_drv_data *sdata = sensor->drvdata;
> +
> +	if (!code)
> +		return -EINVAL;
> +
> +	code->code = sensor_formats[sdata->sensor_id].code;
> +	return 0;
> +}
> +
> +static int sensor_set_fmt(struct v4l2_subdev *sd,
> +			  struct v4l2_subdev_fh *fh,
> +			  struct v4l2_subdev_format *fmt)
> +{
> +	struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
> +	struct fimc_is_sensor_drv_data *sdata = sensor->drvdata;
> +	struct v4l2_mbus_framefmt *sfmt = &fmt->format;
> +
> +	if ((sfmt->width != sensor_formats[sdata->sensor_id].width) ||
> +		(sfmt->height != sensor_formats[sdata->sensor_id].height) ||
> +		(sfmt->code != sensor_formats[sdata->sensor_id].code))
> +		*sfmt = sensor_formats[sdata->sensor_id];
> +
> +	return 0;
> +}
> +
> +static int sensor_get_fmt(struct v4l2_subdev *sd,
> +			  struct v4l2_subdev_fh *fh,
> +			  struct v4l2_subdev_format *fmt)
> +{
> +	struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
> +	struct fimc_is_sensor_drv_data *sdata = sensor->drvdata;
> +
> +	fmt->format = sensor_formats[sdata->sensor_id];
> +	return 0;
> +}
> +
> +static struct v4l2_subdev_pad_ops sensor_pad_ops = {
> +	.enum_mbus_code		= sensor_enum_mbus_code,
> +	.get_fmt		= sensor_get_fmt,
> +	.set_fmt		= sensor_set_fmt,
> +};
> +
> +static int sensor_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
> +
> +	*format = sensor_formats[0];
> +	return 0;
> +}
> +
> +static const struct v4l2_subdev_internal_ops sensor_sd_internal_ops = {
> +	.open = sensor_open,
> +};
> +
> +static int sensor_s_power(struct v4l2_subdev *sd, int on)
> +{
> +	struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
> +
> +	if (on) {
> +		/* Power on sensor */
> +		sensor_clk_enable(sensor);
> +		gpio_set_value(sensor->gpio_reset, 1);
> +	} else {
> +		/* Power off sensor */
> +		gpio_set_value(sensor->gpio_reset, 0);
> +		sensor_clk_disable(sensor);
> +	}
> +	return 0;
> +}
> +
> +static struct v4l2_subdev_core_ops sensor_core_ops = {
> +	.s_power = sensor_s_power,
> +};
> +
> +static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
> +{
> +	struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
> +	int ret;
> +
> +	if (enable) {
> +		pr_debug("Stream ON\n");
> +		/* Open pipeline */
> +		ret = fimc_is_pipeline_open(sensor->pipeline, sensor);
> +		if (ret < 0) {
> +			pr_err("Pipeline already opened.\n");
> +			return -EBUSY;
> +		}
> +
> +		/* Start IS pipeline */
> +		ret = fimc_is_pipeline_start(sensor->pipeline);
> +		if (ret < 0) {
> +			pr_err("Pipeline start failed.\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		pr_debug("Stream OFF\n");
> +		/* Stop IS pipeline */
> +		ret = fimc_is_pipeline_stop(sensor->pipeline);
> +		if (ret < 0) {
> +			pr_err("Pipeline stop failed.\n");
> +			return -EINVAL;
> +		}
> +
> +		/* Close pipeline */
> +		ret = fimc_is_pipeline_close(sensor->pipeline);
> +		if (ret < 0) {
> +			pr_err("Pipeline close failed\n");
> +			return -EBUSY;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_subdev_video_ops sensor_video_ops = {
> +	.s_stream       = sensor_s_stream,
> +};
> +
> +static struct v4l2_subdev_ops sensor_subdev_ops = {
> +	.core = &sensor_core_ops,
> +	.pad = &sensor_pad_ops,
> +	.video = &sensor_video_ops,
> +};
> +
> +static int sensor_parse_dt(struct fimc_is_sensor *sensor,
> +			struct device_node *sensor_node)
> +{
> +	struct device_node *port, *ep, *remote, *fimc_is_node, *camera;
> +	struct fimc_is *is_data;
> +	struct platform_device *pdev_is;
> +	struct v4l2_of_endpoint endpoint;
> +
> +	/* Parse ports */
> +	port = sensor_node;
> +	while ((port = of_get_next_child(port, NULL))) {
> +		if (!of_node_cmp(port->name, "port"))
> +			break;
> +		of_node_put(port);
> +	};
> +	if (!port) {
> +		pr_err("Sensor port undefined\n");
> +		return -EINVAL;
> +	}
> +
> +	ep = of_get_next_child(port, NULL);
> +	if (!ep)
> +		return -EINVAL;
> +
> +	port = of_parse_phandle(ep, "remote-endpoint", 0);
> +	if (port) {
> +		v4l2_of_parse_endpoint(port, &endpoint);
> +		sensor->i2c_ch = (endpoint.port >> 2) & 0x1;
> +	}
> +
> +	remote = v4l2_of_get_remote_port_parent(ep);
> +	of_node_put(ep);
> +
> +	if (!remote)
> +		return -EINVAL;
> +
> +	camera = of_get_parent(remote);
> +	fimc_is_node = NULL;
> +	while ((fimc_is_node = of_get_next_child(camera, fimc_is_node))) {
> +		if (!of_node_cmp(fimc_is_node->name, "fimc-is"))
> +			break;
> +		of_node_put(fimc_is_node);
> +	};
> +	of_node_put(camera);
> +
> +	if (!fimc_is_node)
> +		return -EINVAL;
> +
> +	/* Get the IS pipeline context */
> +	pdev_is = of_find_device_by_node(fimc_is_node);
> +	is_data = dev_get_drvdata(&pdev_is->dev);
> +
> +	if (!is_data)
> +		return -EINVAL;
> +
> +	sensor->pipeline = &is_data->pipeline;
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id fimc_is_sensor_of_match[];
> +
> +static int fimc_is_sensor_probe(struct i2c_client *client,
> +				const struct i2c_device_id *id)
> +{
> +	struct device *dev = &client->dev;
> +	struct fimc_is_sensor *sensor;
> +	const struct of_device_id *of_id;
> +	struct v4l2_subdev *sd;
> +	int gpio, ret;
> +	unsigned int sensor_id;
> +
> +	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
> +	if (!sensor)
> +		return -ENOMEM;
> +
> +	sensor->gpio_reset = -EINVAL;
> +
> +	gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
> +	if (gpio_is_valid(gpio)) {
> +		ret = gpio_request_one(gpio, GPIOF_OUT_INIT_LOW, DRIVER_NAME);
> +		if (ret < 0)
> +			return ret;
> +	}
> +	pr_err("GPIO Request success : %d", gpio);
> +	sensor->gpio_reset = gpio;
> +
> +	of_id = of_match_node(fimc_is_sensor_of_match, dev->of_node);
> +	if (!of_id) {
> +		ret = -ENODEV;
> +		goto err_gpio;
> +	}
> +
> +	sensor->drvdata = (struct fimc_is_sensor_drv_data *) of_id->data;
> +	sensor->dev = dev;
> +
> +	/* Get FIMC-IS context */
> +	ret = sensor_parse_dt(sensor, dev->of_node);
> +	if (ret) {
> +		pr_err("Unable to obtain IS context\n");
> +		ret = -ENODEV;
> +		goto err_gpio;
> +	}
> +
> +	sd = &sensor->subdev;
> +	v4l2_i2c_subdev_init(sd, client, &sensor_subdev_ops);
> +	snprintf(sd->name, sizeof(sd->name), sensor->drvdata->sensor_name);
> +	sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +
> +	sensor_id = sensor->drvdata->sensor_id;
> +	sensor->format.code = sensor_formats[sensor_id].code;
> +	sensor->format.width = sensor_formats[sensor_id].width;
> +	sensor->format.height = sensor_formats[sensor_id].height;
> +
> +	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
> +	ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
> +	if (ret < 0)
> +		goto err_gpio;
> +
> +	v4l2_set_subdevdata(sd, sensor);
> +	i2c_set_clientdata(client, &sensor->subdev);
> +
> +	pm_runtime_no_callbacks(dev);
> +	pm_runtime_enable(dev);
> +	sensor_clk_init(sensor);
> +
> +	return 0;
> +err_gpio:
> +	if (gpio_is_valid(sensor->gpio_reset))
> +		gpio_free(sensor->gpio_reset);
> +	return ret;
> +}
> +
> +static int fimc_is_sensor_remove(struct i2c_client *client)
> +{
> +	struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +	struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
> +
> +	media_entity_cleanup(&sensor->subdev.entity);
> +	sensor_clk_put(sensor);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id fimc_is_sensor_ids[] = {
> +	{ }
> +};
> +
> +static const struct fimc_is_sensor_drv_data s5k4e5_drvdata = {
> +	.sensor_id = SENSOR_S5K4E5,
> +	.sensor_name = "s5k4e5",
> +	.pixel_width = SENSOR_4E5_WIDTH + 16,
> +	.pixel_height = SENSOR_4E5_HEIGHT + 10,
> +	.active_width = SENSOR_4E5_WIDTH,
> +	.active_height = SENSOR_4E5_HEIGHT,
> +	.max_framerate = 30,
> +	.setfile_name = "setfile_4e5.bin",
> +	.ext = {
> +		.actuator_con = {
> +			.product_name = ACTUATOR_NAME_DWXXXX,
> +			.peri_type = SE_I2C,
> +			.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0,
> +		},
> +		.flash_con = {
> +			.product_name = FLADRV_NAME_KTD267,
> +			.peri_type = SE_GPIO,
> +			.peri_setting.gpio.first_gpio_port_no = 1,
> +			.peri_setting.gpio.second_gpio_port_no = 2,
> +		},
> +		.from_con.product_name = FROMDRV_NAME_NOTHING,
> +		.mclk = 0,
> +		.mipi_lane_num = 0,
> +		.mipi_speed = 0,
> +		.fast_open_sensor = 0,
> +		.self_calibration_mode = 0,
> +	},
> +};
> +
> +static const struct fimc_is_sensor_drv_data s5k6a3_drvdata = {
> +	.sensor_id = SENSOR_S5K6A3,
> +	.sensor_name = "s5k6a3",
> +	.pixel_width = SENSOR_6A3_WIDTH + 16,
> +	.pixel_height = SENSOR_6A3_HEIGHT + 10,
> +	.active_width = SENSOR_6A3_WIDTH,
> +	.active_height = SENSOR_6A3_HEIGHT,
> +	.max_framerate = 30,
> +	.setfile_name = "setfile_6a3.bin",
> +};
> +
> +static const struct of_device_id fimc_is_sensor_of_match[] = {
> +	{
> +		.compatible	= "samsung,s5k4e5",
> +		.data		= &s5k4e5_drvdata,
> +	},
> +	{
> +		.compatible	= "samsung,s5k6a3",
> +		.data		= &s5k6a3_drvdata,
> +	},
> +	{  }
> +};
> +MODULE_DEVICE_TABLE(of, fimc_is_sensor_of_match);
> +
> +static struct i2c_driver fimc_is_sensor_driver = {
> +	.driver = {
> +		.of_match_table	= fimc_is_sensor_of_match,
> +		.name		= DRIVER_NAME,
> +		.owner		= THIS_MODULE,
> +	},
> +	.probe		= fimc_is_sensor_probe,
> +	.remove		= fimc_is_sensor_remove,
> +	.id_table	= fimc_is_sensor_ids,
> +};
> +
> +module_i2c_driver(fimc_is_sensor_driver);
> +
> +MODULE_AUTHOR("Arun Kumar K <arun.kk@xxxxxxxxxxx>");
> +MODULE_DESCRIPTION("Exynos5 FIMC-IS sensor subdev driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/platform/exynos5-is/fimc-is-sensor.h b/drivers/media/platform/exynos5-is/fimc-is-sensor.h
> new file mode 100644
> index 0000000..75e5f20
> --- /dev/null
> +++ b/drivers/media/platform/exynos5-is/fimc-is-sensor.h
> @@ -0,0 +1,168 @@
> +/*
> + * Samsung EXYNOS5250 FIMC-IS (Imaging Subsystem) driver
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + * Arun Kumar K <arun.kk@xxxxxxxxxxx>
> + * Kil-yeon Lim <kilyeon.im@xxxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef FIMC_IS_SENSOR_H_
> +#define FIMC_IS_SENSOR_H_
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/videodev2.h>
> +#include <media/v4l2-subdev.h>
> +
> +#include "fimc-is-pipeline.h"
> +
> +#define FIMC_IS_MAX_CAMIF_CLIENTS	2
> +#define FIMC_IS_MAX_NAME_LEN		32
> +#define FIMC_IS_MAX_GPIO_NUM		32
> +#define UART_ISP_SEL			0
> +#define UART_ISP_RATIO			1
> +
> +#define FIMC_IS_MAX_SENSORS		4
> +
> +#define SENSOR_4E5_WIDTH		2560
> +#define SENSOR_4E5_HEIGHT		1920
> +#define SENSOR_6A3_WIDTH		1392
> +#define SENSOR_6A3_HEIGHT		1392
> +
> +enum sensor_id {
> +	SENSOR_S5K3H2	= 1,
> +	SENSOR_S5K6A3	= 2,
> +	SENSOR_S5K4E5	= 3,
> +	SENSOR_S5K3H7	= 4,
> +	SENSOR_CUSTOM	= 100,
> +	SENSOR_END
> +};
> +
> +enum sensor_channel {
> +	SENSOR_CONTROL_I2C0	 = 0,
> +	SENSOR_CONTROL_I2C1	 = 1
> +};
> +
> +enum actuator_name {
> +	ACTUATOR_NAME_AD5823	= 1,
> +	ACTUATOR_NAME_DWXXXX	= 2,
> +	ACTUATOR_NAME_AK7343	= 3,
> +	ACTUATOR_NAME_HYBRIDVCA	= 4,
> +	ACTUATOR_NAME_NOTHING	= 100,
> +	ACTUATOR_NAME_END
> +};
> +
> +enum flash_drv_name {
> +	FLADRV_NAME_KTD267	= 1,
> +	FLADRV_NAME_NOTHING	= 100,
> +	FLADRV_NAME_END
> +};
> +
> +enum from_name {
> +	FROMDRV_NAME_W25Q80BW	= 1,
> +	FROMDRV_NAME_NOTHING
> +};
> +
> +enum sensor_peri_type {
> +	SE_I2C,
> +	SE_SPI,
> +	SE_GPIO,
> +	SE_MPWM,
> +	SE_ADC,
> +	SE_NULL
> +};
> +
> +struct i2c_type {
> +	u32 channel;
> +	u32 slave_address;
> +	u32 speed;
> +};
> +
> +struct spi_type {
> +	u32 channel;
> +};
> +
> +struct gpio_type {
> +	u32 first_gpio_port_no;
> +	u32 second_gpio_port_no;
> +};
> +
> +union sensor_peri_format {
> +	struct i2c_type i2c;
> +	struct spi_type spi;
> +	struct gpio_type gpio;
> +};
> +
> +struct sensor_protocol {
> +	unsigned int product_name;
> +	enum sensor_peri_type peri_type;
> +	union sensor_peri_format peri_setting;
> +};
> +
> +struct fimc_is_sensor_ext {
> +	struct sensor_protocol actuator_con;
> +	struct sensor_protocol flash_con;
> +	struct sensor_protocol from_con;
> +
> +	unsigned int mclk;
> +	unsigned int mipi_lane_num;
> +	unsigned int mipi_speed;
> +	unsigned int fast_open_sensor;
> +	unsigned int self_calibration_mode;
> +};
> +
> +struct fimc_is_sensor_drv_data {
> +	unsigned int	sensor_id;
> +	char		*sensor_name;
> +	unsigned int	pixel_width;
> +	unsigned int	pixel_height;
> +	unsigned int	active_width;
> +	unsigned int	active_height;
> +	unsigned int	max_framerate;
> +	struct fimc_is_sensor_ext ext;
> +	char		*setfile_name;
> +};
> +
> +enum sensor_clks {
> +	SCLK_BAYER,
> +	SCLK_CAM0,
> +	SCLK_CAM1,
> +	SCLK_MAX_NUM,
> +};
> +
> +struct sensor_pix_format {
> +	enum v4l2_mbus_pixelcode code;
> +};
> +
> +/**
> + * struct fimc_is_sensor - fimc-is sensor context
> + * @pad: media pad
> + * @subdev: sensor subdev
> + * @clock: sensor clocks array
> + * @dev: sensor device ptr
> + * @pipeline: is pipeline context pointer
> + * @drvdata: sensor specific driver data
> + * @format: v4l2 mbus format for the subdev
> + * @gpio_reset: gpio pin to be used for sensor power on/off
> + * @i2c_ch: sensor's i2c channel number
> + */
> +struct fimc_is_sensor {
> +	struct media_pad		pad;
> +	struct v4l2_subdev		subdev;
> +	struct clk			*clock[SCLK_MAX_NUM];
> +	struct device			*dev;
> +
> +	struct fimc_is_pipeline		*pipeline;
> +	struct fimc_is_sensor_drv_data	*drvdata;
> +	struct v4l2_mbus_framefmt	format;
> +	int				gpio_reset;
> +	unsigned int			i2c_ch;
> +};
> +
> +#endif /* FIMC_IS_SENSOR_H_ */
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux