[PATCH v9 1/2] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang Acked-by: Rob Herring --- Changes in v9: None Changes in v8: None Changes in v7: - Add Acked-by tag. Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.15.0
[PATCH v9 2/2] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v9: - Use the new SPDX ids. Changes in v8: - As the registers are written at stream start, remove the written code from the set fmt function. Changes in v7: - Fix the wrong handle of default register configuration. - Add the missed assignment of ov7740->frmsize. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1216 4 files changed, 1233 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/MAINTAINERS b/MAINTAINERS index 7a52a66aa991..1de965009b13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10053,6 +10053,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index cb5d7ff82915..00b1c4c031d4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 548a9efce966..9b19ec7fcaf4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..0308ba437bbb --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1216 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017 Microchip Corporation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC0x10/* auto exposure cntrl */ + +#define REG_CLK0x11/* Clock control */ +#define REG_REG55 0x55/* Clock PLL DIV/PreDiv */ + +#define REG_REG12 0x12 + +#define REG_REG13 0x13/* auto/manual AGC, AEC, Write B
[PATCH v9 0/2] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v9: - Use the new SPDX ids. Changes in v8: - As the registers are written at stream start, remove the written code from the set fmt function. Changes in v7: - Add Acked-by tag. - Fix the wrong handle of default register configuration. - Add the missed assignment of ov7740->frmsize. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (2): media: ov7740: Document device tree bindings media: i2c: Add the ov7740 image sensor driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1216 5 files changed, 1280 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.15.0
[PATCH v8 2/2] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v8: - As the registers are written at stream start, remove the written code from the set fmt function. Changes in v7: - Fix the wrong handle of default register configuration. - Add the missed assignment of ov7740->frmsize. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1226 4 files changed, 1243 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/MAINTAINERS b/MAINTAINERS index 7a52a66aa991..1de965009b13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10053,6 +10053,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index cb5d7ff82915..00b1c4c031d4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 548a9efce966..9b19ec7fcaf4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..536971e8ce8b --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1226 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define
[PATCH v8 1/2] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang Acked-by: Rob Herring --- Changes in v8: None Changes in v7: - Add Acked-by tag. Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.15.0
[PATCH v8 0/2] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v8: - As the registers are written at stream start, remove the written code from the set fmt function. Changes in v7: - Add Acked-by tag. - Fix the wrong handle of default register configuration. - Add the missed assignment of ov7740->frmsize. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (2): media: ov7740: Document device tree bindings media: i2c: Add the ov7740 image sensor driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1226 5 files changed, 1290 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.15.0
[PATCH v7 0/2] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v7: - Add Acked-by tag. - Fix the wrong handle of default register configuration. - Add the missed assignment of ov7740->frmsize. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (2): media: ov7740: Document device tree bindings media: i2c: Add the ov7740 image sensor driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1234 5 files changed, 1298 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.15.0
[PATCH v7 2/2] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v7: - Fix the wrong handle of default register configuration. - Add the missed assignment of ov7740->frmsize. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1234 4 files changed, 1251 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/MAINTAINERS b/MAINTAINERS index 7a52a66aa991..1de965009b13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10053,6 +10053,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index cb5d7ff82915..00b1c4c031d4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 548a9efce966..9b19ec7fcaf4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..26b56a627377 --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1234 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC
[PATCH v7 1/2] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang Acked-by: Rob Herring --- Changes in v7: - Add Acked-by tag. Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.15.0
[PATCH v6 2/2] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1226 4 files changed, 1243 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/MAINTAINERS b/MAINTAINERS index 7a52a66aa991..1de965009b13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10053,6 +10053,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index cb5d7ff82915..00b1c4c031d4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 548a9efce966..9b19ec7fcaf4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..42c25277d005 --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1226 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC0x10/* auto exposure cntrl */ + +#define REG_CLK0x11/* Clock control */ +#define REG_REG55 0x
[PATCH v6 1/2] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang --- Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.15.0
[PATCH v6 0/2] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v6: - Remove unnecessary #include . - Remove unnecessary comments and extra newline. - Add const for some structures. - Add the check of the return value from regmap_write(). - Simplify the calling of __v4l2_ctrl_handler_setup(). - Add the default format initialization function. - Integrate the set_power() and enable/disable the clock into one function. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (2): media: ov7740: Document device tree bindings media: i2c: Add the ov7740 image sensor driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1226 5 files changed, 1290 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.15.0
[PATCH v5 2/2] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 4 files changed, 1237 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/MAINTAINERS b/MAINTAINERS index aa71ab52fd76..19086a073ae9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10053,6 +10053,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 3c6d6428f525..ac484bb82fae 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 548a9efce966..9b19ec7fcaf4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..b2ec015bf3f6 --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1220 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC0x10/* auto exposure cntrl */ + +#define REG_CLK0x11/* Clock control */ +#define REG_REG55 0x55/* Clock PLL DIV/PreDiv */ + +#define REG_REG12 0x12 + +#define REG_REG13 0x13/* auto/manual AGC, AEC, Write Balance*/ +#define REG13_AEC_EN 0x01 +#define REG13_AGC_EN 0x04 + +#define REG_REG14 0x14 +#define REG_CTRL15 0x15 +#define REG15_GAIN_MSB 0x03 + +#define REG_REG16 0x16 + +#define REG_MIDH 0x1C/* man
[PATCH v5 1/2] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang --- Changes in v5: None Changes in v4: None Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.15.0
[PATCH v5 0/2] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v5: - Squash the driver and MAINTAINERS entry patches to one. - Precede the driver patch with the bindings patch. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (2): media: ov7740: Document device tree bindings media: i2c: Add the ov7740 image sensor driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 5 files changed, 1284 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.15.0
[PATCH v4 3/3] MAINTAINERS: Add a new entry of the ov7740 driver
Add a new entry of the ov7740 sensor driver to the MAINTAINERS file. Signed-off-by: Wenyou Yang --- Changes in v4: None Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS | 8 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index adbf69306e9e..42b93599a0af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9973,6 +9973,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org -- 2.13.0
[PATCH v4 2/3] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang --- Changes in v4: None Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.13.0
[PATCH v4 1/3] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: None Changes in v2: None drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 3 files changed, 1229 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 3c6d6428f525..ac484bb82fae 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index f8d57e453936..be800c674e8d 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..b2ec015bf3f6 --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1220 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC0x10/* auto exposure cntrl */ + +#define REG_CLK0x11/* Clock control */ +#define REG_REG55 0x55/* Clock PLL DIV/PreDiv */ + +#define REG_REG12 0x12 + +#define REG_REG13 0x13/* auto/manual AGC, AEC, Write Balance*/ +#define REG13_AEC_EN 0x01 +#define REG13_AGC_EN 0x04 + +#define REG_REG14 0x14 +#define REG_CTRL15 0x15 +#define REG15_GAIN_MSB 0x03 + +#define REG_REG16 0x16 + +#define REG_MIDH 0x1C/* manufacture id byte */ +#define REG_MIDL 0x1D/* manufacture id byre */ +#define REG_PIDH 0x0A/* Product ID MSB */ +#define REG_PIDL 0x0B/* Product ID LSB */ + +#define REG_84 0x84/* lots of stuff */ +#define REG_REG38 0x38/* sub-addr */ + +#define REG_AHSTART0x17/* Horiz start high bits */ +#define REG_AHSIZE 0x18 +#define REG_AVSTART0x19/* Vert start high bits */ +#define REG_AVSIZE 0x1A +#define REG_PSHFT 0x1b/* Pixel delay after HREF */ + +#define REG_HOUTSIZE 0x31 +#define REG_VOUTSIZE 0x32 +#define REG_HVSIZEOFF 0x33 +#define REG_REG34 0x34/* DSP output size H/V LSB*/ + +#define REG_ISP_CTRL00 0x80 +#define ISPCTRL00_AWB_EN 0x10 +#define ISPCTRL00_AWB_GAIN_EN 0x04 + +#defineREG_YGAIN 0xE2/* ygain for contrast control */ + +#defineREG_YBRIGHT 0xE3
[PATCH v4 0/3] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v4: - Assign 'val' a initial value to avoid warning: 'val' may be used uninitialized. - Rename REG_REG15 to avoid warning: "REG_REG15" redefined. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (3): media: i2c: Add the ov7740 image sensor driver media: ov7740: Document device tree bindings MAINTAINERS: Add a new entry of the ov7740 driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 5 files changed, 1284 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.13.0
[PATCH v3 3/3] MAINTAINERS: Add a new entry of the ov7740 driver
Add a new entry of the ov7740 sensor driver to the MAINTAINERS file. Signed-off-by: Wenyou Yang --- Changes in v3: - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. MAINTAINERS | 8 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index adbf69306e9e..42b93599a0af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9973,6 +9973,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org -- 2.13.0
[PATCH v3 2/3] media: ov7740: Document device tree bindings
Add the device tree binding documentation for the ov7740 sensor driver. Signed-off-by: Wenyou Yang --- Changes in v3: - Explicitly document the "remote-endpoint" property. Changes in v2: None .../devicetree/bindings/media/i2c/ov7740.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..af781c3a5f0e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,47 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +The common video interfaces bindings (see video-interfaces.txt) should +be used to specify link to the image data receiver. The OV7740 device +node should contain one 'port' child node with an 'endpoint' subnode. + +Required Properties: +- compatible: "ovti,ov7740". +- reg: I2C slave address of the sensor. +- clocks: Reference to the xvclk input clock. +- clock-names: "xvclk". + +Optional Properties: +- reset-gpios: Rreference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: Reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +Endpoint node mandatory properties: +- remote-endpoint: A phandle to the bus receiver's endpoint node. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; -- 2.13.0
[PATCH v3 0/3] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v3: - Explicitly document the "remote-endpoint" property. - Put the MAINTAINERS change to a separate patch. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (3): media: i2c: Add the ov7740 image sensor driver media: ov7740: Document device tree bindings MAINTAINERS: Add a new entry of the ov7740 driver .../devicetree/bindings/media/i2c/ov7740.txt | 47 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 5 files changed, 1284 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.13.0
[PATCH v3 1/3] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v3: None Changes in v2: None drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 3 files changed, 1229 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 3c6d6428f525..ac484bb82fae 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -665,6 +665,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index f8d57e453936..be800c674e8d 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..d68add05b46e --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1220 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC0x10/* auto exposure cntrl */ + +#define REG_CLK0x11/* Clock control */ +#define REG_REG55 0x55/* Clock PLL DIV/PreDiv */ + +#define REG_REG12 0x12 + +#define REG_REG13 0x13/* auto/manual AGC, AEC, Write Balance*/ +#define REG13_AEC_EN 0x01 +#define REG13_AGC_EN 0x04 + +#define REG_REG14 0x14 +#define REG_REG15 0x15 +#define REG15_GAIN_MSB 0x03 + +#define REG_REG16 0x16 + +#define REG_MIDH 0x1C/* manufacture id byte */ +#define REG_MIDL 0x1D/* manufacture id byre */ +#define REG_PIDH 0x0A/* Product ID MSB */ +#define REG_PIDL 0x0B/* Product ID LSB */ + +#define REG_84 0x84/* lots of stuff */ +#define REG_REG38 0x38/* sub-addr */ + +#define REG_AHSTART0x17/* Horiz start high bits */ +#define REG_AHSIZE 0x18 +#define REG_AVSTART0x19/* Vert start high bits */ +#define REG_AVSIZE 0x1A +#define REG_PSHFT 0x1b/* Pixel delay after HREF */ + +#define REG_HOUTSIZE 0x31 +#define REG_VOUTSIZE 0x32 +#define REG_HVSIZEOFF 0x33 +#define REG_REG34 0x34/* DSP output size H/V LSB*/ + +#define REG_ISP_CTRL00 0x80 +#define ISPCTRL00_AWB_EN 0x10 +#define ISPCTRL00_AWB_GAIN_EN 0x04 + +#defineREG_YGAIN 0xE2/* ygain for contrast control */ + +#defineREG_YBRIGHT 0xE3 +#defineREG_SGNSET0xE4 +#defineSGNSET_YBRIGHT_MASK 0x08 + +#define REG_USAT 0xDD +#define REG_VSAT 0xDE + + +struct ov7740 { + struct v4l2_subdev
[PATCH] media: atmel-isc: Fix clock ID for clk_prepare/unprepare
Fix the clock ID to do the runtime pm should be ISC_ISPCK, instead of ISC_MCK in clk_prepare(), clk_unprepare() and isc_clk_is_enabled(). Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 2c40a7886542..9294ff0c7b83 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -598,7 +598,7 @@ static int isc_clk_prepare(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); - if (isc_clk->id == ISC_MCK) + if (isc_clk->id == ISC_ISPCK) pm_runtime_get_sync(isc_clk->dev); return isc_wait_clk_stable(hw); @@ -610,7 +610,7 @@ static void isc_clk_unprepare(struct clk_hw *hw) isc_wait_clk_stable(hw); - if (isc_clk->id == ISC_MCK) + if (isc_clk->id == ISC_ISPCK) pm_runtime_put_sync(isc_clk->dev); } @@ -657,12 +657,12 @@ static int isc_clk_is_enabled(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 status; - if (isc_clk->id == ISC_MCK) + if (isc_clk->id == ISC_ISPCK) pm_runtime_get_sync(isc_clk->dev); regmap_read(isc_clk->regmap, ISC_CLKSR, &status); - if (isc_clk->id == ISC_MCK) + if (isc_clk->id == ISC_ISPCK) pm_runtime_put_sync(isc_clk->dev); return status & ISC_CLK(isc_clk->id) ? 1 : 0; -- 2.13.0
[PATCH v2 2/2] media: ov7740: Document device tree bindings
Add the device tree binding documentation for ov7740 driver and add a new entry of ov7740 to the MAINTAINERS file. Signed-off-by: Wenyou Yang --- Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. .../devicetree/bindings/media/i2c/ov7740.txt | 43 ++ MAINTAINERS| 8 2 files changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..b306e5aa97bf --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,43 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +Required Properties: +- compatible: should be "ovti,ov7740" +- clocks: reference to the xvclk input clock. +- clock-names: should be "xvclk". + +Optional Properties: +- reset-gpios: reference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +The device node must contain one 'port' child node for its digital +output video port, in accordance with the video interface bindings +defined in Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 90230fe020f3..f0f3f121d1d8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9965,6 +9965,14 @@ S: Maintained F: drivers/media/i2c/ov7670.c F: Documentation/devicetree/bindings/media/i2c/ov7670.txt +OMNIVISION OV7740 SENSOR DRIVER +M: Wenyou Yang +L: linux-me...@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/ov7740.c +F: Documentation/devicetree/bindings/media/i2c/ov7740.txt + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-...@lists.infradead.org -- 2.13.0
[PATCH v2 0/2] media: ov7740: Add a V4L2 sensor-level driver
Add a Video4Linux2 sensor-level driver for the OmniVision OV7740 VGA camera image sensor. Changes in v2: - Split off the bindings into a separate patch. - Add a new entry to the MAINTAINERS file. Wenyou Yang (2): media: i2c: Add the ov7740 image sensor driver media: ov7740: Document device tree bindings .../devicetree/bindings/media/i2c/ov7740.txt | 43 + MAINTAINERS|8 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 5 files changed, 1280 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c -- 2.13.0
[PATCH v2 1/2] media: i2c: Add the ov7740 image sensor driver
The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 3 files changed, 1229 insertions(+) create mode 100644 drivers/media/i2c/ov7740.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 47113774a297..402ad0e4024c 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -657,6 +657,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index c843c181dfb9..f94cb2a8ed91 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..d68add05b46e --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1220 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#define REG_GAIN 0x00/* Gain lower 8 bits (rest in vref) */ +#define REG_BGAIN 0x01/* blue gain */ +#define REG_RGAIN 0x02/* red gain */ +#define REG_GGAIN 0x03/* green gain */ +#define REG_REG04 0x04/* analog setting, dont change*/ +#define REG_BAVG 0x05/* b channel average */ +#define REG_GAVG 0x06/* g channel average */ +#define REG_RAVG 0x07/* r channel average */ + +#define REG_REG0C 0x0C/* filp enable */ +#define REG0C_IMG_FLIP 0x80 +#define REG0C_IMG_MIRROR 0x40 + +#define REG_REG0E 0x0E/* blc line */ +#define REG_HAEC 0x0F/* auto exposure cntrl */ +#define REG_AEC0x10/* auto exposure cntrl */ + +#define REG_CLK0x11/* Clock control */ +#define REG_REG55 0x55/* Clock PLL DIV/PreDiv */ + +#define REG_REG12 0x12 + +#define REG_REG13 0x13/* auto/manual AGC, AEC, Write Balance*/ +#define REG13_AEC_EN 0x01 +#define REG13_AGC_EN 0x04 + +#define REG_REG14 0x14 +#define REG_REG15 0x15 +#define REG15_GAIN_MSB 0x03 + +#define REG_REG16 0x16 + +#define REG_MIDH 0x1C/* manufacture id byte */ +#define REG_MIDL 0x1D/* manufacture id byre */ +#define REG_PIDH 0x0A/* Product ID MSB */ +#define REG_PIDL 0x0B/* Product ID LSB */ + +#define REG_84 0x84/* lots of stuff */ +#define REG_REG38 0x38/* sub-addr */ + +#define REG_AHSTART0x17/* Horiz start high bits */ +#define REG_AHSIZE 0x18 +#define REG_AVSTART0x19/* Vert start high bits */ +#define REG_AVSIZE 0x1A +#define REG_PSHFT 0x1b/* Pixel delay after HREF */ + +#define REG_HOUTSIZE 0x31 +#define REG_VOUTSIZE 0x32 +#define REG_HVSIZEOFF 0x33 +#define REG_REG34 0x34/* DSP output size H/V LSB*/ + +#define REG_ISP_CTRL00 0x80 +#define ISPCTRL00_AWB_EN 0x10 +#define ISPCTRL00_AWB_GAIN_EN 0x04 + +#defineREG_YGAIN 0xE2/* ygain for contrast control */ + +#defineREG_YBRIGHT 0xE3 +#defineREG_SGNSET0xE4 +#defineSGNSET_YBRIGHT_MASK 0x08 + +#define REG_USAT 0xDD +#define REG_VSAT 0xDE + + +struct ov7740 { + struct v4l2_subdev subdev; +#if defined(CONFI
[PATCH] media: i2c: Add the ov7740 image sensor driver
From: Songjun Wu The ov7740 (color) image sensor is a high performance VGA CMOS image snesor, which supports for output formats: RAW RGB and YUV and image sizes: VGA, and QVGA, CIF and any size smaller. Signed-off-by: Songjun Wu Signed-off-by: Wenyou Yang --- .../devicetree/bindings/media/i2c/ov7740.txt | 43 + drivers/media/i2c/Kconfig |8 + drivers/media/i2c/Makefile |1 + drivers/media/i2c/ov7740.c | 1220 4 files changed, 1272 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ov7740.txt create mode 100644 drivers/media/i2c/ov7740.c diff --git a/Documentation/devicetree/bindings/media/i2c/ov7740.txt b/Documentation/devicetree/bindings/media/i2c/ov7740.txt new file mode 100644 index ..b306e5aa97bf --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ov7740.txt @@ -0,0 +1,43 @@ +* Omnivision OV7740 CMOS image sensor + +The Omnivision OV7740 image sensor supports multiple output image +size, such as VGA, and QVGA, CIF and any size smaller. It also +supports the RAW RGB and YUV output formats. + +Required Properties: +- compatible: should be "ovti,ov7740" +- clocks: reference to the xvclk input clock. +- clock-names: should be "xvclk". + +Optional Properties: +- reset-gpios: reference to the GPIO connected to the reset_b pin, + if any. Active low with pull-ip resistor. +- powerdown-gpios: reference to the GPIO connected to the pwdn pin, + if any. Active high with pull-down resistor. + +The device node must contain one 'port' child node for its digital +output video port, in accordance with the video interface bindings +defined in Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + i2c1: i2c@fc028000 { + ov7740: camera@21 { + compatible = "ovti,ov7740"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sensor_power &pinctrl_sensor_reset>; + clocks = <&isc>; + clock-names = "xvclk"; + assigned-clocks = <&isc>; + assigned-clock-rates = <2400>; + reset-gpios = <&pioA 43 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&pioA 44 GPIO_ACTIVE_HIGH>; + + port { + ov7740_0: endpoint { + remote-endpoint = <&isc_0>; + }; + }; + }; + }; diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 47113774a297..402ad0e4024c 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -657,6 +657,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7740 + tristate "OmniVision OV7740 sensor support" + depends on I2C && VIDEO_V4L2 + depends on MEDIA_CAMERA_SUPPORT + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7740 VGA camera sensor. + config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index c843c181dfb9..f94cb2a8ed91 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o obj-$(CONFIG_VIDEO_OV6650) += ov6650.o obj-$(CONFIG_VIDEO_OV7640) += ov7640.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c new file mode 100644 index ..d68add05b46e --- /dev/null +++ b/drivers/media/i2c/ov7740.c @@ -0,0 +1,1220 @@ +/* + * Copyright (c) 2017 Microchip Corporation. + * + * 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_OUTSIZE_LSB 0x34 + +/* OV7740 register tables */ +#de
[PATCH v5 1/5] media: atmel-isc: Add spin lock for clock enable ops
Add the spin lock for the clock enable and disable operations. Signed-off-by: Wenyou Yang --- Changes in v5: None Changes in v4: None Changes in v3: - Fix the wrong used spinlock. - s/_/- on the subject. Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 15 ++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 2f8e345d297e..991f962b7023 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -65,6 +65,7 @@ struct isc_clk { struct clk_hw hw; struct clk *clk; struct regmap *regmap; + spinlock_t lock; u8 id; u8 parent_id; u32 div; @@ -312,26 +313,37 @@ static int isc_clk_enable(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; struct regmap *regmap = isc_clk->regmap; + unsigned long flags; + unsigned int status; dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n", __func__, isc_clk->div, isc_clk->parent_id); + spin_lock_irqsave(&isc_clk->lock, flags); regmap_update_bits(regmap, ISC_CLKCFG, ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id), (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) | (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id))); regmap_write(regmap, ISC_CLKEN, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); - return 0; + regmap_read(regmap, ISC_CLKSR, &status); + if (status & ISC_CLK(id)) + return 0; + else + return -EINVAL; } static void isc_clk_disable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; + unsigned long flags; + spin_lock_irqsave(&isc_clk->lock, flags); regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); } static int isc_clk_is_enabled(struct clk_hw *hw) @@ -492,6 +504,7 @@ static int isc_clk_register(struct isc_device *isc, unsigned int id) isc_clk->regmap = regmap; isc_clk->id = id; isc_clk->dev= isc->dev; + spin_lock_init(&isc_clk->lock); isc_clk->clk = clk_register(isc->dev, &isc_clk->hw); if (IS_ERR(isc_clk->clk)) { -- 2.13.0
[PATCH v5 5/5] media: atmel-isc: Rework the format list
To improve the readability of code, split the format array into two, one for the format description, other for the register configuration. Meanwhile, add the flag member to indicate the format can be achieved from the sensor or be produced by the controller, and rename members related to the register configuration. Also add more formats support: GREY, ARGB444, ARGB555 and ARGB32. Signed-off-by: Wenyou Yang --- Changes in v5: None Changes in v4: None Changes in v3: - Add a new flag for Raw Bayer format to remove MAX_RAW_FMT_INDEX define. - Add the comments for define of the format flag. - Rebase media_tree/master. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html drivers/media/platform/atmel/atmel-isc.c | 530 --- 1 file changed, 411 insertions(+), 119 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index a99796f7eb03..9294ff0c7b83 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -89,34 +89,63 @@ struct isc_subdev_entity { struct list_head list; }; +/* Indicate the format is generated by the sensor */ +#define FMT_FLAG_FROM_SENSOR BIT(0) +/* Indicate the format is produced by ISC itself */ +#define FMT_FLAG_FROM_CONTROLLER BIT(1) +/* Indicate a Raw Bayer format */ +#define FMT_FLAG_RAW_FORMATBIT(2) + +#define FMT_FLAG_RAW_FROM_SENSOR (FMT_FLAG_FROM_SENSOR | \ +FMT_FLAG_RAW_FORMAT) + /* * struct isc_format - ISC media bus format information * @fourcc:Fourcc code for this format * @mbus_code: V4L2 media bus format code. + * flags: Indicate format from sensor or converted by controller * @bpp: Bits per pixel (when stored in memory) - * @reg_bps: reg value for bits per sample * (when transferred over a bus) - * @pipeline: pipeline switch * @sd_support:Subdev supports this format * @isc_support: ISC can convert raw format to this format */ + struct isc_format { u32 fourcc; u32 mbus_code; + u32 flags; u8 bpp; - u32 reg_bps; - u32 reg_bay_cfg; - u32 reg_rlp_mode; - u32 reg_dcfg_imode; - u32 reg_dctrl_dview; - - u32 pipeline; - boolsd_support; boolisc_support; }; +/* Pipeline bitmap */ +#define WB_ENABLE BIT(0) +#define CFA_ENABLE BIT(1) +#define CC_ENABLE BIT(2) +#define GAM_ENABLE BIT(3) +#define GAM_BENABLEBIT(4) +#define GAM_GENABLEBIT(5) +#define GAM_RENABLEBIT(6) +#define CSC_ENABLE BIT(7) +#define CBC_ENABLE BIT(8) +#define SUB422_ENABLE BIT(9) +#define SUB420_ENABLE BIT(10) + +#define GAM_ENABLES(GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) + +struct fmt_config { + u32 fourcc; + + u32 pfe_cfg0_bps; + u32 cfa_baycfg; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; +}; #define HIST_ENTRIES 512 #define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1) @@ -181,80 +210,320 @@ struct isc_device { struct list_headsubdev_entities; }; -#define RAW_FMT_IND_START0 -#define RAW_FMT_IND_END 11 -#define ISC_FMT_IND_START12 -#define ISC_FMT_IND_END 14 - -static struct isc_format isc_formats[] = { - { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16
[PATCH v5 0/5] media: atmel-isc: Rework the format list and clock provider
To improve the readability of code, rework the format list table, split the format array into two. Meanwhile, fix the issue of the clock provider operation and the pm runtime support. Changes in v5: - Fix the clock ID which enters the runtime suspend should be ISC_ISPCK, instead of ISC_MCK for clk_prepare/clk_unprepare(). - Fix the clock ID to ISC_ISPCK, instead of ISC_MCK for isc_clk_is_enabled(). Changes in v4: - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->prepare and ->unprepare callback. - Move pm_runtime_enable() call from the complete callback to the end of probe. - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->is_enabled() callbacks. - Call clk_disable_unprepare() in ->remove callback. Changes in v3: - Fix the wrong used spinlock. - s/_/- on the subject. - Add a new flag for Raw Bayer format to remove MAX_RAW_FMT_INDEX define. - Add the comments for define of the format flag. - Rebase media_tree/master. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html Wenyou Yang (5): media: atmel-isc: Add spin lock for clock enable ops media: atmel-isc: Add prepare and unprepare ops media: atmel-isc: Enable the clocks during probe media: atmel-isc: Remove unnecessary member media: atmel-isc: Rework the format list drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 629 -- 2 files changed, 498 insertions(+), 132 deletions(-) -- 2.13.0
[PATCH v5 4/5] media: atmel-isc: Remove unnecessary member
Remove the memeber *config from the isc_subdev_entity struct, the member is useless afterward. Signed-off-by: Wenyou Yang --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 4431c27dfb09..a99796f7eb03 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -83,7 +83,6 @@ struct isc_subdev_entity { struct v4l2_subdev *sd; struct v4l2_async_subdev*asd; struct v4l2_async_notifier notifier; - struct v4l2_subdev_pad_config *config; u32 pfe_cfg0; @@ -1000,6 +999,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, { struct isc_format *isc_fmt; struct v4l2_pix_format *pixfmt = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; @@ -1030,7 +1030,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, - isc->current_subdev->config, &format); + &pad_cfg, &format); if (ret < 0) return ret; @@ -1495,8 +1495,6 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct isc_device, v4l2_dev); cancel_work_sync(&isc->awb_work); video_unregister_device(&isc->video_dev); - if (isc->current_subdev->config) - v4l2_subdev_free_pad_config(isc->current_subdev->config); v4l2_ctrl_handler_free(&isc->ctrls.handler); } @@ -1648,10 +1646,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) INIT_LIST_HEAD(&isc->dma_queue); spin_lock_init(&isc->dma_queue_lock); - sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd); - if (!sd_entity->config) - return -ENOMEM; - ret = isc_formats_init(isc); if (ret < 0) { v4l2_err(&isc->v4l2_dev, -- 2.13.0
[PATCH v5 2/5] media: atmel-isc: Add prepare and unprepare ops
A software write operation to the ISC_CLKEN or ISC_CLKDIS register requires double clock domain synchronization and is not permitted when the ISC_SR.SIP is asserted. So add the .prepare and .unprepare ops to make sure the ISC_CLKSR.SIP is unasserted before the write operation to the ISC_CLKEN or ISC_CLKDIS register. Signed-off-by: Wenyou Yang --- Changes in v5: - Fix the clock ID which enters the runtime suspend should be ISC_ISPCK, instead of ISC_MCK for clk_prepare/clk_unprepare(). Changes in v4: - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->prepare and ->unprepare callback. Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 40 +++ 2 files changed, 41 insertions(+) diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index 6936ac467609..93e58fcf1d5f 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -42,6 +42,7 @@ /* ISC Clock Status Register */ #define ISC_CLKSR 0x0020 +#define ISC_CLKSR_SIP BIT(31) #define ISC_CLK(n) BIT(n) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 991f962b7023..329ee8f256bb 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -308,6 +308,44 @@ module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, "Sensor is preferred to output the specified format (1-on 0-off), default 1"); +static int isc_wait_clk_stable(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + struct regmap *regmap = isc_clk->regmap; + unsigned long timeout = jiffies + usecs_to_jiffies(1000); + unsigned int status; + + while (time_before(jiffies, timeout)) { + regmap_read(regmap, ISC_CLKSR, &status); + if (!(status & ISC_CLKSR_SIP)) + return 0; + + usleep_range(10, 250); + } + + return -ETIMEDOUT; +} + +static int isc_clk_prepare(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + + if (isc_clk->id == ISC_ISPCK) + pm_runtime_get_sync(isc_clk->dev); + + return isc_wait_clk_stable(hw); +} + +static void isc_clk_unprepare(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + + isc_wait_clk_stable(hw); + + if (isc_clk->id == ISC_ISPCK) + pm_runtime_put_sync(isc_clk->dev); +} + static int isc_clk_enable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); @@ -459,6 +497,8 @@ static int isc_clk_set_rate(struct clk_hw *hw, } static const struct clk_ops isc_clk_ops = { + .prepare= isc_clk_prepare, + .unprepare = isc_clk_unprepare, .enable = isc_clk_enable, .disable= isc_clk_disable, .is_enabled = isc_clk_is_enabled, -- 2.13.0
[PATCH v5 3/5] media: atmel-isc: Enable the clocks during probe
To meet the relationship, enable the HCLOCK and ispck during the device probe, "isc_pck frequency is less than or equal to isc_ispck, and isc_ispck is greater than or equal to HCLOCK." Meanwhile, call the pm_runtime_enable() in the right place. Signed-off-by: Wenyou Yang --- Changes in v5: - Fix the clock ID to ISC_ISPCK, instead of ISC_MCK for isc_clk_is_enabled(). Changes in v4: - Move pm_runtime_enable() call from the complete callback to the end of probe. - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->is_enabled() callbacks. - Call clk_disable_unprepare() in ->remove callback. Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 34 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 329ee8f256bb..4431c27dfb09 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -389,8 +389,14 @@ static int isc_clk_is_enabled(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 status; + if (isc_clk->id == ISC_ISPCK) + pm_runtime_get_sync(isc_clk->dev); + regmap_read(isc_clk->regmap, ISC_CLKSR, &status); + if (isc_clk->id == ISC_ISPCK) + pm_runtime_put_sync(isc_clk->dev); + return status & ISC_CLK(isc_clk->id) ? 1 : 0; } @@ -1866,25 +1872,37 @@ static int atmel_isc_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(isc->hclock); + if (ret) { + dev_err(dev, "failed to enable hclock: %d\n", ret); + return ret; + } + ret = isc_clk_init(isc); if (ret) { dev_err(dev, "failed to init isc clock: %d\n", ret); - goto clean_isc_clk; + goto unprepare_hclk; } isc->ispck = isc->isc_clks[ISC_ISPCK].clk; + ret = clk_prepare_enable(isc->ispck); + if (ret) { + dev_err(dev, "failed to enable ispck: %d\n", ret); + goto unprepare_hclk; + } + /* ispck should be greater or equal to hclock */ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); if (ret) { dev_err(dev, "failed to set ispck rate: %d\n", ret); - goto clean_isc_clk; + goto unprepare_clk; } ret = v4l2_device_register(dev, &isc->v4l2_dev); if (ret) { dev_err(dev, "unable to register v4l2 device.\n"); - goto clean_isc_clk; + goto unprepare_clk; } ret = isc_parse_dt(dev, isc); @@ -1917,7 +1935,9 @@ static int atmel_isc_probe(struct platform_device *pdev) break; } + pm_runtime_set_active(dev); pm_runtime_enable(dev); + pm_request_idle(dev); return 0; @@ -1927,7 +1947,11 @@ static int atmel_isc_probe(struct platform_device *pdev) unregister_v4l2_device: v4l2_device_unregister(&isc->v4l2_dev); -clean_isc_clk: +unprepare_clk: + clk_disable_unprepare(isc->ispck); +unprepare_hclk: + clk_disable_unprepare(isc->hclock); + isc_clk_cleanup(isc); return ret; @@ -1938,6 +1962,8 @@ static int atmel_isc_remove(struct platform_device *pdev) struct isc_device *isc = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(isc->ispck); + clk_disable_unprepare(isc->hclock); isc_subdev_cleanup(isc); -- 2.13.0
[PATCH v6 3/3] media: ov7670: Add the ov7670_s_power function
Add the ov7670_s_power function which is responsible for manipulating the power dowm mode through the PWDN pin and the reset operation through the RESET pin, and keep it powered at all times. Signed-off-by: Wenyou Yang --- Changes in v6: - Remove .s_power callback to keep the ov7670 powered at all times. - Update the commit log accordingly. Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). drivers/media/i2c/ov7670.c | 31 ++- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 73ceec63a8ca..35a30605d6e3 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1544,6 +1544,22 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_direction_output(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + static void ov7670_get_default_format(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format) { @@ -1694,23 +1710,25 @@ static int ov7670_probe(struct i2c_client *client, if (ret) return ret; - ret = ov7670_init_gpio(client, info); - if (ret) - goto clk_disable; - info->clock_speed = clk_get_rate(info->clk) / 100; if (info->clock_speed < 10 || info->clock_speed > 48) { ret = -EINVAL; goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); @@ -1789,6 +1807,8 @@ static int ov7670_probe(struct i2c_client *client, #endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1806,6 +1826,7 @@ static int ov7670_remove(struct i2c_client *client) #if defined(CONFIG_MEDIA_CONTROLLER) media_entity_cleanup(&info->sd.entity); #endif + ov7670_s_power(sd, 0); return 0; } -- 2.13.0
[PATCH v6 2/3] media: ov7670: Add the get_fmt callback
Add the get_fmt callback, also enable V4L2_SUBDEV_FL_HAS_DEVNODE flag to make this subdev has device node. Signed-off-by: Wenyou Yang --- Changes in v6: None Changes in v5: - Fix the build warning on the declaration *mbus_fmt(ISO C90 forbids mixed). Changes in v4: - Fix the build error when not enabling V4L2 sub-device userspace API option. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: None drivers/media/i2c/ov7670.c | 77 +- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 553945d4ca28..73ceec63a8ca 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -232,6 +232,7 @@ struct ov7670_info { struct v4l2_ctrl *saturation; struct v4l2_ctrl *hue; }; + struct v4l2_mbus_framefmt format; struct ov7670_format_struct *fmt; /* Current format */ struct clk *clk; struct gpio_desc *resetb_gpio; @@ -975,6 +976,9 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, fmt->width = wsize->width; fmt->height = wsize->height; fmt->colorspace = ov7670_formats[index].colorspace; + + info->format = *fmt; + return 0; } @@ -988,6 +992,9 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; struct ov7670_info *info = to_state(sd); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; +#endif unsigned char com7; int ret; @@ -998,8 +1005,13 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); if (ret) return ret; - cfg->try_fmt = format->format; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + *mbus_fmt = format->format; return 0; +#else + return -ENOTTY; +#endif } ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize); @@ -1041,6 +1053,30 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, return 0; } +static int ov7670_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct ov7670_info *info = to_state(sd); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; +#endif + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); + format->format = *mbus_fmt; + return 0; +#else + return -ENOTTY; +#endif + } else { + format->format = info->format; + } + + return 0; +} + /* * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. @@ -1508,6 +1544,30 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static void ov7670_get_default_format(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *format) +{ + struct ov7670_info *info = to_state(sd); + + format->width = info->devtype->win_sizes[0].width; + format->height = info->devtype->win_sizes[0].height; + format->colorspace = info->fmt->colorspace; + format->code = info->fmt->mbus_code; + format->field = V4L2_FIELD_NONE; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + ov7670_get_default_format(sd, format); + + return 0; +} +#endif + /* --- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1528,6 +1588,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, + .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, }; @@ -1537,6 +1598,12 @@ static const struct v4l2_subdev_ops ov7670_ops = { .pad = &ov7670_pad_ops, }; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { + .open = ov7670_open, +}; +#endif + /* ---
[PATCH v6 0/3] media: ov7670: Add entity init and power operation
This patch set is to add the media entity pads initialization, the ov7670_s_power function and get_fmt callback support. Changes in v6: - Remove .s_power callback to keep the ov7670 powered at all times. - Update the commit log accordingly. Changes in v5: - Fix the build warning on the declaration *mbus_fmt(ISO C90 forbids mixed). Changes in v4: - Fix the build error when not enabling Media Controller API option. - Fix the build error when not enabling V4L2 sub-device userspace API option. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). Wenyou Yang (3): media: ov7670: Add entity pads initialization media: ov7670: Add the get_fmt callback media: ov7670: Add the ov7670_s_power function drivers/media/i2c/ov7670.c | 129 ++--- 1 file changed, 122 insertions(+), 7 deletions(-) -- 2.13.0
[PATCH v6 1/3] media: ov7670: Add entity pads initialization
Add the media entity pads initialization. Signed-off-by: Wenyou Yang --- Changes in v6: None Changes in v5: None Changes in v4: - Fix the build error when not enabling Media Controller API option. Changes in v3: None Changes in v2: None drivers/media/i2c/ov7670.c | 21 - 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..553945d4ca28 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,9 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_pad pad; +#endif struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -1688,14 +1691,27 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + +#if defined(CONFIG_MEDIA_CONTROLLER) + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; +#endif + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); clk_disable: @@ -1712,6 +1728,9 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif return 0; } -- 2.13.0
[PATCH v4 4/5] media: atmel-isc: Remove unnecessary member
Remove the memeber *config from the isc_subdev_entity struct, the member is useless afterward. Signed-off-by: Wenyou Yang --- Changes in v4: None Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index a44a66ad2c02..29780fcdfc8b 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -83,7 +83,6 @@ struct isc_subdev_entity { struct v4l2_subdev *sd; struct v4l2_async_subdev*asd; struct v4l2_async_notifier notifier; - struct v4l2_subdev_pad_config *config; u32 pfe_cfg0; @@ -1000,6 +999,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, { struct isc_format *isc_fmt; struct v4l2_pix_format *pixfmt = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; @@ -1030,7 +1030,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, - isc->current_subdev->config, &format); + &pad_cfg, &format); if (ret < 0) return ret; @@ -1495,8 +1495,6 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct isc_device, v4l2_dev); cancel_work_sync(&isc->awb_work); video_unregister_device(&isc->video_dev); - if (isc->current_subdev->config) - v4l2_subdev_free_pad_config(isc->current_subdev->config); v4l2_ctrl_handler_free(&isc->ctrls.handler); } @@ -1648,10 +1646,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) INIT_LIST_HEAD(&isc->dma_queue); spin_lock_init(&isc->dma_queue_lock); - sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd); - if (!sd_entity->config) - return -ENOMEM; - ret = isc_formats_init(isc); if (ret < 0) { v4l2_err(&isc->v4l2_dev, -- 2.13.0
[PATCH v4 5/5] media: atmel-isc: Rework the format list
To improve the readability of code, split the format array into two, one for the format description, other for the register configuration. Meanwhile, add the flag member to indicate the format can be achieved from the sensor or be produced by the controller, and rename members related to the register configuration. Also add more formats support: GREY, ARGB444, ARGB555 and ARGB32. Signed-off-by: Wenyou Yang --- Changes in v4: None Changes in v3: - Add a new flag for Raw Bayer format to remove MAX_RAW_FMT_INDEX define. - Add the comments for define of the format flag. - Rebase media_tree/master. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html drivers/media/platform/atmel/atmel-isc.c | 530 --- 1 file changed, 411 insertions(+), 119 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 29780fcdfc8b..2c40a7886542 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -89,34 +89,63 @@ struct isc_subdev_entity { struct list_head list; }; +/* Indicate the format is generated by the sensor */ +#define FMT_FLAG_FROM_SENSOR BIT(0) +/* Indicate the format is produced by ISC itself */ +#define FMT_FLAG_FROM_CONTROLLER BIT(1) +/* Indicate a Raw Bayer format */ +#define FMT_FLAG_RAW_FORMATBIT(2) + +#define FMT_FLAG_RAW_FROM_SENSOR (FMT_FLAG_FROM_SENSOR | \ +FMT_FLAG_RAW_FORMAT) + /* * struct isc_format - ISC media bus format information * @fourcc:Fourcc code for this format * @mbus_code: V4L2 media bus format code. + * flags: Indicate format from sensor or converted by controller * @bpp: Bits per pixel (when stored in memory) - * @reg_bps: reg value for bits per sample * (when transferred over a bus) - * @pipeline: pipeline switch * @sd_support:Subdev supports this format * @isc_support: ISC can convert raw format to this format */ + struct isc_format { u32 fourcc; u32 mbus_code; + u32 flags; u8 bpp; - u32 reg_bps; - u32 reg_bay_cfg; - u32 reg_rlp_mode; - u32 reg_dcfg_imode; - u32 reg_dctrl_dview; - - u32 pipeline; - boolsd_support; boolisc_support; }; +/* Pipeline bitmap */ +#define WB_ENABLE BIT(0) +#define CFA_ENABLE BIT(1) +#define CC_ENABLE BIT(2) +#define GAM_ENABLE BIT(3) +#define GAM_BENABLEBIT(4) +#define GAM_GENABLEBIT(5) +#define GAM_RENABLEBIT(6) +#define CSC_ENABLE BIT(7) +#define CBC_ENABLE BIT(8) +#define SUB422_ENABLE BIT(9) +#define SUB420_ENABLE BIT(10) + +#define GAM_ENABLES(GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) + +struct fmt_config { + u32 fourcc; + + u32 pfe_cfg0_bps; + u32 cfa_baycfg; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; +}; #define HIST_ENTRIES 512 #define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1) @@ -181,80 +210,320 @@ struct isc_device { struct list_headsubdev_entities; }; -#define RAW_FMT_IND_START0 -#define RAW_FMT_IND_END 11 -#define ISC_FMT_IND_START12 -#define ISC_FMT_IND_END 14 - -static struct isc_format isc_formats[] = { - { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN
[PATCH v4 3/5] media: atmel-isc: Enable the clocks during probe
To meet the relationship, enable the HCLOCK and ispck during the device probe, "isc_pck frequency is less than or equal to isc_ispck, and isc_ispck is greater than or equal to HCLOCK." Meanwhile, call the pm_runtime_enable() in the right place. Signed-off-by: Wenyou Yang --- Changes in v4: - Move pm_runtime_enable() call from the complete callback to the end of probe. - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->is_enabled() callbacks. - Call clk_disable_unprepare() in ->remove callback. Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 34 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 5f8228fc9c8d..a44a66ad2c02 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -389,8 +389,14 @@ static int isc_clk_is_enabled(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 status; + if (isc_clk->id == ISC_MCK) + pm_runtime_get_sync(isc_clk->dev); + regmap_read(isc_clk->regmap, ISC_CLKSR, &status); + if (isc_clk->id == ISC_MCK) + pm_runtime_put_sync(isc_clk->dev); + return status & ISC_CLK(isc_clk->id) ? 1 : 0; } @@ -1866,25 +1872,37 @@ static int atmel_isc_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(isc->hclock); + if (ret) { + dev_err(dev, "failed to enable hclock: %d\n", ret); + return ret; + } + ret = isc_clk_init(isc); if (ret) { dev_err(dev, "failed to init isc clock: %d\n", ret); - goto clean_isc_clk; + goto unprepare_hclk; } isc->ispck = isc->isc_clks[ISC_ISPCK].clk; + ret = clk_prepare_enable(isc->ispck); + if (ret) { + dev_err(dev, "failed to enable ispck: %d\n", ret); + goto unprepare_hclk; + } + /* ispck should be greater or equal to hclock */ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); if (ret) { dev_err(dev, "failed to set ispck rate: %d\n", ret); - goto clean_isc_clk; + goto unprepare_clk; } ret = v4l2_device_register(dev, &isc->v4l2_dev); if (ret) { dev_err(dev, "unable to register v4l2 device.\n"); - goto clean_isc_clk; + goto unprepare_clk; } ret = isc_parse_dt(dev, isc); @@ -1917,7 +1935,9 @@ static int atmel_isc_probe(struct platform_device *pdev) break; } + pm_runtime_set_active(dev); pm_runtime_enable(dev); + pm_request_idle(dev); return 0; @@ -1927,7 +1947,11 @@ static int atmel_isc_probe(struct platform_device *pdev) unregister_v4l2_device: v4l2_device_unregister(&isc->v4l2_dev); -clean_isc_clk: +unprepare_clk: + clk_disable_unprepare(isc->ispck); +unprepare_hclk: + clk_disable_unprepare(isc->hclock); + isc_clk_cleanup(isc); return ret; @@ -1938,6 +1962,8 @@ static int atmel_isc_remove(struct platform_device *pdev) struct isc_device *isc = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(isc->ispck); + clk_disable_unprepare(isc->hclock); isc_subdev_cleanup(isc); -- 2.13.0
[PATCH v4 2/5] media: atmel-isc: Add prepare and unprepare ops
A software write operation to the ISC_CLKEN or ISC_CLKDIS register requires double clock domain synchronization and is not permitted when the ISC_SR.SIP is asserted. So add the .prepare and .unprepare ops to make sure the ISC_CLKSR.SIP is unasserted before the write operation to the ISC_CLKEN or ISC_CLKDIS register. Signed-off-by: Wenyou Yang --- Changes in v4: - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->prepare and ->unprepare callback. Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 40 +++ 2 files changed, 41 insertions(+) diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index 6936ac467609..93e58fcf1d5f 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -42,6 +42,7 @@ /* ISC Clock Status Register */ #define ISC_CLKSR 0x0020 +#define ISC_CLKSR_SIP BIT(31) #define ISC_CLK(n) BIT(n) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 991f962b7023..5f8228fc9c8d 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -308,6 +308,44 @@ module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, "Sensor is preferred to output the specified format (1-on 0-off), default 1"); +static int isc_wait_clk_stable(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + struct regmap *regmap = isc_clk->regmap; + unsigned long timeout = jiffies + usecs_to_jiffies(1000); + unsigned int status; + + while (time_before(jiffies, timeout)) { + regmap_read(regmap, ISC_CLKSR, &status); + if (!(status & ISC_CLKSR_SIP)) + return 0; + + usleep_range(10, 250); + } + + return -ETIMEDOUT; +} + +static int isc_clk_prepare(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + + if (isc_clk->id == ISC_MCK) + pm_runtime_get_sync(isc_clk->dev); + + return isc_wait_clk_stable(hw); +} + +static void isc_clk_unprepare(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + + isc_wait_clk_stable(hw); + + if (isc_clk->id == ISC_MCK) + pm_runtime_put_sync(isc_clk->dev); +} + static int isc_clk_enable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); @@ -459,6 +497,8 @@ static int isc_clk_set_rate(struct clk_hw *hw, } static const struct clk_ops isc_clk_ops = { + .prepare= isc_clk_prepare, + .unprepare = isc_clk_unprepare, .enable = isc_clk_enable, .disable= isc_clk_disable, .is_enabled = isc_clk_is_enabled, -- 2.13.0
[PATCH v4 0/5] media: atmel-isc: Rework the format list and clock provider
To improve the readability of code, rework the format list table, split the format array into two. Meanwhile, fix the issue of the clock provider operation and the pm runtime support. Changes in v4: - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->prepare and ->unprepare callback. - Move pm_runtime_enable() call from the complete callback to the end of probe. - Call pm_runtime_get_sync() and pm_runtime_put_sync() in ->is_enabled() callbacks. - Call clk_disable_unprepare() in ->remove callback. Changes in v3: - Fix the wrong used spinlock. - s/_/- on the subject. - Add a new flag for Raw Bayer format to remove MAX_RAW_FMT_INDEX define. - Add the comments for define of the format flag. - Rebase media_tree/master. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html Wenyou Yang (5): media: atmel-isc: Add spin lock for clock enable ops media: atmel-isc: Add prepare and unprepare ops media: atmel-isc: Enable the clocks during probe media: atmel-isc: Remove unnecessary member media: atmel-isc: Rework the format list drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 629 -- 2 files changed, 498 insertions(+), 132 deletions(-) -- 2.13.0
[PATCH v4 1/5] media: atmel-isc: Add spin lock for clock enable ops
Add the spin lock for the clock enable and disable operations. Signed-off-by: Wenyou Yang --- Changes in v4: None Changes in v3: - Fix the wrong used spinlock. - s/_/- on the subject. Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 15 ++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 2f8e345d297e..991f962b7023 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -65,6 +65,7 @@ struct isc_clk { struct clk_hw hw; struct clk *clk; struct regmap *regmap; + spinlock_t lock; u8 id; u8 parent_id; u32 div; @@ -312,26 +313,37 @@ static int isc_clk_enable(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; struct regmap *regmap = isc_clk->regmap; + unsigned long flags; + unsigned int status; dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n", __func__, isc_clk->div, isc_clk->parent_id); + spin_lock_irqsave(&isc_clk->lock, flags); regmap_update_bits(regmap, ISC_CLKCFG, ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id), (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) | (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id))); regmap_write(regmap, ISC_CLKEN, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); - return 0; + regmap_read(regmap, ISC_CLKSR, &status); + if (status & ISC_CLK(id)) + return 0; + else + return -EINVAL; } static void isc_clk_disable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; + unsigned long flags; + spin_lock_irqsave(&isc_clk->lock, flags); regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); } static int isc_clk_is_enabled(struct clk_hw *hw) @@ -492,6 +504,7 @@ static int isc_clk_register(struct isc_device *isc, unsigned int id) isc_clk->regmap = regmap; isc_clk->id = id; isc_clk->dev= isc->dev; + spin_lock_init(&isc_clk->lock); isc_clk->clk = clk_register(isc->dev, &isc_clk->hw); if (IS_ERR(isc_clk->clk)) { -- 2.13.0
[PATCH v3 5/5] media: atmel-isc: Rework the format list
To improve the readability of code, split the format array into two, one for the format description, other for the register configuration. Meanwhile, add the flag member to indicate the format can be achieved from the sensor or be produced by the controller, and rename members related to the register configuration. Also add more formats support: GREY, ARGB444, ARGB555 and ARGB32. Signed-off-by: Wenyou Yang --- Changes in v3: - Add a new flag for Raw Bayer format to remove MAX_RAW_FMT_INDEX define. - Add the comments for define of the format flag. - Rebase media_tree/master. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html drivers/media/platform/atmel/atmel-isc.c | 530 --- 1 file changed, 411 insertions(+), 119 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 0ff9dfbfff70..d2f8c05ad0ce 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -89,34 +89,63 @@ struct isc_subdev_entity { struct list_head list; }; +/* Indicate the format is generated by the sensor */ +#define FMT_FLAG_FROM_SENSOR BIT(0) +/* Indicate the format is produced by ISC itself */ +#define FMT_FLAG_FROM_CONTROLLER BIT(1) +/* Indicate a Raw Bayer format */ +#define FMT_FLAG_RAW_FORMATBIT(2) + +#define FMT_FLAG_RAW_FROM_SENSOR (FMT_FLAG_FROM_SENSOR | \ +FMT_FLAG_RAW_FORMAT) + /* * struct isc_format - ISC media bus format information * @fourcc:Fourcc code for this format * @mbus_code: V4L2 media bus format code. + * flags: Indicate format from sensor or converted by controller * @bpp: Bits per pixel (when stored in memory) - * @reg_bps: reg value for bits per sample * (when transferred over a bus) - * @pipeline: pipeline switch * @sd_support:Subdev supports this format * @isc_support: ISC can convert raw format to this format */ + struct isc_format { u32 fourcc; u32 mbus_code; + u32 flags; u8 bpp; - u32 reg_bps; - u32 reg_bay_cfg; - u32 reg_rlp_mode; - u32 reg_dcfg_imode; - u32 reg_dctrl_dview; - - u32 pipeline; - boolsd_support; boolisc_support; }; +/* Pipeline bitmap */ +#define WB_ENABLE BIT(0) +#define CFA_ENABLE BIT(1) +#define CC_ENABLE BIT(2) +#define GAM_ENABLE BIT(3) +#define GAM_BENABLEBIT(4) +#define GAM_GENABLEBIT(5) +#define GAM_RENABLEBIT(6) +#define CSC_ENABLE BIT(7) +#define CBC_ENABLE BIT(8) +#define SUB422_ENABLE BIT(9) +#define SUB420_ENABLE BIT(10) + +#define GAM_ENABLES(GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) + +struct fmt_config { + u32 fourcc; + + u32 pfe_cfg0_bps; + u32 cfa_baycfg; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; +}; #define HIST_ENTRIES 512 #define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1) @@ -181,80 +210,320 @@ struct isc_device { struct list_headsubdev_entities; }; -#define RAW_FMT_IND_START0 -#define RAW_FMT_IND_END 11 -#define ISC_FMT_IND_START12 -#define ISC_FMT_IND_END 14 - -static struct isc_format isc_formats[] = { - { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GBGB
[PATCH v3 4/5] media: atmel-isc: Remove unnecessary member
Remove the memeber *config from the isc_subdev_entity struct, the member is useless afterward. Signed-off-by: Wenyou Yang --- Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index f092c95587c1..0ff9dfbfff70 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -83,7 +83,6 @@ struct isc_subdev_entity { struct v4l2_subdev *sd; struct v4l2_async_subdev*asd; struct v4l2_async_notifier notifier; - struct v4l2_subdev_pad_config *config; u32 pfe_cfg0; @@ -984,6 +983,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, { struct isc_format *isc_fmt; struct v4l2_pix_format *pixfmt = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; @@ -1014,7 +1014,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, - isc->current_subdev->config, &format); + &pad_cfg, &format); if (ret < 0) return ret; @@ -1479,8 +1479,6 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct isc_device, v4l2_dev); cancel_work_sync(&isc->awb_work); video_unregister_device(&isc->video_dev); - if (isc->current_subdev->config) - v4l2_subdev_free_pad_config(isc->current_subdev->config); v4l2_ctrl_handler_free(&isc->ctrls.handler); } @@ -1633,10 +1631,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) INIT_LIST_HEAD(&isc->dma_queue); spin_lock_init(&isc->dma_queue_lock); - sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd); - if (!sd_entity->config) - return -ENOMEM; - ret = isc_formats_init(isc); if (ret < 0) { v4l2_err(&isc->v4l2_dev, -- 2.13.0
[PATCH v3 3/5] media: atmel-isc: Enable the clocks during probe
To meet the relationship, enable the HCLOCK and ispck during the device probe, "isc_pck frequency is less than or equal to isc_ispck, and isc_ispck is greater than or equal to HCLOCK." Meanwhile, call the pm_runtime_enable() in the right place. Signed-off-by: Wenyou Yang --- Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 31 +-- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 0b15dc1a3a0b..f092c95587c1 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -1594,6 +1594,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) struct isc_subdev_entity *sd_entity; struct video_device *vdev = &isc->video_dev; struct vb2_queue *q = &isc->vb2_vidq; + struct device *dev = isc->dev; int ret; ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev); @@ -1677,6 +1678,10 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) return ret; } + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_request_idle(dev); + return 0; } @@ -1856,25 +1861,37 @@ static int atmel_isc_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(isc->hclock); + if (ret) { + dev_err(dev, "failed to enable hclock: %d\n", ret); + return ret; + } + ret = isc_clk_init(isc); if (ret) { dev_err(dev, "failed to init isc clock: %d\n", ret); - goto clean_isc_clk; + goto unprepare_hclk; } isc->ispck = isc->isc_clks[ISC_ISPCK].clk; + ret = clk_prepare_enable(isc->ispck); + if (ret) { + dev_err(dev, "failed to enable ispck: %d\n", ret); + goto unprepare_hclk; + } + /* ispck should be greater or equal to hclock */ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); if (ret) { dev_err(dev, "failed to set ispck rate: %d\n", ret); - goto clean_isc_clk; + goto unprepare_clk; } ret = v4l2_device_register(dev, &isc->v4l2_dev); if (ret) { dev_err(dev, "unable to register v4l2 device.\n"); - goto clean_isc_clk; + goto unprepare_clk; } ret = isc_parse_dt(dev, isc); @@ -1907,8 +1924,6 @@ static int atmel_isc_probe(struct platform_device *pdev) break; } - pm_runtime_enable(dev); - return 0; cleanup_subdev: @@ -1917,7 +1932,11 @@ static int atmel_isc_probe(struct platform_device *pdev) unregister_v4l2_device: v4l2_device_unregister(&isc->v4l2_dev); -clean_isc_clk: +unprepare_clk: + clk_disable_unprepare(isc->ispck); +unprepare_hclk: + clk_disable_unprepare(isc->hclock); + isc_clk_cleanup(isc); return ret; -- 2.13.0
[PATCH v3 2/5] media: atmel-isc: Add prepare and unprepare ops
A software write operation to the ISC_CLKEN or ISC_CLKDIS register requires double clock domain synchronization and is not permitted when the ISC_SR.SIP is asserted. So add the .prepare and .unprepare ops to make sure the ISC_CLKSR.SIP is unasserted before the write operation to the ISC_CLKEN or ISC_CLKDIS register. Signed-off-by: Wenyou Yang --- Changes in v3: None Changes in v2: None drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 30 +++ 2 files changed, 31 insertions(+) diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index 6936ac467609..93e58fcf1d5f 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -42,6 +42,7 @@ /* ISC Clock Status Register */ #define ISC_CLKSR 0x0020 +#define ISC_CLKSR_SIP BIT(31) #define ISC_CLK(n) BIT(n) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 991f962b7023..0b15dc1a3a0b 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -308,6 +308,34 @@ module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, "Sensor is preferred to output the specified format (1-on 0-off), default 1"); +static int isc_wait_clk_stable(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + struct regmap *regmap = isc_clk->regmap; + unsigned long timeout = jiffies + usecs_to_jiffies(1000); + unsigned int status; + + while (time_before(jiffies, timeout)) { + regmap_read(regmap, ISC_CLKSR, &status); + if (!(status & ISC_CLKSR_SIP)) + return 0; + + usleep_range(10, 250); + } + + return -ETIMEDOUT; +} + +static int isc_clk_prepare(struct clk_hw *hw) +{ + return isc_wait_clk_stable(hw); +} + +static void isc_clk_unprepare(struct clk_hw *hw) +{ + isc_wait_clk_stable(hw); +} + static int isc_clk_enable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); @@ -459,6 +487,8 @@ static int isc_clk_set_rate(struct clk_hw *hw, } static const struct clk_ops isc_clk_ops = { + .prepare= isc_clk_prepare, + .unprepare = isc_clk_unprepare, .enable = isc_clk_enable, .disable= isc_clk_disable, .is_enabled = isc_clk_is_enabled, -- 2.13.0
[PATCH v3 1/5] media: atmel-isc: Add spin lock for clock enable ops
Add the spin lock for the clock enable and disable operations. Signed-off-by: Wenyou Yang --- Changes in v3: - Fix the wrong used spinlock. - s/_/- on the subject. Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 15 ++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 2f8e345d297e..991f962b7023 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -65,6 +65,7 @@ struct isc_clk { struct clk_hw hw; struct clk *clk; struct regmap *regmap; + spinlock_t lock; u8 id; u8 parent_id; u32 div; @@ -312,26 +313,37 @@ static int isc_clk_enable(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; struct regmap *regmap = isc_clk->regmap; + unsigned long flags; + unsigned int status; dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n", __func__, isc_clk->div, isc_clk->parent_id); + spin_lock_irqsave(&isc_clk->lock, flags); regmap_update_bits(regmap, ISC_CLKCFG, ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id), (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) | (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id))); regmap_write(regmap, ISC_CLKEN, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); - return 0; + regmap_read(regmap, ISC_CLKSR, &status); + if (status & ISC_CLK(id)) + return 0; + else + return -EINVAL; } static void isc_clk_disable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; + unsigned long flags; + spin_lock_irqsave(&isc_clk->lock, flags); regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id)); + spin_unlock_irqrestore(&isc_clk->lock, flags); } static int isc_clk_is_enabled(struct clk_hw *hw) @@ -492,6 +504,7 @@ static int isc_clk_register(struct isc_device *isc, unsigned int id) isc_clk->regmap = regmap; isc_clk->id = id; isc_clk->dev= isc->dev; + spin_lock_init(&isc_clk->lock); isc_clk->clk = clk_register(isc->dev, &isc_clk->hw); if (IS_ERR(isc_clk->clk)) { -- 2.13.0
[PATCH v3 0/5] media: atmel-isc: Rework the format list and clock provider
To improve the readability of code, rework the format list table, split the format array into two. Meanwhile, fix the issue of the clock provider operation. Changes in v3: - Fix the wrong used spinlock. - s/_/- on the subject. - Add a new flag for Raw Bayer format to remove MAX_RAW_FMT_INDEX define. - Add the comments for define of the format flag. - Rebase media_tree/master. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html Wenyou Yang (5): media: atmel-isc: Add spin lock for clock enable ops media: atmel-isc: Add prepare and unprepare ops media: atmel-isc: Enable the clocks during probe media: atmel-isc: Remove unnecessary member media: atmel-isc: Rework the format list drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 616 -- 2 files changed, 483 insertions(+), 134 deletions(-) -- 2.13.0
[PATCH v5 3/3] media: ov7670: Add the s_power operation
Add the s_power operation which is responsible for manipulating the power dowm mode through the PWDN pin and the reset operation through the RESET pin. Signed-off-by: Wenyou Yang --- Changes in v5: None Changes in v4: None Changes in v3: None Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). drivers/media/i2c/ov7670.c | 32 +++- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 73ceec63a8ca..8e86479d8a24 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1544,6 +1544,22 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_direction_output(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + static void ov7670_get_default_format(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format) { @@ -1577,6 +1593,7 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .g_register = ov7670_g_register, .s_register = ov7670_s_register, #endif + .s_power = ov7670_s_power, }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { @@ -1694,23 +1711,25 @@ static int ov7670_probe(struct i2c_client *client, if (ret) return ret; - ret = ov7670_init_gpio(client, info); - if (ret) - goto clk_disable; - info->clock_speed = clk_get_rate(info->clk) / 100; if (info->clock_speed < 10 || info->clock_speed > 48) { ret = -EINVAL; goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); @@ -1789,6 +1808,8 @@ static int ov7670_probe(struct i2c_client *client, #endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1806,6 +1827,7 @@ static int ov7670_remove(struct i2c_client *client) #if defined(CONFIG_MEDIA_CONTROLLER) media_entity_cleanup(&info->sd.entity); #endif + ov7670_s_power(sd, 0); return 0; } -- 2.13.0
[PATCH v5 2/3] media: ov7670: Add the get_fmt callback
Add the get_fmt callback, also enable V4L2_SUBDEV_FL_HAS_DEVNODE flag to make this subdev has device node. Signed-off-by: Wenyou Yang --- Changes in v5: - Fix the build warning on the declaration *mbus_fmt(ISO C90 forbids mixed). Changes in v4: - Fix the build error when not enabling V4L2 sub-device userspace API option. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: None drivers/media/i2c/ov7670.c | 77 +- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 553945d4ca28..73ceec63a8ca 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -232,6 +232,7 @@ struct ov7670_info { struct v4l2_ctrl *saturation; struct v4l2_ctrl *hue; }; + struct v4l2_mbus_framefmt format; struct ov7670_format_struct *fmt; /* Current format */ struct clk *clk; struct gpio_desc *resetb_gpio; @@ -975,6 +976,9 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, fmt->width = wsize->width; fmt->height = wsize->height; fmt->colorspace = ov7670_formats[index].colorspace; + + info->format = *fmt; + return 0; } @@ -988,6 +992,9 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; struct ov7670_info *info = to_state(sd); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; +#endif unsigned char com7; int ret; @@ -998,8 +1005,13 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); if (ret) return ret; - cfg->try_fmt = format->format; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + *mbus_fmt = format->format; return 0; +#else + return -ENOTTY; +#endif } ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize); @@ -1041,6 +1053,30 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, return 0; } +static int ov7670_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct ov7670_info *info = to_state(sd); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; +#endif + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); + format->format = *mbus_fmt; + return 0; +#else + return -ENOTTY; +#endif + } else { + format->format = info->format; + } + + return 0; +} + /* * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. @@ -1508,6 +1544,30 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static void ov7670_get_default_format(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *format) +{ + struct ov7670_info *info = to_state(sd); + + format->width = info->devtype->win_sizes[0].width; + format->height = info->devtype->win_sizes[0].height; + format->colorspace = info->fmt->colorspace; + format->code = info->fmt->mbus_code; + format->field = V4L2_FIELD_NONE; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + ov7670_get_default_format(sd, format); + + return 0; +} +#endif + /* --- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1528,6 +1588,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, + .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, }; @@ -1537,6 +1598,12 @@ static const struct v4l2_subdev_ops ov7670_ops = { .pad = &ov7670_pad_ops, }; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { + .open = ov7670_open, +}; +#endif + /*
[PATCH v5 1/3] media: ov7670: Add entity pads initialization
Add the media entity pads initialization. Signed-off-by: Wenyou Yang --- Changes in v5: None Changes in v4: - Fix the build error when not enabling Media Controller API option. Changes in v3: None Changes in v2: None drivers/media/i2c/ov7670.c | 21 - 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..553945d4ca28 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,9 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_pad pad; +#endif struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -1688,14 +1691,27 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + +#if defined(CONFIG_MEDIA_CONTROLLER) + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; +#endif + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); clk_disable: @@ -1712,6 +1728,9 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif return 0; } -- 2.13.0
[PATCH v5 0/3] media: ov7670: Add entity init and power operation
This patch set is to add the media entity pads initialization, the s_power operation and get_fmt callback support. Changes in v5: - Fix the build warning on the declaration *mbus_fmt(ISO C90 forbids mixed). Changes in v4: - Fix the build error when not enabling Media Controller API option. - Fix the build error when not enabling V4L2 sub-device userspace API option. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). Wenyou Yang (3): media: ov7670: Add entity pads initialization media: ov7670: Add the get_fmt callback media: ov7670: Add the s_power operation drivers/media/i2c/ov7670.c | 130 ++--- 1 file changed, 123 insertions(+), 7 deletions(-) -- 2.13.0
[PATCH v4 3/3] media: ov7670: Add the s_power operation
Add the s_power operation which is responsible for manipulating the power dowm mode through the PWDN pin and the reset operation through the RESET pin. Signed-off-by: Wenyou Yang --- Changes in v4: None Changes in v3: None Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). drivers/media/i2c/ov7670.c | 32 +++- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 456f48057605..304abc769a67 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1542,6 +1542,22 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_direction_output(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + static void ov7670_get_default_format(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format) { @@ -1575,6 +1591,7 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .g_register = ov7670_g_register, .s_register = ov7670_s_register, #endif + .s_power = ov7670_s_power, }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { @@ -1692,23 +1709,25 @@ static int ov7670_probe(struct i2c_client *client, if (ret) return ret; - ret = ov7670_init_gpio(client, info); - if (ret) - goto clk_disable; - info->clock_speed = clk_get_rate(info->clk) / 100; if (info->clock_speed < 10 || info->clock_speed > 48) { ret = -EINVAL; goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); @@ -1787,6 +1806,8 @@ static int ov7670_probe(struct i2c_client *client, #endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1804,6 +1825,7 @@ static int ov7670_remove(struct i2c_client *client) #if defined(CONFIG_MEDIA_CONTROLLER) media_entity_cleanup(&info->sd.entity); #endif + ov7670_s_power(sd, 0); return 0; } -- 2.13.0
[PATCH v4 1/3] media: ov7670: Add entity pads initialization
Add the media entity pads initialization. Signed-off-by: Wenyou Yang --- Changes in v4: - Fix the build error when not enabling Media Controller API option. Changes in v3: None Changes in v2: None drivers/media/i2c/ov7670.c | 21 - 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..553945d4ca28 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,9 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_pad pad; +#endif struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -1688,14 +1691,27 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + +#if defined(CONFIG_MEDIA_CONTROLLER) + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; +#endif + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif hdl_free: v4l2_ctrl_handler_free(&info->hdl); clk_disable: @@ -1712,6 +1728,9 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&info->sd.entity); +#endif return 0; } -- 2.13.0
[PATCH v4 2/3] media: ov7670: Add the get_fmt callback
Add the get_fmt callback, also enable V4L2_SUBDEV_FL_HAS_DEVNODE flag to make this subdev has device node. Signed-off-by: Wenyou Yang --- Changes in v4: - Fix the build error when not enabling V4L2 sub-device userspace API option. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: None drivers/media/i2c/ov7670.c | 75 +- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 553945d4ca28..456f48057605 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -232,6 +232,7 @@ struct ov7670_info { struct v4l2_ctrl *saturation; struct v4l2_ctrl *hue; }; + struct v4l2_mbus_framefmt format; struct ov7670_format_struct *fmt; /* Current format */ struct clk *clk; struct gpio_desc *resetb_gpio; @@ -975,6 +976,9 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, fmt->width = wsize->width; fmt->height = wsize->height; fmt->colorspace = ov7670_formats[index].colorspace; + + info->format = *fmt; + return 0; } @@ -998,8 +1002,15 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); if (ret) return ret; - cfg->try_fmt = format->format; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; + + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + *mbus_fmt = format->format; return 0; +#else + return -ENOTTY; +#endif } ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize); @@ -1041,6 +1052,29 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, return 0; } +static int ov7670_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct ov7670_info *info = to_state(sd); + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + struct v4l2_mbus_framefmt *mbus_fmt; + + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); + format->format = *mbus_fmt; + return 0; +#else + return -ENOTTY; +#endif + } else { + format->format = info->format; + } + + return 0; +} + /* * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. @@ -1508,6 +1542,30 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static void ov7670_get_default_format(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *format) +{ + struct ov7670_info *info = to_state(sd); + + format->width = info->devtype->win_sizes[0].width; + format->height = info->devtype->win_sizes[0].height; + format->colorspace = info->fmt->colorspace; + format->code = info->fmt->mbus_code; + format->field = V4L2_FIELD_NONE; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + ov7670_get_default_format(sd, format); + + return 0; +} +#endif + /* --- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1528,6 +1586,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, + .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, }; @@ -1537,6 +1596,12 @@ static const struct v4l2_subdev_ops ov7670_ops = { .pad = &ov7670_pad_ops, }; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { + .open = ov7670_open, +}; +#endif + /* --- */ static const struct ov7670_devtype ov7670_devdata[] = { @@ -1589,6 +1654,11 @@ static int ov7670_probe(struct i2c_client *client, sd = &info->sd; v4l2_i2c_subdev_init(sd, client, &ov7670_ops); +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &ov7670_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_
[PATCH v4 0/3] media: ov7670: Add entity init and power operation
This patch set is to add the media entity pads initialization, the s_power operation and get_fmt callback support. Changes in v4: - Fix the build error when not enabling Media Controller API option. - Fix the build error when not enabling V4L2 sub-device userspace API option. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). Wenyou Yang (3): media: ov7670: Add entity pads initialization media: ov7670: Add the get_fmt callback media: ov7670: Add the s_power operation drivers/media/i2c/ov7670.c | 128 ++--- 1 file changed, 121 insertions(+), 7 deletions(-) -- 2.13.0
[PATCH v2 5/5] media: atmel-isc: Rework the format list
To improve the readability of code, split the format array into two, one for the format description, other for the register configuration. Meanwhile, add the flag member to indicate the format can be achieved from the sensor or be produced by the controller, and rename members related to the register configuration. Also add more formats support: GREY, ARGB444, ARGB555 and ARGB32. Signed-off-by: Wenyou Yang --- Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html drivers/media/platform/atmel/atmel-isc.c | 524 --- 1 file changed, 405 insertions(+), 119 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 2d876903da71..90bd0b28a975 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -89,34 +89,56 @@ struct isc_subdev_entity { struct list_head list; }; +#define FMT_FLAG_FROM_SENSOR BIT(0) +#define FMT_FLAG_FROM_CONTROLLER BIT(1) + /* * struct isc_format - ISC media bus format information * @fourcc:Fourcc code for this format * @mbus_code: V4L2 media bus format code. + * flags: Indicate format from sensor or converted by controller * @bpp: Bits per pixel (when stored in memory) - * @reg_bps: reg value for bits per sample * (when transferred over a bus) - * @pipeline: pipeline switch * @sd_support:Subdev supports this format * @isc_support: ISC can convert raw format to this format */ + struct isc_format { u32 fourcc; u32 mbus_code; + u32 flags; u8 bpp; - u32 reg_bps; - u32 reg_bay_cfg; - u32 reg_rlp_mode; - u32 reg_dcfg_imode; - u32 reg_dctrl_dview; - - u32 pipeline; - boolsd_support; boolisc_support; }; +/* Pipeline bitmap */ +#define WB_ENABLE BIT(0) +#define CFA_ENABLE BIT(1) +#define CC_ENABLE BIT(2) +#define GAM_ENABLE BIT(3) +#define GAM_BENABLEBIT(4) +#define GAM_GENABLEBIT(5) +#define GAM_RENABLEBIT(6) +#define CSC_ENABLE BIT(7) +#define CBC_ENABLE BIT(8) +#define SUB422_ENABLE BIT(9) +#define SUB420_ENABLE BIT(10) + +#define GAM_ENABLES(GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) + +struct fmt_config { + u32 fourcc; + + u32 pfe_cfg0_bps; + u32 cfa_baycfg; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; +}; #define HIST_ENTRIES 512 #define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1) @@ -181,80 +203,321 @@ struct isc_device { struct list_headsubdev_entities; }; -#define RAW_FMT_IND_START0 -#define RAW_FMT_IND_END 11 -#define ISC_FMT_IND_START12 -#define ISC_FMT_IND_END 14 - -static struct isc_format isc_formats[] = { - { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT10
[PATCH v2 4/5] media: atmel-isc: Remove unnecessary member
Remove the memeber *config from the isc_subdev_entity struct, the member is useless afterward. Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 3ecd2bf016a8..2d876903da71 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -83,7 +83,6 @@ struct isc_subdev_entity { struct v4l2_subdev *sd; struct v4l2_async_subdev*asd; struct v4l2_async_notifier notifier; - struct v4l2_subdev_pad_config *config; u32 pfe_cfg0; @@ -983,6 +982,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, { struct isc_format *isc_fmt; struct v4l2_pix_format *pixfmt = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; @@ -1013,7 +1013,7 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, - isc->current_subdev->config, &format); + &pad_cfg, &format); if (ret < 0) return ret; @@ -1478,8 +1478,6 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct isc_device, v4l2_dev); cancel_work_sync(&isc->awb_work); video_unregister_device(&isc->video_dev); - if (isc->current_subdev->config) - v4l2_subdev_free_pad_config(isc->current_subdev->config); v4l2_ctrl_handler_free(&isc->ctrls.handler); } @@ -1632,10 +1630,6 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) INIT_LIST_HEAD(&isc->dma_queue); spin_lock_init(&isc->dma_queue_lock); - sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd); - if (!sd_entity->config) - return -ENOMEM; - ret = isc_formats_init(isc); if (ret < 0) { v4l2_err(&isc->v4l2_dev, -- 2.13.0
[PATCH v2 3/5] media: atmel-isc: Enable the clocks during probe
To meet the relationship, enable the HCLOCK and ispck during the device probe, "isc_pck frequency is less than or equal to isc_ispck, and isc_ispck is greater than or equal to HCLOCK." Meanwhile, call the pm_runtime_enable() in the right place. Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 31 +-- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 8b9c1cafa348..3ecd2bf016a8 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -1593,6 +1593,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) struct isc_subdev_entity *sd_entity; struct video_device *vdev = &isc->video_dev; struct vb2_queue *q = &isc->vb2_vidq; + struct device *dev = isc->dev; int ret; ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev); @@ -1676,6 +1677,10 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) return ret; } + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_request_idle(dev); + return 0; } @@ -1855,25 +1860,37 @@ static int atmel_isc_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(isc->hclock); + if (ret) { + dev_err(dev, "failed to enable hclock: %d\n", ret); + return ret; + } + ret = isc_clk_init(isc); if (ret) { dev_err(dev, "failed to init isc clock: %d\n", ret); - goto clean_isc_clk; + goto unprepare_hclk; } isc->ispck = isc->isc_clks[ISC_ISPCK].clk; + ret = clk_prepare_enable(isc->ispck); + if (ret) { + dev_err(dev, "failed to enable ispck: %d\n", ret); + goto unprepare_hclk; + } + /* ispck should be greater or equal to hclock */ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); if (ret) { dev_err(dev, "failed to set ispck rate: %d\n", ret); - goto clean_isc_clk; + goto unprepare_clk; } ret = v4l2_device_register(dev, &isc->v4l2_dev); if (ret) { dev_err(dev, "unable to register v4l2 device.\n"); - goto clean_isc_clk; + goto unprepare_clk; } ret = isc_parse_dt(dev, isc); @@ -1906,8 +1923,6 @@ static int atmel_isc_probe(struct platform_device *pdev) break; } - pm_runtime_enable(dev); - return 0; cleanup_subdev: @@ -1916,7 +1931,11 @@ static int atmel_isc_probe(struct platform_device *pdev) unregister_v4l2_device: v4l2_device_unregister(&isc->v4l2_dev); -clean_isc_clk: +unprepare_clk: + clk_disable_unprepare(isc->ispck); +unprepare_hclk: + clk_disable_unprepare(isc->hclock); + isc_clk_cleanup(isc); return ret; -- 2.13.0
[PATCH v2 2/5] media: atmel-isc: Add prepare and unprepare ops
A software write operation to the ISC_CLKEN or ISC_CLKDIS register requires double clock domain synchronization and is not permitted when the ISC_SR.SIP is asserted. So add the .prepare and .unprepare ops to make sure the ISC_CLKSR.SIP is unasserted before the write operation to the ISC_CLKEN or ISC_CLKDIS register. Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 30 +++ 2 files changed, 31 insertions(+) diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index 6936ac467609..93e58fcf1d5f 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -42,6 +42,7 @@ /* ISC Clock Status Register */ #define ISC_CLKSR 0x0020 +#define ISC_CLKSR_SIP BIT(31) #define ISC_CLK(n) BIT(n) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 78114193af4c..8b9c1cafa348 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -308,6 +308,34 @@ module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, "Sensor is preferred to output the specified format (1-on 0-off), default 1"); +static int isc_wait_clk_stable(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + struct regmap *regmap = isc_clk->regmap; + unsigned long timeout = jiffies + usecs_to_jiffies(1000); + unsigned int status; + + while (time_before(jiffies, timeout)) { + regmap_read(regmap, ISC_CLKSR, &status); + if (!(status & ISC_CLKSR_SIP)) + return 0; + + usleep_range(10, 250); + } + + return -ETIMEDOUT; +} + +static int isc_clk_prepare(struct clk_hw *hw) +{ + return isc_wait_clk_stable(hw); +} + +static void isc_clk_unprepare(struct clk_hw *hw) +{ + isc_wait_clk_stable(hw); +} + static int isc_clk_enable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); @@ -459,6 +487,8 @@ static int isc_clk_set_rate(struct clk_hw *hw, } static const struct clk_ops isc_clk_ops = { + .prepare= isc_clk_prepare, + .unprepare = isc_clk_unprepare, .enable = isc_clk_enable, .disable= isc_clk_disable, .is_enabled = isc_clk_is_enabled, -- 2.13.0
[PATCH v2 1/5] media: atmel_isc: Add spin lock for clock enable ops
Add the spin lock for the clock enable and disable operations. Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/platform/atmel/atmel-isc.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 2f8e345d297e..78114193af4c 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -65,6 +65,7 @@ struct isc_clk { struct clk_hw hw; struct clk *clk; struct regmap *regmap; + spinlock_t *lock; u8 id; u8 parent_id; u32 div; @@ -312,26 +313,37 @@ static int isc_clk_enable(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; struct regmap *regmap = isc_clk->regmap; + unsigned long flags; + unsigned int status; dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n", __func__, isc_clk->div, isc_clk->parent_id); + spin_lock_irqsave(isc_clk->lock, flags); regmap_update_bits(regmap, ISC_CLKCFG, ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id), (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) | (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id))); regmap_write(regmap, ISC_CLKEN, ISC_CLK(id)); + spin_unlock_irqrestore(isc_clk->lock, flags); - return 0; + regmap_read(regmap, ISC_CLKSR, &status); + if (status & ISC_CLK(id)) + return 0; + else + return -EINVAL; } static void isc_clk_disable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; + unsigned long flags; + spin_lock_irqsave(isc_clk->lock, flags); regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id)); + spin_unlock_irqrestore(isc_clk->lock, flags); } static int isc_clk_is_enabled(struct clk_hw *hw) -- 2.13.0
[PATCH v2 0/5] media: atmel-isc: Rework the format list and the clock
To improve the readability of code, rework the format list table, split the format array into two. Meanwhile, fix the clock operation issue. Changes in v2: - Add the new patch to remove the unnecessary member from isc_subdev_entity struct. - Rebase on the patch set, [PATCH 0/6] [media] Atmel: Adjustments for seven function implementations https://www.mail-archive.com/linux-media@vger.kernel.org/msg118342.html Wenyou Yang (5): media: atmel_isc: Add spin lock for clock enable ops media: atmel-isc: Add prepare and unprepare ops media: atmel-isc: Enable the clocks during probe media: atmel-isc: Remove unnecessary member media: atmel-isc: Rework the format list drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 609 -- 2 files changed, 476 insertions(+), 134 deletions(-) -- 2.13.0
[PATCH v3 3/3] media: ov7670: Add the s_power operation
Add the s_power operation which is responsible for manipulating the power dowm mode through the PWDN pin and the reset operation through the RESET pin. Signed-off-by: Wenyou Yang --- Changes in v3: None Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). drivers/media/i2c/ov7670.c | 32 +++- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 5d6f1859a39b..66b9bf2111f7 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1529,6 +1529,22 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_direction_output(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + static void ov7670_get_default_format(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format) { @@ -1560,6 +1576,7 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .g_register = ov7670_g_register, .s_register = ov7670_s_register, #endif + .s_power = ov7670_s_power, }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { @@ -1673,23 +1690,25 @@ static int ov7670_probe(struct i2c_client *client, if (ret) return ret; - ret = ov7670_init_gpio(client, info); - if (ret) - goto clk_disable; - info->clock_speed = clk_get_rate(info->clk) / 100; if (info->clock_speed < 10 || info->clock_speed > 48) { ret = -EINVAL; goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); @@ -1764,6 +1783,8 @@ static int ov7670_probe(struct i2c_client *client, media_entity_cleanup(&info->sd.entity); hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1779,6 +1800,7 @@ static int ov7670_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); media_entity_cleanup(&info->sd.entity); + ov7670_s_power(sd, 0); return 0; } -- 2.13.0
[PATCH v3 2/3] media: ov7670: Add the get_fmt callback
Add the get_fmt callback, also enable V4L2_SUBDEV_FL_HAS_DEVNODE flag to make this subdev has device node. Signed-off-by: Wenyou Yang --- Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: None drivers/media/i2c/ov7670.c | 58 +- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 5c8460ee65c3..5d6f1859a39b 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -230,6 +230,7 @@ struct ov7670_info { struct v4l2_ctrl *saturation; struct v4l2_ctrl *hue; }; + struct v4l2_mbus_framefmt format; struct ov7670_format_struct *fmt; /* Current format */ struct clk *clk; struct gpio_desc *resetb_gpio; @@ -973,6 +974,9 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, fmt->width = wsize->width; fmt->height = wsize->height; fmt->colorspace = ov7670_formats[index].colorspace; + + info->format = *fmt; + return 0; } @@ -986,6 +990,7 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; struct ov7670_info *info = to_state(sd); + struct v4l2_mbus_framefmt *mbus_fmt; unsigned char com7; int ret; @@ -996,7 +1001,8 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); if (ret) return ret; - cfg->try_fmt = format->format; + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + *mbus_fmt = format->format; return 0; } @@ -1039,6 +1045,23 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, return 0; } +static int ov7670_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct ov7670_info *info = to_state(sd); + struct v4l2_mbus_framefmt *mbus_fmt; + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); + format->format = *mbus_fmt; + } else { + format->format = info->format; + } + + return 0; +} + /* * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. @@ -1506,6 +1529,28 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static void ov7670_get_default_format(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *format) +{ + struct ov7670_info *info = to_state(sd); + + format->width = info->devtype->win_sizes[0].width; + format->height = info->devtype->win_sizes[0].height; + format->colorspace = info->fmt->colorspace; + format->code = info->fmt->mbus_code; + format->field = V4L2_FIELD_NONE; +} + +static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct v4l2_mbus_framefmt *format = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + ov7670_get_default_format(sd, format); + + return 0; +} + /* --- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1526,6 +1571,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, + .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, }; @@ -1535,6 +1581,10 @@ static const struct v4l2_subdev_ops ov7670_ops = { .pad = &ov7670_pad_ops, }; +static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = { + .open = ov7670_open, +}; + /* --- */ static const struct ov7670_devtype ov7670_devdata[] = { @@ -1587,6 +1637,9 @@ static int ov7670_probe(struct i2c_client *client, sd = &info->sd; v4l2_i2c_subdev_init(sd, client, &ov7670_ops); + sd->internal_ops = &ov7670_subdev_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + info->clock_speed = 30; /* default: a guess */ if (client->dev.platform_data) { struct ov7670_config *config = client->dev.platform_data; @@ -1643,6 +1696,9 @@ static int ov7670_probe(struct i2c_client *client,
[PATCH v3 1/3] media: ov7670: Add entity pads initialization
Add the media entity pads initialization. Signed-off-by: Wenyou Yang --- Changes in v3: None Changes in v2: None drivers/media/i2c/ov7670.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..5c8460ee65c3 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,7 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -1688,14 +1689,23 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: + media_entity_cleanup(&info->sd.entity); hdl_free: v4l2_ctrl_handler_free(&info->hdl); clk_disable: @@ -1712,6 +1722,7 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); + media_entity_cleanup(&info->sd.entity); return 0; } -- 2.13.0
[PATCH v3 0/3] media: ov7670: Add entity init and power operation
This patch set is to add the media entity pads initialization, the s_power operation and get_fmt callback support. Changes in v3: - Keep tried format info in the try_fmt member of v4l2_subdev__pad_config struct. - Add the internal_ops callback to set default format. Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). Wenyou Yang (3): media: ov7670: Add entity pads initialization media: ov7670: Add the get_fmt callback media: ov7670: Add the s_power operation drivers/media/i2c/ov7670.c | 103 ++--- 1 file changed, 96 insertions(+), 7 deletions(-) -- 2.13.0
[PATCH v2 3/3] media: ov7670: Add the s_power operation
Add the s_power operation which is responsible for manipulating the power dowm mode through the PWDN pin and the reset operation through the RESET pin. Signed-off-by: Wenyou Yang --- Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). drivers/media/i2c/ov7670.c | 32 +++- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index efc738112e2a..d1211ae48f63 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1530,6 +1530,22 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_direction_output(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + /* --- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1539,6 +1555,7 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .g_register = ov7670_g_register, .s_register = ov7670_s_register, #endif + .s_power = ov7670_s_power, }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { @@ -1645,23 +1662,25 @@ static int ov7670_probe(struct i2c_client *client, if (ret) return ret; - ret = ov7670_init_gpio(client, info); - if (ret) - goto clk_disable; - info->clock_speed = clk_get_rate(info->clk) / 100; if (info->clock_speed < 10 || info->clock_speed > 48) { ret = -EINVAL; goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); @@ -1734,6 +1753,8 @@ static int ov7670_probe(struct i2c_client *client, media_entity_cleanup(&info->sd.entity); hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1749,6 +1770,7 @@ static int ov7670_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); media_entity_cleanup(&info->sd.entity); + ov7670_s_power(sd, 0); return 0; } -- 2.13.0
[PATCH v2 2/3] media: ov7670: Add the get_fmt callback
Add the get_fmt callback, also enable V4L2_SUBDEV_FL_HAS_DEVNODE flag to make this subdev has device node. Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/i2c/ov7670.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 5c8460ee65c3..efc738112e2a 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -230,6 +230,7 @@ struct ov7670_info { struct v4l2_ctrl *saturation; struct v4l2_ctrl *hue; }; + struct v4l2_mbus_framefmt format; struct ov7670_format_struct *fmt; /* Current format */ struct clk *clk; struct gpio_desc *resetb_gpio; @@ -973,6 +974,29 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, fmt->width = wsize->width; fmt->height = wsize->height; fmt->colorspace = ov7670_formats[index].colorspace; + + info->format.code = fmt->code; + info->format.width = fmt->width; + info->format.height = fmt->height; + info->format.colorspace = fmt->colorspace; + + return 0; +} + +static int ov7670_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct ov7670_info *info = to_state(sd); + struct v4l2_mbus_framefmt *fmt; + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) + fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + else + fmt = &info->format; + + format->format = *fmt; + return 0; } @@ -1526,6 +1550,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = { .enum_frame_interval = ov7670_enum_frame_interval, .enum_frame_size = ov7670_enum_frame_size, .enum_mbus_code = ov7670_enum_mbus_code, + .get_fmt = ov7670_get_fmt, .set_fmt = ov7670_set_fmt, }; @@ -1698,6 +1723,7 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_handler_setup(&info->hdl); + info->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) goto entity_cleanup; -- 2.13.0
[PATCH v2 1/3] media: ov7670: Add entity pads initialization
Add the media entity pads initialization. Signed-off-by: Wenyou Yang --- Changes in v2: None drivers/media/i2c/ov7670.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..5c8460ee65c3 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,7 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -1688,14 +1689,23 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: + media_entity_cleanup(&info->sd.entity); hdl_free: v4l2_ctrl_handler_free(&info->hdl); clk_disable: @@ -1712,6 +1722,7 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); + media_entity_cleanup(&info->sd.entity); return 0; } -- 2.13.0
[PATCH v2 0/3] media: ov7670: Add entity init and power operation
This patch set is to add the media entity pads initialization, the s_power operation and get_fmt callback support. Changes in v2: - Add the patch to support the get_fmt ops. - Remove the redundant invoking ov7670_init_gpio(). Wenyou Yang (3): media: ov7670: Add entity pads initialization media: ov7670: Add the get_fmt callback media: ov7670: Add the s_power operation drivers/media/i2c/ov7670.c | 71 ++ 1 file changed, 65 insertions(+), 6 deletions(-) -- 2.13.0
[PATCH 4/4] media: atmel-isc: Rework the format list
To improve the readability of code, split the format array into two, one for the format description, other for the register configuration. Meanwhile, add the flag member to indicate the format can be achieved from the sensor or be produced by the controller, and rename members related to the register configuration. Also add more formats support: GREY, ARGB444, ARGB555 and ARGB32. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 524 --- 1 file changed, 405 insertions(+), 119 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index bc3098982d12..9090004fccdf 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -90,34 +90,56 @@ struct isc_subdev_entity { struct list_head list; }; +#define FMT_FLAG_FROM_SENSOR BIT(0) +#define FMT_FLAG_FROM_CONTROLLER BIT(1) + /* * struct isc_format - ISC media bus format information * @fourcc:Fourcc code for this format * @mbus_code: V4L2 media bus format code. + * flags: Indicate format from sensor or converted by controller * @bpp: Bits per pixel (when stored in memory) - * @reg_bps: reg value for bits per sample * (when transferred over a bus) - * @pipeline: pipeline switch * @sd_support:Subdev supports this format * @isc_support: ISC can convert raw format to this format */ + struct isc_format { u32 fourcc; u32 mbus_code; + u32 flags; u8 bpp; - u32 reg_bps; - u32 reg_bay_cfg; - u32 reg_rlp_mode; - u32 reg_dcfg_imode; - u32 reg_dctrl_dview; - - u32 pipeline; - boolsd_support; boolisc_support; }; +/* Pipeline bitmap */ +#define WB_ENABLE BIT(0) +#define CFA_ENABLE BIT(1) +#define CC_ENABLE BIT(2) +#define GAM_ENABLE BIT(3) +#define GAM_BENABLEBIT(4) +#define GAM_GENABLEBIT(5) +#define GAM_RENABLEBIT(6) +#define CSC_ENABLE BIT(7) +#define CBC_ENABLE BIT(8) +#define SUB422_ENABLE BIT(9) +#define SUB420_ENABLE BIT(10) + +#define GAM_ENABLES(GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) + +struct fmt_config { + u32 fourcc; + + u32 pfe_cfg0_bps; + u32 cfa_baycfg; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; +}; #define HIST_ENTRIES 512 #define HIST_BAYER (ISC_HIS_CFG_MODE_B + 1) @@ -182,80 +204,321 @@ struct isc_device { struct list_headsubdev_entities; }; -#define RAW_FMT_IND_START0 -#define RAW_FMT_IND_END 11 -#define ISC_FMT_IND_START12 -#define ISC_FMT_IND_END 14 - -static struct isc_format isc_formats[] = { - { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, - ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - { V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, 16, - ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, - - { V4L2_PIX_FMT_SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12, 16, - ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0
[PATCH 2/4] media: atmel-isc: Add prepare and unprepare ops
A software write operation to the ISC_CLKEN or ISC_CLKDIS register requires double clock domain synchronization and is not permitted when the ISC_SR.SIP is asserted. So add the .prepare and .unprepare ops to make sure the ISC_CLKSR.SIP is unasserted before the write operation to the ISC_CLKEN or ISC_CLKDIS register. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 30 +++ 2 files changed, 31 insertions(+) diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index 6936ac467609..93e58fcf1d5f 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -42,6 +42,7 @@ /* ISC Clock Status Register */ #define ISC_CLKSR 0x0020 +#define ISC_CLKSR_SIP BIT(31) #define ISC_CLK(n) BIT(n) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index d119c5d39ede..80968f7d79f2 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -308,6 +308,34 @@ module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, "Sensor is preferred to output the specified format (1-on 0-off), default 1"); +static int isc_wait_clk_stable(struct clk_hw *hw) +{ + struct isc_clk *isc_clk = to_isc_clk(hw); + struct regmap *regmap = isc_clk->regmap; + unsigned long timeout = jiffies + usecs_to_jiffies(1000); + unsigned int status; + + while (time_before(jiffies, timeout)) { + regmap_read(regmap, ISC_CLKSR, &status); + if (!(status & ISC_CLKSR_SIP)) + return 0; + + usleep_range(10, 250); + } + + return -ETIMEDOUT; +} + +static int isc_clk_prepare(struct clk_hw *hw) +{ + return isc_wait_clk_stable(hw); +} + +static void isc_clk_unprepare(struct clk_hw *hw) +{ + isc_wait_clk_stable(hw); +} + static int isc_clk_enable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); @@ -459,6 +487,8 @@ static int isc_clk_set_rate(struct clk_hw *hw, } static const struct clk_ops isc_clk_ops = { + .prepare= isc_clk_prepare, + .unprepare = isc_clk_unprepare, .enable = isc_clk_enable, .disable= isc_clk_disable, .is_enabled = isc_clk_is_enabled, -- 2.13.0
[PATCH 3/4] media: atmel-isc: Enable the clocks during probe
To meet the relationship, enable the HCLOCK and ispck during the device probe, "isc_pck frequency is less than or equal to isc_ispck, and isc_ispck is greater than or equal to HCLOCK." Meanwhile, call the pm_runtime_enable() in the right place. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 31 +-- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 80968f7d79f2..bc3098982d12 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -1595,6 +1595,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) struct isc_subdev_entity *sd_entity; struct video_device *vdev = &isc->video_dev; struct vb2_queue *q = &isc->vb2_vidq; + struct device *dev = isc->dev; int ret; ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev); @@ -1678,6 +1679,10 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) return ret; } + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_request_idle(dev); + return 0; } @@ -1857,25 +1862,37 @@ static int atmel_isc_probe(struct platform_device *pdev) return ret; } + ret = clk_prepare_enable(isc->hclock); + if (ret) { + dev_err(dev, "failed to enable hclock: %d\n", ret); + return ret; + } + ret = isc_clk_init(isc); if (ret) { dev_err(dev, "failed to init isc clock: %d\n", ret); - goto clean_isc_clk; + goto unprepare_hclk; } isc->ispck = isc->isc_clks[ISC_ISPCK].clk; + ret = clk_prepare_enable(isc->ispck); + if (ret) { + dev_err(dev, "failed to enable ispck: %d\n", ret); + goto unprepare_hclk; + } + /* ispck should be greater or equal to hclock */ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); if (ret) { dev_err(dev, "failed to set ispck rate: %d\n", ret); - goto clean_isc_clk; + goto unprepare_clk; } ret = v4l2_device_register(dev, &isc->v4l2_dev); if (ret) { dev_err(dev, "unable to register v4l2 device.\n"); - goto clean_isc_clk; + goto unprepare_clk; } ret = isc_parse_dt(dev, isc); @@ -1908,8 +1925,6 @@ static int atmel_isc_probe(struct platform_device *pdev) break; } - pm_runtime_enable(dev); - return 0; cleanup_subdev: @@ -1918,7 +1933,11 @@ static int atmel_isc_probe(struct platform_device *pdev) unregister_v4l2_device: v4l2_device_unregister(&isc->v4l2_dev); -clean_isc_clk: +unprepare_clk: + clk_disable_unprepare(isc->ispck); +unprepare_hclk: + clk_disable_unprepare(isc->hclock); + isc_clk_cleanup(isc); return ret; -- 2.13.0
[PATCH 1/4] media: atmel_isc: Add spin lock for clock enable ops
Add the spin lock for the clock enable and disable operations. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index d7103c5f92c3..d119c5d39ede 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -65,6 +65,7 @@ struct isc_clk { struct clk_hw hw; struct clk *clk; struct regmap *regmap; + spinlock_t *lock; u8 id; u8 parent_id; u32 div; @@ -312,26 +313,37 @@ static int isc_clk_enable(struct clk_hw *hw) struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; struct regmap *regmap = isc_clk->regmap; + unsigned long flags; + unsigned int status; dev_dbg(isc_clk->dev, "ISC CLK: %s, div = %d, parent id = %d\n", __func__, isc_clk->div, isc_clk->parent_id); + spin_lock_irqsave(isc_clk->lock, flags); regmap_update_bits(regmap, ISC_CLKCFG, ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id), (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) | (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id))); regmap_write(regmap, ISC_CLKEN, ISC_CLK(id)); + spin_unlock_irqrestore(isc_clk->lock, flags); - return 0; + regmap_read(regmap, ISC_CLKSR, &status); + if (status & ISC_CLK(id)) + return 0; + else + return -EINVAL; } static void isc_clk_disable(struct clk_hw *hw) { struct isc_clk *isc_clk = to_isc_clk(hw); u32 id = isc_clk->id; + unsigned long flags; + spin_lock_irqsave(isc_clk->lock, flags); regmap_write(isc_clk->regmap, ISC_CLKDIS, ISC_CLK(id)); + spin_unlock_irqrestore(isc_clk->lock, flags); } static int isc_clk_is_enabled(struct clk_hw *hw) -- 2.13.0
[PATCH 0/4] media: atmel-isc: Rework the format list and the clock
To improve the readability of code, rework the format list table, split the format array into two. And fix the clock operation issue. Wenyou Yang (4): media: atmel_isc: Add spin lock for clock enable ops media: atmel-isc: Add prepare and unprepare ops media: atmel-isc: Enable the clocks during probe media: atmel-isc: Rework the format list drivers/media/platform/atmel/atmel-isc-regs.h | 1 + drivers/media/platform/atmel/atmel-isc.c | 599 -- 2 files changed, 474 insertions(+), 126 deletions(-) -- 2.13.0
[PATCH 3/3] media: atmel-isc: Add more format configurations
Add the configuration of formats: GREY, ARGB444, ARGB555 and ARGB32. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 22 -- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index d91f4e5f8a8d..4e18fe1104c8 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -184,7 +184,7 @@ struct isc_device { #define RAW_FMT_IND_START0 #define RAW_FMT_IND_END 11 #define ISC_FMT_IND_START12 -#define ISC_FMT_IND_END 14 +#define ISC_FMT_IND_END 18 static struct isc_format isc_formats[] = { /* 0 */ @@ -246,12 +246,30 @@ static struct isc_format isc_formats[] = { { V4L2_PIX_FMT_YUV422P, 0x0, 16, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, ISC_DCFG_IMODE_YC422P, ISC_DCTRL_DVIEW_PLANAR, 0x3fb }, + /* 14 */ + { V4L2_PIX_FMT_GREY, MEDIA_BUS_FMT_Y8_1X8, 8, + ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DATY8, + ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x1fb }, + + /* 15 */ + { V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, 16, + ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_ARGB444, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x7b }, + /* 16 */ + { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, 16, + ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_ARGB555, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x7b }, + /* 17 */ { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_RGB565_2X8_LE, 16, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_RGB565, ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x7b }, + /* 18 */ + { V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB_1X32, 32, + ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_ARGB32, + ISC_DCFG_IMODE_PACKED32, ISC_DCTRL_DVIEW_PACKED, 0x7b }, - /* 15 */ + /* 19 */ { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_YUYV8_2X8, 16, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0 }, -- 2.13.0
[PATCH 2/3] media: atmel-isc: Remove the redundant assignment
Remove the redundant assignment of members in the isc_formats array. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 64 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 535bb03783fe..d91f4e5f8a8d 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -187,74 +187,74 @@ struct isc_device { #define ISC_FMT_IND_END 14 static struct isc_format isc_formats[] = { + /* 0 */ { V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, 8, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 1 */ { V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, 8, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 2 */ { V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, 8, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 3 */ { V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, 8, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT8, - ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED8, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 4 */ { V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, 16, ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 5 */ { V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, 16, ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 6 */ { V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, 16, ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 7 */ { V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, 16, ISC_PFG_CFG0_BPS_TEN, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT10, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 8 */ { V4L2_PIX_FMT_SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12, 16, ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 9 */ { V4L2_PIX_FMT_SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12, 16, ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_GBGB, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 10 */ { V4L2_PIX_FMT_SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12, 16, ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_GRGR, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 11 */ { V4L2_PIX_FMT_SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12, 16, ISC_PFG_CFG0_BPS_TWELVE, ISC_BAY_CFG_RGRG, ISC_RLP_CFG_MODE_DAT12, - ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0, - false, false }, + ISC_DCFG_IMODE_PACKED16, ISC_DCTRL_DVIEW_PACKED, 0x0 }, + /* 12 */ { V4L2_PIX_FMT_YUV420, 0x0, 12, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, - ISC_DCFG_IMODE_YC420P, ISC_DCTRL_DVIEW_PLANAR, 0x7fb, - false, false }, + ISC_DCFG_IMODE_YC420P, ISC_DCTRL_DVIEW_PLANAR, 0x7fb }, + /* 13 */ { V4L2_PIX_FMT_YUV422P, 0x0, 16, ISC_PFE_CFG0_BPS_EIGHT, ISC_BAY_CFG_BGBG, ISC_RLP_CFG_MODE_YYCC, - ISC_DCFG_IMODE_YC422P, ISC_DCTRL_DVIEW_PLANAR, 0x3fb, - false, false }, + ISC_DCFG_IMODE_YC422P, ISC_DCTRL_DVIEW_PLANAR, 0x3fb }, + /* 14 */ { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_RGB565_2X8_LE, 16, ISC_PFE_CFG0_BPS_EIGHT
[PATCH 1/3] media: atmel-isc: Not support RBG format from sensor.
The 12-bit parallel interface supports the Raw Bayer, YCbCr, Monochrome and JPEG Compressed pixel formats from the external sensor, not support RBG pixel format. Signed-off-by: Wenyou Yang --- drivers/media/platform/atmel/atmel-isc.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index d4df3d4ccd85..535bb03783fe 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -1478,6 +1478,11 @@ static int isc_formats_init(struct isc_device *isc) while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &mbus_code)) { mbus_code.index++; + + /* Not support the RGB pixel formats from sensor */ + if ((mbus_code.code & 0xf000) == 0x1000) + continue; + fmt = find_format_by_code(mbus_code.code, &i); if (!fmt) continue; -- 2.13.0
[PATCH 0/3] media: atmel-isc: Supplement the configuration of formats
The intention of the patch set is to add more configuration of formats: GREY, ARGB444, ARGB555 and ARGB32, and add the checking the format from the extern sensor which doesn't support RGB formats from the external sensor. Wenyou Yang (3): media: atmel-isc: Not support RBG format from sensor. media: atmel-isc: Remove the redundant assignment media: atmel-isc: Add more format configurations drivers/media/platform/atmel/atmel-isc.c | 89 1 file changed, 56 insertions(+), 33 deletions(-) -- 2.13.0
[PATCH] ARM: dts: at91: sama5d2_xplained: Add charger node
From: Wenyou Yang Add the charger device node as a sub-device of act8945a mfd, move the charger's properties in the node, and replace the "active-semi,irq_gpios" with the "interrupts" property to denote the act8945a charger's irq. Signed-off-by: Wenyou Yang --- arch/arm/boot/dts/at91-sama5d2_xplained.dts | 23 +++ 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 2e2c3d1a1fa2..2a0f5f41260f 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -160,14 +160,6 @@ compatible = "active-semi,act8945a"; reg = <0x5b>; active-semi,vsel-high; - active-semi,chglev-gpios = <&pioA 12 GPIO_ACTIVE_HIGH>; - active-semi,lbo-gpios = <&pioA 72 GPIO_ACTIVE_LOW>; - active-semi,irq_gpios = <&pioA 45 GPIO_ACTIVE_LOW>; - active-semi,input-voltage-threshold-microvolt = <6600>; - active-semi,precondition-timeout = <40>; - active-semi,total-timeout = <3>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>; status = "okay"; regulators { @@ -220,6 +212,21 @@ regulator-always-on; }; }; + + charger { + compatible = "active-semi,act8945a-charger"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>; + interrupt-parent = <&pioA>; + interrupts = <45 GPIO_ACTIVE_LOW>; + + active-semi,chglev-gpios = <&pioA 12 GPIO_ACTIVE_HIGH>; + active-semi,lbo-gpios = <&pioA 72 GPIO_ACTIVE_LOW>; + active-semi,input-voltage-threshold-microvolt = <6600>; + active-semi,precondition-timeout = <40>; + active-semi,total-timeout = <3>; + status = "okay"; + }; }; }; -- 2.13.0
[PATCH 2/2] media: ov7670: Add the s_power operation
Add the s_power operation which is responsible for manipulating the power dowm mode through the PWDN pin and the reset operation through the RESET pin. Signed-off-by: Wenyou Yang --- drivers/media/i2c/ov7670.c | 30 +++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 5c8460ee65c3..5ed79ccfaf91 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1506,6 +1506,22 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif +static int ov7670_s_power(struct v4l2_subdev *sd, int on) +{ + struct ov7670_info *info = to_state(sd); + + if (info->pwdn_gpio) + gpiod_direction_output(info->pwdn_gpio, !on); + if (on && info->resetb_gpio) { + gpiod_set_value(info->resetb_gpio, 1); + usleep_range(500, 1000); + gpiod_set_value(info->resetb_gpio, 0); + usleep_range(3000, 5000); + } + + return 0; +} + /* --- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1515,6 +1531,7 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .g_register = ov7670_g_register, .s_register = ov7670_s_register, #endif + .s_power = ov7670_s_power, }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { @@ -1568,8 +1585,6 @@ static int ov7670_init_gpio(struct i2c_client *client, struct ov7670_info *info) return PTR_ERR(info->resetb_gpio); } - usleep_range(3000, 5000); - return 0; } @@ -1630,13 +1645,19 @@ static int ov7670_probe(struct i2c_client *client, goto clk_disable; } + ret = ov7670_init_gpio(client, info); + if (ret) + goto clk_disable; + + ov7670_s_power(sd, 1); + /* Make sure it's an ov7670 */ ret = ov7670_detect(sd); if (ret) { v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - goto clk_disable; + goto power_off; } v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); @@ -1708,6 +1729,8 @@ static int ov7670_probe(struct i2c_client *client, media_entity_cleanup(&info->sd.entity); hdl_free: v4l2_ctrl_handler_free(&info->hdl); +power_off: + ov7670_s_power(sd, 0); clk_disable: clk_disable_unprepare(info->clk); return ret; @@ -1723,6 +1746,7 @@ static int ov7670_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); media_entity_cleanup(&info->sd.entity); + ov7670_s_power(sd, 0); return 0; } -- 2.13.0
[PATCH 1/2] media: ov7670: Add entity pads initialization
Add the media entity pads initialization. Signed-off-by: Wenyou Yang --- drivers/media/i2c/ov7670.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e88549f0e704..5c8460ee65c3 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -213,6 +213,7 @@ struct ov7670_devtype { struct ov7670_format_struct; /* coming later */ struct ov7670_info { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; struct { /* gain cluster */ @@ -1688,14 +1689,23 @@ static int ov7670_probe(struct i2c_client *client, v4l2_ctrl_auto_cluster(2, &info->auto_exposure, V4L2_EXPOSURE_MANUAL, false); v4l2_ctrl_cluster(2, &info->saturation); + + info->pad.flags = MEDIA_PAD_FL_SOURCE; + info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); + if (ret < 0) + goto hdl_free; + v4l2_ctrl_handler_setup(&info->hdl); ret = v4l2_async_register_subdev(&info->sd); if (ret < 0) - goto hdl_free; + goto entity_cleanup; return 0; +entity_cleanup: + media_entity_cleanup(&info->sd.entity); hdl_free: v4l2_ctrl_handler_free(&info->hdl); clk_disable: @@ -1712,6 +1722,7 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); clk_disable_unprepare(info->clk); + media_entity_cleanup(&info->sd.entity); return 0; } -- 2.13.0
[PATCH 0/2] media: ov7670: Add entity init and power operation
This patch set is to add the media entity pads initialization and add the s_power operation. Wenyou Yang (2): media: ov7670: Add entity pads initialization media: ov7670: Add the s_power operation drivers/media/i2c/ov7670.c | 43 +++ 1 file changed, 39 insertions(+), 4 deletions(-) -- 2.13.0
[PATCH v2] ARM: at91/defconfig: add MCAN driver to sama5_defconfig
Add the Controller Area Network (MCAN) driver compilation for sama5 default configuration. Is used by sama5d2 SoC for instance. Signed-off-by: Wenyou Yang --- Changes in v2: - Rebase on Linux-4.12-rc1. arch/arm/configs/sama5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index 777c9e986425..01f7dedd570d 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -52,6 +52,7 @@ CONFIG_IP_PNP_RARP=y CONFIG_IPV6_SIT_6RD=y CONFIG_CAN=y CONFIG_CAN_AT91=y +CONFIG_CAN_M_CAN=y CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_MAC80211_LEDS=y -- 2.11.0
[PATCH v3] ARM: dts: at91: sama5d2: add m_can nodes
Add nodes to support the Controller Area Network(M_CAN) on SAMA5D2. The version of M_CAN IP core is 3.1.0 (CREL = 0x31040730). As said in SAMA5D2 datasheet, the CAN clock is recommended to use frequencies of 20, 40 or 80 MHz. To achieve these frequencies, PMC GCLK3 must select the UPLLCK(480 MHz) as source clock and divide by 24, 12, or 6. So, the "assigned-clock-rates" property has three options: 2000, 4000, and 8000. The "assigned-clock-parents" property should be referred to utmi fixedly. The MSBs [bits 31:16] of the CAN Message RAM for CAN0 and CAN1 are default configured in 0x0020. To avoid conflict with SRAM map for PM, change them to 0x0021 in the AT91Bootstrap via setting the CAN Memories Address-based Register(SFR_CAN) of SFR. Signed-off-by: Wenyou Yang Tested-by: Quentin Schulz --- The patch is tested on SAMA5D2 Xplained and based on the patch set, 1. [PATCH v4 1/7] can: m_can: Disabled Interrupt Line 1 http://marc.info/?l=linux-can&m=149165343604033&w=2 Changes in v3: - Add Tested-by tag. - Change the number of Rx Rx Buffers, Tx Buffers and Tx Event FIFO to maximum. Changes in v2: - Configures 10 TX Event FIFO elements and 10 TX Buffers/FIFO slots, because the TXE FIFO is needed to be configured. - Configure the offset of Message RAM for CAN1 followed from CAN0's. arch/arm/boot/dts/at91-sama5d2_xplained.dts | 24 + arch/arm/boot/dts/sama5d2.dtsi | 56 + 2 files changed, 80 insertions(+) diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 9f7f8a7d8ff9..2f19b08dc226 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -257,6 +257,12 @@ status = "okay"; }; + can0: can@f8054000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can0_default>; + status = "okay"; + }; + uart3: serial@fc008000 { atmel,use-dma-rx; atmel,use-dma-tx; @@ -321,6 +327,18 @@ bias-disable; }; + pinctrl_can0_default: can0_default { + pinmux = , +; + bias-disable; + }; + + pinctrl_can1_default: can1_default { + pinmux = , +; + bias-disable; + }; + pinctrl_charger_chglev: charger_chglev { pinmux = ; bias-disable; @@ -468,6 +486,12 @@ }; }; + + can1: can@fc05 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1_default>; + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 22332be72140..7e00fa21373e 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -762,6 +762,18 @@ atmel,clk-output-range = <0 8300>; }; + can0_clk: can0_clk { + #clock-cells = <0>; + reg = <56>; + atmel,clk-output-range = <0 8300>; + }; + + can1_clk: can1_clk { + #clock-cells = <0>; + reg = <57>; + atmel,clk-output-range = <0 8300>; + }; + classd_clk: classd_clk { #clock-cells = <0>; reg = <59>; @@ -890,6 +902,18 @@ #clock-cells = <0>; reg = <55>;
[PATCH v2] ARM: dts: at91: sama5d2: add m_can nodes
Add nodes to support the Controller Area Network(M_CAN) on SAMA5D2. The version of M_CAN IP core is 3.1.0 (CREL = 0x31040730). As said in SAMA5D2 datasheet, the CAN clock is recommended to use frequencies of 20, 40 or 80 MHz. To achieve these frequencies, PMC GCLK3 must select the UPLLCK(480 MHz) as source clock and divide by 24, 12, or 6. So, the "assigned-clock-rates" property has three options: 2000, 4000, and 8000. The "assigned-clock-parents" property should be referred to utmi fixedly. The MSBs [bits 31:16] of the CAN Message RAM for CAN0 and CAN1 are default configured in 0x0020. To avoid conflict with SRAM map for PM, change them to 0x0021 in the AT91Bootstrap via setting the CAN Memories Address-based Register(SFR_CAN) of SFR. Signed-off-by: Wenyou Yang --- The patch is tested on SAMA5D2 Xplained and based on the patch set, 1. [PATCH v4 1/7] can: m_can: Disabled Interrupt Line 1 http://marc.info/?l=linux-can&m=149165343604033&w=2 Changes in v2: - Configures 10 TX Event FIFO elements and 10 TX Buffers/FIFO slots, because the TXE FIFO is needed to be configured. - Configure the offset of Message RAM for CAN1 followed from CAN0's. arch/arm/boot/dts/at91-sama5d2_xplained.dts | 24 + arch/arm/boot/dts/sama5d2.dtsi | 56 + 2 files changed, 80 insertions(+) diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 9f7f8a7d8ff9..2f19b08dc226 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -257,6 +257,12 @@ status = "okay"; }; + can0: can@f8054000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can0_default>; + status = "okay"; + }; + uart3: serial@fc008000 { atmel,use-dma-rx; atmel,use-dma-tx; @@ -321,6 +327,18 @@ bias-disable; }; + pinctrl_can0_default: can0_default { + pinmux = , +; + bias-disable; + }; + + pinctrl_can1_default: can1_default { + pinmux = , +; + bias-disable; + }; + pinctrl_charger_chglev: charger_chglev { pinmux = ; bias-disable; @@ -468,6 +486,12 @@ }; }; + + can1: can@fc05 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1_default>; + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 22332be72140..383ca9307edf 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -762,6 +762,18 @@ atmel,clk-output-range = <0 8300>; }; + can0_clk: can0_clk { + #clock-cells = <0>; + reg = <56>; + atmel,clk-output-range = <0 8300>; + }; + + can1_clk: can1_clk { + #clock-cells = <0>; + reg = <57>; + atmel,clk-output-range = <0 8300>; + }; + classd_clk: classd_clk { #clock-cells = <0>; reg = <59>; @@ -890,6 +902,18 @@ #clock-cells = <0>; reg = <55>; }; + + can0_gclk: can0_gclk { +
[PATCH] ARM: dts: at91: sama5d2: add m_can nodes
Add nodes to support the Controller Area Network(M_CAN) on SAMA5D2. As said in SAMA5D2 datasheet, the CAN clock is recommended to use frequencies of 20, 40 or 80 MHz. To achieve these frequencies, PMC GCLK3 must select the UPLLCK(480 MHz) as source clock and divide by 24, 12, or 6. So, the "assigned-clock-rates" property has three options: 2000, 4000, and 8000. The "assigned-clock-parents" property should be referred to utmi fixedly. The MSBs [bits 31:16] of the CAN Message RAM for CAN0 and CAN1 are default configured in 0x0020. To avoid conflict with SRAM map for pm, change them to 0x0021 in the AT91Bootstrap via setting the CAN Memories Address-based Register(SFR_CAN) of SFR. Signed-off-by: Wenyou Yang --- arch/arm/boot/dts/at91-sama5d2_xplained.dts | 24 + arch/arm/boot/dts/sama5d2.dtsi | 56 + 2 files changed, 80 insertions(+) diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 9f7f8a7d8ff9..2f19b08dc226 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -257,6 +257,12 @@ status = "okay"; }; + can0: can@f8054000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can0_default>; + status = "okay"; + }; + uart3: serial@fc008000 { atmel,use-dma-rx; atmel,use-dma-tx; @@ -321,6 +327,18 @@ bias-disable; }; + pinctrl_can0_default: can0_default { + pinmux = , +; + bias-disable; + }; + + pinctrl_can1_default: can1_default { + pinmux = , +; + bias-disable; + }; + pinctrl_charger_chglev: charger_chglev { pinmux = ; bias-disable; @@ -468,6 +486,12 @@ }; }; + + can1: can@fc05 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1_default>; + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index 22332be72140..d2febea79cfb 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -762,6 +762,18 @@ atmel,clk-output-range = <0 8300>; }; + can0_clk: can0_clk { + #clock-cells = <0>; + reg = <56>; + atmel,clk-output-range = <0 8300>; + }; + + can1_clk: can1_clk { + #clock-cells = <0>; + reg = <57>; + atmel,clk-output-range = <0 8300>; + }; + classd_clk: classd_clk { #clock-cells = <0>; reg = <59>; @@ -890,6 +902,18 @@ #clock-cells = <0>; reg = <55>; }; + + can0_gclk: can0_gclk { + #clock-cells = <0>; + reg = <56>; + atmel,clk-output-range = <0 8000>; + }; + + can1_gclk: can1_gclk { + #clock-cells = <0>; + reg = <57>; + atmel,clk-output-range
[PATCH] ARM: at91/defconfig: add MCAN driver to sama5_defconfig
Add the Controller Area Network (MCAN) driver compilation for sama5 default configuration. Is used by sama5d2 SoC for instance. Signed-off-by: Wenyou Yang --- arch/arm/configs/sama5_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index 777c9e986425..01f7dedd570d 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -52,6 +52,7 @@ CONFIG_IP_PNP_RARP=y CONFIG_IPV6_SIT_6RD=y CONFIG_CAN=y CONFIG_CAN_AT91=y +CONFIG_CAN_M_CAN=y CONFIG_CFG80211=y CONFIG_MAC80211=y CONFIG_MAC80211_LEDS=y -- 2.11.0
[PATCH v2] can: m_can: enable transmission of FD frame on latest version
Enables the transmission of CAN FD frames on M_CAN IP core >= v3.1.x and with the bit rate switching. Tested on M_CAN IP 3.1.0 (CREL = 0x31040730) of SAMA5D2 SoC. Signed-off-by: Wenyou Yang --- The testing is based on [RESEND PATCH 1/1] can: m_can: fix bitrate setup on latest silicon http://lkml.iu.edu/hypermail/linux/kernel/1702.1/05347.html Changes in v2: - Rename TX_BUF_EDL with TX_BUF_FDF. - Improve the commit log to avoid misleading. drivers/net/can/m_can/m_can.c | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 246584ed89b6..c2dd2550de40 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -283,8 +283,12 @@ enum m_can_mram_cfg { /* Tx Buffer Element */ /* R0 */ +#define TX_BUF_ESI BIT(31) #define TX_BUF_XTD BIT(30) #define TX_BUF_RTR BIT(29) +#define TX_BUF_EFC BIT(23) +#define TX_BUF_FDF BIT(21) +#define TX_BUF_BRS BIT(20) /* address offset and element number for each FIFO/Buffer in the Message RAM */ struct mram_cfg { @@ -916,7 +920,7 @@ static void m_can_chip_config(struct net_device *dev) } if (priv->can.ctrlmode & CAN_CTRLMODE_FD) - cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT; + cccr |= (CCCR_CME_CANFD_BRS | CCCR_CME_CANFD) << CCCR_CME_SHIFT; m_can_write(priv, M_CAN_CCCR, cccr); m_can_write(priv, M_CAN_TEST, test); @@ -1079,6 +1083,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, struct canfd_frame *cf = (struct canfd_frame *)skb->data; u32 id, cccr; int i; + u32 dlc; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; @@ -1097,7 +1102,6 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, /* message ram configuration */ m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id); - m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16); for (i = 0; i < cf->len; i += 4) m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4), @@ -1105,20 +1109,29 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, can_put_echo_skb(skb, dev, 0); + dlc = can_len2dlc(cf->len) << 16; + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { cccr = m_can_read(priv, M_CAN_CCCR); cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT); if (can_is_canfd_skb(skb)) { - if (cf->flags & CANFD_BRS) + dlc |= TX_BUF_FDF; + if (cf->flags & CANFD_ESI) + dlc |= TX_BUF_ESI; + if (cf->flags & CANFD_BRS) { + dlc |= TX_BUF_BRS; cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT; - else + } else { cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT; + } } else { cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT; } m_can_write(priv, M_CAN_CCCR, cccr); } + m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, dlc); + /* enable first TX buffer to start transfer */ m_can_write(priv, M_CAN_TXBTIE, 0x1); m_can_write(priv, M_CAN_TXBAR, 0x1); -- 2.11.0
[PATCH] can: m_can: support transmit frame in CAN FD format
Add support to transmit the frame in the CAN FD format and with the bit rate switching. Tested on SAMA5D2 Xplained board. Signed-off-by: Wenyou Yang --- The testing is based on [RESEND PATCH 1/1] can: m_can: fix bitrate setup on latest silicon http://lkml.iu.edu/hypermail/linux/kernel/1702.1/05347.html drivers/net/can/m_can/m_can.c | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 195f15edb32e..9ef9b337d25b 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -266,8 +266,12 @@ enum m_can_mram_cfg { /* Tx Buffer Element */ /* R0 */ +#define TX_BUF_ESI BIT(31) #define TX_BUF_XTD BIT(30) #define TX_BUF_RTR BIT(29) +#define TX_BUF_EFC BIT(23) +#define TX_BUF_EDL BIT(21) +#define TX_BUF_BRS BIT(20) /* address offset and element number for each FIFO/Buffer in the Message RAM */ struct mram_cfg { @@ -884,7 +888,7 @@ static void m_can_chip_config(struct net_device *dev) } if (priv->can.ctrlmode & CAN_CTRLMODE_FD) - cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT; + cccr |= (CCCR_CME_CANFD_BRS | CCCR_CME_CANFD) << CCCR_CME_SHIFT; m_can_write(priv, M_CAN_CCCR, cccr); m_can_write(priv, M_CAN_TEST, test); @@ -1047,6 +1051,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, struct canfd_frame *cf = (struct canfd_frame *)skb->data; u32 id, cccr; int i; + u32 dlc; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; @@ -1065,7 +1070,6 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, /* message ram configuration */ m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id); - m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16); for (i = 0; i < cf->len; i += 4) m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4), @@ -1073,20 +1077,29 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, can_put_echo_skb(skb, dev, 0); + dlc = can_len2dlc(cf->len) << 16; + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { cccr = m_can_read(priv, M_CAN_CCCR); cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT); if (can_is_canfd_skb(skb)) { - if (cf->flags & CANFD_BRS) + dlc |= TX_BUF_EDL; + if (cf->flags & CANFD_ESI) + dlc |= TX_BUF_ESI; + if (cf->flags & CANFD_BRS) { + dlc |= TX_BUF_BRS; cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT; - else + } else { cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT; + } } else { cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT; } m_can_write(priv, M_CAN_CCCR, cccr); } + m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, dlc); + /* enable first TX buffer to start transfer */ m_can_write(priv, M_CAN_TXBTIE, 0x1); m_can_write(priv, M_CAN_TXBAR, 0x1); -- 2.11.0
[PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
For the SoCs such as SAMA5D2 and SAMA5D4 which have L2 cache, flush the L2 cache first before entering the cpu idle. Signed-off-by: Wenyou Yang --- arch/arm/mach-at91/pm.c | 19 +++ drivers/memory/atmel-sdramc.c | 1 + 2 files changed, 20 insertions(+) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index b4332b727e9c..1a60dede1a01 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -289,6 +289,24 @@ static void at91_ddr_standby(void) at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); } +static void at91_ddr_cache_standby(void) +{ + u32 saved_lpr; + + flush_cache_all(); + outer_disable(); + + saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR); + at91_ramc_write(0, AT91_DDRSDRC_LPR, (saved_lpr & + (~AT91_DDRSDRC_LPCB)) | AT91_DDRSDRC_LPCB_SELF_REFRESH); + + cpu_do_idle(); + + at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr); + + outer_resume(); +} + /* We manage both DDRAM/SDRAM controllers, we need more than one value to * remember. */ @@ -324,6 +342,7 @@ static const struct of_device_id const ramc_ids[] __initconst = { { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, { .compatible = "atmel,sama5d3-ddramc", .data = at91_ddr_standby }, + { .compatible = "atmel,sama5d4-ddramc", .data = at91_ddr_cache_standby }, { /*sentinel*/ } }; diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c index b418b39af180..7e5c5c6c1348 100644 --- a/drivers/memory/atmel-sdramc.c +++ b/drivers/memory/atmel-sdramc.c @@ -48,6 +48,7 @@ static const struct of_device_id atmel_ramc_of_match[] = { { .compatible = "atmel,at91sam9260-sdramc", .data = &at91rm9200_caps, }, { .compatible = "atmel,at91sam9g45-ddramc", .data = &at91sam9g45_caps, }, { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, }, + { .compatible = "atmel,sama5d4-ddramc", .data = &sama5d3_caps, }, {}, }; -- 2.11.0
[PATCH 0/3] ARM: at91: fix cpuidle crash on SAMA5D4 Xplained board
Fix cpuidle crash on SAMA5D4 Xplained board when enable CONFIG_ARM_AT91_CPUIDLE. Because some SoCs have the L2 cache, we should flush the L2 cache before entering the cpu idle. Wenyou Yang (3): ARM: at91: flush the L2 cache before entering cpu idle doc: binding: add new compatible for SDRAM/DDR Controller ARM: dts: at91: use "atmel,sama5d4-ddramc" for ramc Documentation/devicetree/bindings/arm/atmel-at91.txt | 1 + arch/arm/boot/dts/sama5d2.dtsi | 2 +- arch/arm/boot/dts/sama5d4.dtsi | 2 +- arch/arm/mach-at91/pm.c | 19 +++ drivers/memory/atmel-sdramc.c| 1 + 5 files changed, 23 insertions(+), 2 deletions(-) -- 2.11.0
[PATCH 2/3] doc: binding: add new compatible for SDRAM/DDR Controller
Add the new compatible "atmel,sama5d4-ddramc" for the SDRAM/DDR Controller. Signed-off-by: Wenyou Yang --- Documentation/devicetree/bindings/arm/atmel-at91.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index 29737b9b616e..9b5de6397666 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -111,6 +111,7 @@ RAMC SDRAM/DDR Controller required properties: "atmel,at91sam9260-sdramc", "atmel,at91sam9g45-ddramc", "atmel,sama5d3-ddramc", + "atmel,sama5d4-ddramc", - reg: Should contain registers location and length Examples: -- 2.11.0
[PATCH 3/3] ARM: dts: at91: use "atmel,sama5d4-ddramc" for ramc
Use the new compatible "atmel,sama5d4-ddramc" for the ramc of SAMA5D2 and SAMA5D4. Signed-off-by: Wenyou Yang --- arch/arm/boot/dts/sama5d2.dtsi | 2 +- arch/arm/boot/dts/sama5d4.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index ceb9783ff7e1..b5259d85737d 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -380,7 +380,7 @@ }; ramc0: ramc@f000c000 { - compatible = "atmel,sama5d3-ddramc"; + compatible = "atmel,sama5d4-ddramc"; reg = <0xf000c000 0x200>; clocks = <&ddrck>, <&mpddr_clk>; clock-names = "ddrck", "mpddr"; diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index 4f60c1b7b137..603ba986858c 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -370,7 +370,7 @@ }; ramc0: ramc@f001 { - compatible = "atmel,sama5d3-ddramc"; + compatible = "atmel,sama5d4-ddramc"; reg = <0xf001 0x200>; clocks = <&ddrck>, <&mpddr_clk>; clock-names = "ddrck", "mpddr"; -- 2.11.0
[PATCH v3] ARM: at91/dt: add dts file for sama5d36ek CMP board
The sama5d36ek CMP board is the variant of sama5d3xek board. It is equipped with the low-power DDR2 SDRAM, PMIC ACT8865 and some power rail. Its main purpose is used to measure the power consumption. The difference of the sama5d36ek CMP dts from sama5d36ek dts is listed as below. 1. The USB host nodes are removed, that is, the USB host is disabled. 2. The gpio_keys node is added to wake up from the sleep. 3. The LCD isn't supported due to the pins for LCD are conflicted with gpio_keys. 4. The adc0 node support the pinctrl sleep state to fix the over consumption on VDDANA. As said in errata, "When the USB host ports are used in high speed mode (EHCI), it is not possible to suspend the ports if no device is attached on each port. This leads to increased power consumption even if the system is in a low power mode." That is why the the USB host is disabled. Signed-off-by: Wenyou Yang --- Changes in v3: - Use a dual license scheme for DT files. - Use the proper model name and the compatible string to reflect the nature of this new "CMP" board. - Change name of wakeup property to "wakeup-source". - Remove unnecessary comments. - Remove bootargs. Changes in v2: - Add the pinctrl sleep state for adc0 node to fix the over consumption on VDDANA. - Improve the commit log. arch/arm/boot/dts/sama5d36ek_cmp.dts | 87 ++ arch/arm/boot/dts/sama5d3xcm_cmp.dtsi | 201 +++ arch/arm/boot/dts/sama5d3xmb_cmp.dtsi | 301 ++ 3 files changed, 589 insertions(+) create mode 100644 arch/arm/boot/dts/sama5d36ek_cmp.dts create mode 100644 arch/arm/boot/dts/sama5d3xcm_cmp.dtsi create mode 100644 arch/arm/boot/dts/sama5d3xmb_cmp.dtsi diff --git a/arch/arm/boot/dts/sama5d36ek_cmp.dts b/arch/arm/boot/dts/sama5d36ek_cmp.dts new file mode 100644 index 000..b632143 --- /dev/null +++ b/arch/arm/boot/dts/sama5d36ek_cmp.dts @@ -0,0 +1,87 @@ +/* + * sama5d36ek_cmp.dts - Device Tree file for SAMA5D36-EK CMP board + * + * Copyright (C) 2016 Atmel, + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +/dts-v1/; +#include "sama5d36.dtsi" +#include "sama5d3xmb_cmp.dtsi" + +/ { + model = "Atmel SAMA5D36EK-CMP"; + compatible = "atmel,sama5d36ek-cmp", "atmel,sama5d3xmb-cmp", "atmel,sama5d3xcm-cmp", "atmel,sama5d36", "atmel,sama5d3", "atmel,sama5"; + + ahb { + apb { + spi0: spi@f0004000 { + status = "okay"; + }; + + ssc0: ssc@f0008000 { + status = "okay"; + }; + + can0: can@f000c000 { + status = "okay"; + }; + + i2c0: i2c@f0014000 { + status = "okay"; +
[PATCH v2] iio: adc: at91: add suspend and resume callback
Add suspend/resume callback, support the pinctrl sleep state when the system suspend as well. Signed-off-by: Wenyou Yang --- Changes in v2: - Use CONFIG_PM_SLEEP. - Use SIMPLE_DEV_PM_OPS macro. drivers/iio/adc/at91_adc.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index bbdac07..34b928c 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Registers */ #define AT91_ADC_CR0x00/* Control Register */ @@ -1347,6 +1348,32 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int at91_adc_suspend(struct device *dev) +{ + struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(idev); + + pinctrl_pm_select_sleep_state(dev); + clk_disable_unprepare(st->clk); + + return 0; +} + +static int at91_adc_resume(struct device *dev) +{ + struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(idev); + + clk_prepare_enable(st->clk); + pinctrl_pm_select_default_state(dev); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume); + static struct at91_adc_caps at91sam9260_caps = { .calc_startup_ticks = calc_startup_ticks_9260, .num_channels = 4, @@ -1441,6 +1468,7 @@ static struct platform_driver at91_adc_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(at91_adc_dt_ids), + .pm = &at91_adc_pm_ops, }, }; -- 2.7.4
[PATCH v2] ARM: at91/dt: add dts file for sama5d36ek CMP board
The sama5d36ek CMP board is the variant of sama5d3xek board. It is equipped with the low-power DDR2 SDRAM, PMIC ACT8865 and some power rail. Its main purpose is used to measure the power consumption. The difference of the sama5d36ek CMP dts from sama5d36ek dts is listed as below. 1. The USB host nodes are removed, that is, the USB host is disabled. 2. The gpio_keys node is added to wake up from the sleep. 3. The LCD isn't supported due to the pins for LCD are conflicted with gpio_keys. 4. The adc0 node support the pinctrl sleep state to fix the over consumption on VDDANA. As said in errata, "When the USB host ports are used in high speed mode (EHCI), it is not possible to suspend the ports if no device is attached on each port. This leads to increased power consumption even if the system is in a low power mode." That is why the the USB host is disabled. Signed-off-by: Wenyou Yang --- Changes in v2: - Add the pinctrl sleep state for adc0 node to fix the over consumption on VDDANA. - Improve the commit log. arch/arm/boot/dts/sama5d36ek_cmp.dts | 51 +++ arch/arm/boot/dts/sama5d3xcm_cmp.dtsi | 166 + arch/arm/boot/dts/sama5d3xmb_cmp.dtsi | 265 ++ 3 files changed, 482 insertions(+) create mode 100644 arch/arm/boot/dts/sama5d36ek_cmp.dts create mode 100644 arch/arm/boot/dts/sama5d3xcm_cmp.dtsi create mode 100644 arch/arm/boot/dts/sama5d3xmb_cmp.dtsi diff --git a/arch/arm/boot/dts/sama5d36ek_cmp.dts b/arch/arm/boot/dts/sama5d36ek_cmp.dts new file mode 100644 index 000..fd6bcd6 --- /dev/null +++ b/arch/arm/boot/dts/sama5d36ek_cmp.dts @@ -0,0 +1,51 @@ +/* + * sama5d36ek_cmp.dts - Device Tree file for SAMA5D36-EK CMP board + * + * Copyright (C) 2016 Atmel, + * + * Licensed under GPLv2 or later. + */ +/dts-v1/; +#include "sama5d36.dtsi" +#include "sama5d3xmb_cmp.dtsi" + +/ { + model = "Atmel SAMA5D36-EK"; + compatible = "atmel,sama5d36ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d36", "atmel,sama5d3", "atmel,sama5"; + + ahb { + apb { + spi0: spi@f0004000 { + status = "okay"; + }; + + ssc0: ssc@f0008000 { + status = "okay"; + }; + + can0: can@f000c000 { + status = "okay"; + }; + + i2c0: i2c@f0014000 { + status = "okay"; + }; + + i2c1: i2c@f0018000 { + status = "okay"; + }; + + macb0: ethernet@f0028000 { + status = "okay"; + }; + + macb1: ethernet@f802c000 { + status = "okay"; + }; + }; + }; + + sound { + status = "okay"; + }; +}; diff --git a/arch/arm/boot/dts/sama5d3xcm_cmp.dtsi b/arch/arm/boot/dts/sama5d3xcm_cmp.dtsi new file mode 100644 index 000..77638c3 --- /dev/null +++ b/arch/arm/boot/dts/sama5d3xcm_cmp.dtsi @@ -0,0 +1,166 @@ +/* + * sama5d3xcm_cmp.dtsi - Device Tree Include file for SAMA5D36 CMP CPU Module + * + * Copyright (C) 2016 Atmel, + * + * Licensed under GPLv2 or later. + */ + +/ { + compatible = "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5"; + + chosen { + bootargs = "rootfstype=ubifs ubi.mtd=5 root=ubi0:rootfs"; + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0x2000 0x2000>; + }; + + clocks { + slow_xtal { + clock-frequency = <32768>; + }; + + main_xtal { + clock-frequency = <1200>; + }; + }; + + ahb { + apb { + spi0: spi@f0004000 { + cs-gpios = <&pioD 13 0>, <0>, <0>, <0>; + }; + + macb0: ethernet@f0028000 { + phy-mode = "rgmii"; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@1 { + reg = <0x1>; + interrupt-parent = <&pioB>; + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + txen
[PATCH v1] iio: adc: at91: add suspend and resume callback
Add suspend/resume callback, support the pinctrl sleep state when the system suspend as well. Signed-off-by: Wenyou Yang --- drivers/iio/adc/at91_adc.c | 35 +++ 1 file changed, 35 insertions(+) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index bbdac07..ffa81a1 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Registers */ #define AT91_ADC_CR0x00/* Control Register */ @@ -1347,6 +1348,39 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int at91_adc_suspend(struct device *dev) +{ + struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(idev); + + pinctrl_pm_select_sleep_state(dev); + clk_disable_unprepare(st->clk); + + return 0; +} + +static int at91_adc_resume(struct device *dev) +{ + struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(idev); + + clk_prepare_enable(st->clk); + pinctrl_pm_select_default_state(dev); + + return 0; +} + +static const struct dev_pm_ops at91_adc_pm_ops = { + .suspend = at91_adc_suspend, + .resume = at91_adc_resume, +}; + +#define AT91_ADC_PM_OPS (&at91_adc_pm_ops) +#else +#define AT91_ADC_PM_OPS NULL +#endif + static struct at91_adc_caps at91sam9260_caps = { .calc_startup_ticks = calc_startup_ticks_9260, .num_channels = 4, @@ -1441,6 +1475,7 @@ static struct platform_driver at91_adc_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(at91_adc_dt_ids), + .pm = AT91_ADC_PM_OPS, }, }; -- 2.7.4