1
0
Fork 0

MLK-18098: camera: add MIPI and PARALLEL CSI support in one dtb

1. Divide ov5640_v3.c into two parts, one for parallel csi driver
   and the other for mipi csi driver

2. Add parallel and mipi support in one dtb file. User can select
   one of them without changing the dtb file

Reviewed-by: Sandor.yu <sandor.yu@nxp.com>
Signed-off-by: Guoniu.Zhou <guoniu.zhou@nxp.com>
pull/10/head
Guoniu.Zhou 2018-04-20 16:23:09 +08:00 committed by Jason Liu
parent b5e639aafc
commit adf7b3a4b9
9 changed files with 1629 additions and 179 deletions

View File

@ -46,6 +46,7 @@ dtb-$(CONFIG_ARCH_FSL_IMX8QXP) += fsl-imx8qxp-lpddr4-arm2.dtb \
fsl-imx8qxp-mek-dom0.dtb \
fsl-imx8qxp-mek-csi.dtb \
fsl-imx8qxp-mek-mipi-ov5640.dtb \
fsl-imx8qxp-mek-ov5640.dtb \
fsl-imx8qxp-mek-enet2.dtb \
fsl-imx8qxp-mek-enet2-tja1100.dtb \
fsl-imx8qxp-mek-dsi-rm67191.dtb \

View File

@ -48,7 +48,7 @@
status = "okay";
ov5640_mipi: ov5640_mipi@3c {
compatible = "ovti,ov5640_v3";
compatible = "ovti,ov5640_mipi_v3";
reg = <0x3c>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mipi_csi0>;

View File

@ -0,0 +1,160 @@
#include "fsl-imx8qxp-mek.dts"
#include "fsl-imx8qxp-mek-lvds0-it6263.dtsi"
&iomuxc {
imx8qxp-mek {
pinctrl_mipi_csi0: mipicsi0grp{
fsl,pins = <
SC_P_MIPI_CSI0_MCLK_OUT_MIPI_CSI0_ACM_MCLK_OUT 0xC0000041
SC_P_MIPI_CSI0_GPIO0_01_LSIO_GPIO3_IO07 0xC0000041
SC_P_MIPI_CSI0_GPIO0_00_LSIO_GPIO3_IO08 0xC0000041
>;
};
pinctrl_parallel_csi: parallelcsigrp {
fsl,pins = <
SC_P_CSI_D00_CI_PI_D02 0xC0000041
SC_P_CSI_D01_CI_PI_D03 0xC0000041
SC_P_CSI_D02_CI_PI_D04 0xC0000041
SC_P_CSI_D03_CI_PI_D05 0xC0000041
SC_P_CSI_D04_CI_PI_D06 0xC0000041
SC_P_CSI_D05_CI_PI_D07 0xC0000041
SC_P_CSI_D06_CI_PI_D08 0xC0000041
SC_P_CSI_D07_CI_PI_D09 0xC0000041
SC_P_CSI_MCLK_CI_PI_MCLK 0xC0000041
SC_P_CSI_PCLK_CI_PI_PCLK 0xC0000041
SC_P_CSI_HSYNC_CI_PI_HSYNC 0xC0000041
SC_P_CSI_VSYNC_CI_PI_VSYNC 0xC0000041
SC_P_CSI_EN_LSIO_GPIO3_IO02 0xC0000041
SC_P_CSI_RESET_LSIO_GPIO3_IO03 0xC0000041
>;
};
};
};
&isi_0 {
interface = <6 0 2>; /* INPUT: 6-PARALLEL CSI */
parallel_csi;
status = "okay";
};
&i2c0_cm40 {
ov5640: ov5640@3c {
compatible = "ovti,ov5640_v3";
reg = <0x3c>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_parallel_csi>;
clocks = <&clk IMX8QXP_PARALLEL_CSI_MISC0_CLK>;
clock-names = "csi_mclk";
pwn-gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
rst-gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
csi_id = <0>;
mclk = <24000000>;
mclk_source = <0>;
status = "okay";
port {
ov5640_ep: endpoint {
remote-endpoint = <&parallel_csi_ep>;
};
};
};
};
&cameradev {
parallel_csi;
status = "okay";
};
&parallel_csi {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
port@0 {
reg = <0>;
parallel_csi_ep: endpoint {
remote-endpoint = <&ov5640_ep>;
};
};
};
&isi_1 {
interface = <2 0 2>;
status = "okay";
};
&isi_2 {
status = "disabled";
};
&isi_3 {
status = "disabled";
};
&isi_4 {
status = "disabled";
};
&isi_5 {
status = "disabled";
};
&isi_6 {
status = "disabled";
};
&isi_7 {
status = "disabled";
};
&i2c0_csi0 {
clock-frequency = <100000>;
status = "okay";
ov5640_mipi: ov5640_mipi@3c {
compatible = "ovti,ov5640_mipi_v3";
reg = <0x3c>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mipi_csi0>;
clocks = <&clk IMX8QXP_CLK_DUMMY>;
clock-names = "csi_mclk";
csi_id = <0>;
pwn-gpios = <&gpio3 7 GPIO_ACTIVE_LOW>;
rst-gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
mclk = <24000000>;
mclk_source = <0>;
mipi_csi;
status = "okay";
port {
ov5640_mipi_ep: endpoint {
remote-endpoint = <&mipi_csi0_ep>;
};
};
};
max9286_mipi@6A {
status = "disabled";
};
};
&mipi_csi_0 {
/delete-property/virtual-channel;
status = "okay";
port@0 {
reg = <0>;
mipi_csi0_ep: endpoint {
remote-endpoint = <&ov5640_mipi_ep>;
data-lanes = <1 2>;
};
};
};
&jpegdec {
status = "disabled";
};
&jpegenc {
status = "disabled";
};

View File

@ -30,6 +30,11 @@ config MXC_CAMERA_OV5640_V3
depends on I2C
default y
config MXC_CAMERA_OV5640_MIPI_V3
tristate "Maxim OV5640_MIPI_V3 driver support"
depends on I2C
default y
config GMSL_MAX9286
tristate "Maxim max9286 GMSL Deserializer Input support"
select SENSOR_OV10635

View File

@ -6,6 +6,7 @@ obj-$(CONFIG_IMX8_PARALLEL_CSI) += mxc-parallel-csi.o
obj-$(CONFIG_IMX8_MIPI_CSI2_YAV) += mxc-mipi-csi2_yav.o
ov5640_camera_v3-objs := ov5640_v3.o
obj-$(CONFIG_MXC_CAMERA_OV5640_V3) += ov5640_camera_v3.o
obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI_V3) += ov5640_mipi_v3.o
max9286_gmsl-objs := max9286.o
obj-$(CONFIG_GMSL_MAX9286) += max9286_gmsl.o
obj-$(CONFIG_IMX8_MEDIA_DEVICE) += mxc-media-dev.o

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 NXP
* Copyright 2017-2018 NXP
*/
/*
* The code contained herein is licensed under the GNU General Public
@ -199,7 +199,7 @@ static int mxc_md_create_links(struct mxc_md *mxc_md)
if (sensor == NULL || sensor->sd == NULL)
continue;
if (mxc_md->parallel_csi) {
if (mxc_md->parallel_csi && !sensor->mipi_mode) {
pcsidev = mxc_md->pcsidev;
if (pcsidev == NULL)
continue;
@ -345,11 +345,12 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
struct device_node *port;
if (of_node_cmp(node->name, "csi") &&
of_node_cmp(node->name, "pcsi")) {
of_node_cmp(node->name, "pcsi"))
continue;
}
if (!of_device_is_available(node))
continue;
/* csi2 node have only port */
port = of_get_next_child(node, NULL);
if (!port)
@ -368,6 +369,9 @@ static int register_sensor_entities(struct mxc_md *mxc_md)
mxc_md->sensor[index].id = endpoint.base.port;
if (!of_node_cmp(node->name, "csi"))
mxc_md->sensor[index].mipi_mode = true;
/* remote port---sensor node */
rem = of_graph_get_remote_port_parent(ep);
of_node_put(ep);

View File

@ -72,7 +72,8 @@ struct mxc_sensor_info {
int id;
struct v4l2_subdev *sd;
struct v4l2_async_subdev asd;
// struct mxc_isi_dev *host;
bool mipi_mode;
/* struct mxc_isi_dev *host; */
};
struct mxc_mjpeg_dec{

File diff suppressed because it is too large Load Diff

View File

@ -110,7 +110,6 @@ struct ov5640 {
struct v4l2_captureparm streamcap;
struct media_pad pads[OV5640_SENS_PADS_NUM];
bool on;
bool mipi_csi;
/* control settings */
int brightness;
@ -451,52 +450,6 @@ static struct reg_value ov5640_pll_1080P_15fps_1920_1080[] = {
{0x3824, 0x04, 0, 0}, {0x4837, 0x16, 0, 0},
};
/* MIPI */
static struct reg_value ov5640_mipi_pll_VGA_30fps_640_480[] = {
{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x4837, 0x0a, 0, 0},
};
static struct reg_value ov5640_mipi_pll_VGA_15fps_640_480[] = {
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x4837, 0x0a, 0, 0},
};
static struct reg_value ov5640_mipi_pll_QVGA_30fps_320_240[] = {
{0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x4837, 0x22, 0, 0},
};
static struct reg_value ov5640_mipi_pll_QVGA_15fps_320_240[] = {
{0x3035, 0x22, 0, 0}, {0x3036, 0x38, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x4837, 0x0a, 0, 0},
};
static struct reg_value ov5640_mipi_pll_30fps_480_272[] = {
{0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x460c, 0x20, 0, 0},
{0x3824, 0x04, 0, 0}, {0x4837, 0x16, 0, 0},
};
static struct reg_value ov5640_mipi_pll_15fps_480_272[] = {
{0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x460c, 0x20, 0, 0},
{0x3824, 0x04, 0, 0}, {0x4837, 0x16, 0, 0},
};
static struct reg_value ov5640_mipi_pll_720P_30fps_1280_720[] = {
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x460c, 0x20, 0, 0},
{0x3824, 0x04, 0, 0}, {0x4837, 0x0a, 0, 0},
};
static struct reg_value ov5640_mipi_pll_720P_15fps_1280_720[] = {
{0x3035, 0x41, 0, 0}, {0x3036, 0x54, 0, 0}, {0x460c, 0x20, 0, 0},
{0x3824, 0x04, 0, 0}, {0x4837, 0x0a, 0, 0},
};
static struct reg_value ov5640_mipi_pll_1080P_15fps_1920_1080[] = {
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x460c, 0x20, 0, 0},
{0x3824, 0x04, 0, 0}, {0x4837, 0x0a, 0, 0},
};
static struct reg_value ov5640_config[] = {
{0x302C, 0xc2, 0, 0}, /* Driver Capability */
@ -514,36 +467,6 @@ static struct reg_value ov5640_config[] = {
{0x5000, 0xa7, 0, 0},
};
static struct reg_value ov5640_mipi_config[] = {
{0x302C, 0xc2, 0, 0}, /* Driver Capability */
{0x4300, 0x3F, 0, 0}, /* YUV422 YVYU */
{0x501f, 0x00, 0, 0}, /* YUV422 YVYU */
{0x3034, 0x18, 0, 0}, /* MIPI 8bits mode */
{0x3017, 0x00, 0, 0},
{0x3018, 0x00, 0, 0},
{0x300e, 0x45, 0, 0}, /* MIPI mode */
{0x4800, 0x04, 0, 0},
{0x4740, 0x23, 0, 0}, /* BIT5: Pixel BIT1: HSYNC BIT0: VSYNC
1: hight level
0: low level valid*/
{0x5000, 0xa7, 0, 0},
};
static struct ov5640_hs_info hs_setting[] = {
{1920, 1080, 30, 0x0B},
{1920, 1080, 15, 0x10},
{1280, 720, 30, 0x11},
{1280, 720, 15, 0x16},
{640, 480, 30, 0x1E},
{640, 480, 15, 0x23},
{320, 240, 30, 0x1E},
{320, 240, 15, 0x23},
};
static struct ov5640_mode_info ov5640_mode_info_data[ov5640_mode_MAX + 1] = {
{ov5640_mode_VGA_640_480, 640, 480, ov5640_setting_VGA_640_480,
ARRAY_SIZE(ov5640_setting_VGA_640_480)},
@ -594,39 +517,6 @@ static struct ov5640_pll_info ov5640_pll_info_data[2][ov5640_mode_MAX + 1] = {
},
};
static struct ov5640_pll_info ov5640_mipi_pll_info_data[2][ov5640_mode_MAX + 1] = {
{
{ov5640_mode_VGA_640_480, ov5640_mipi_pll_VGA_15fps_640_480,
ARRAY_SIZE(ov5640_mipi_pll_VGA_15fps_640_480)},
{ov5640_mode_QVGA_320_240, ov5640_mipi_pll_QVGA_15fps_320_240,
ARRAY_SIZE(ov5640_mipi_pll_QVGA_15fps_320_240)},
{ov5640_mode_480_272, ov5640_mipi_pll_15fps_480_272,
ARRAY_SIZE(ov5640_mipi_pll_15fps_480_272)},
{ov5640_mode_720P_1280_720, ov5640_mipi_pll_720P_15fps_1280_720,
ARRAY_SIZE(ov5640_mipi_pll_720P_15fps_1280_720)},
{ov5640_mode_1080P_1920_1080, ov5640_mipi_pll_1080P_15fps_1920_1080,
ARRAY_SIZE(ov5640_mipi_pll_1080P_15fps_1920_1080)},
},
{
{ov5640_mode_VGA_640_480, ov5640_mipi_pll_VGA_30fps_640_480,
ARRAY_SIZE(ov5640_mipi_pll_VGA_30fps_640_480)},
{ov5640_mode_QVGA_320_240, ov5640_mipi_pll_QVGA_30fps_320_240,
ARRAY_SIZE(ov5640_mipi_pll_QVGA_30fps_320_240)},
{ov5640_mode_480_272, ov5640_mipi_pll_30fps_480_272,
ARRAY_SIZE(ov5640_mipi_pll_30fps_480_272)},
{ov5640_mode_720P_1280_720, ov5640_mipi_pll_720P_30fps_1280_720,
ARRAY_SIZE(ov5640_mipi_pll_720P_30fps_1280_720)},
},
};
static struct regulator *io_regulator;
static struct regulator *core_regulator;
static struct regulator *analog_regulator;
@ -665,27 +555,6 @@ static struct ov5640 *to_ov5640(const struct i2c_client *client)
return container_of(i2c_get_clientdata(client), struct ov5640, subdev);
}
static uint16_t find_hs_configure(struct ov5640 *sensor)
{
struct device *dev = &sensor->i2c_client->dev;
struct v4l2_fract *timeperframe = &sensor->streamcap.timeperframe;
struct v4l2_pix_format *pix = &sensor->pix;
u32 frame_rate = timeperframe->denominator / timeperframe->numerator;
int i;
for (i = 0; i < ARRAY_SIZE(hs_setting); i++) {
if (hs_setting[i].width == pix->width &&
hs_setting[i].height == pix->height &&
hs_setting[i].frame_rate == frame_rate)
return hs_setting[i].val;
}
if (i == ARRAY_SIZE(hs_setting))
dev_err(dev, "%s can not find hs configure\n", __func__);
return -EINVAL;
}
/* Find a data format by a pixel code in an array */
static const struct ov5640_datafmt
*ov5640_find_datafmt(u32 code)
@ -915,11 +784,6 @@ static int ov5640_config_resolution(enum ov5640_mode mode)
ov5640_write_reg(0x3821, 0x06);
}
if (ov5640_data.mipi_csi && mode == ov5640_mode_480_272) {
mode = ov5640_mode_VGA_640_480;
pr_warn("Not support 480*272, change to 640*480\n");
}
/* Configure ov5640 initial parm */
pModeSetting = ov5640_mode_info_data[mode].init_data_ptr;
ArySize = ov5640_mode_info_data[mode].init_data_size;
@ -940,28 +804,15 @@ static int ov5640_config_others(enum ov5640_frame_rate rate,
if (mode < ov5640_mode_MIN || mode > ov5640_mode_MAX)
return -EINVAL;
if (ov5640_data.mipi_csi) {
mode = (mode == ov5640_mode_480_272) ?
ov5640_mode_VGA_640_480 : mode;
pModeSetting = ov5640_mipi_pll_info_data[rate][mode].init_data_ptr;
ArySize = ov5640_mipi_pll_info_data[rate][mode].init_data_size;
} else {
pModeSetting = ov5640_pll_info_data[rate][mode].init_data_ptr;
ArySize = ov5640_pll_info_data[rate][mode].init_data_size;
}
pModeSetting = ov5640_pll_info_data[rate][mode].init_data_ptr;
ArySize = ov5640_pll_info_data[rate][mode].init_data_size;
retval = ov5640_download_firmware(pModeSetting, ArySize);
if (retval < 0)
return retval;
/* Configure ov5640 initial parm */
if (ov5640_data.mipi_csi) {
pModeSetting = ov5640_mipi_config;
ArySize = ARRAY_SIZE(ov5640_mipi_config);
} else {
pModeSetting = ov5640_config;
ArySize = ARRAY_SIZE(ov5640_config);
}
pModeSetting = ov5640_config;
ArySize = ARRAY_SIZE(ov5640_config);
retval = ov5640_download_firmware(pModeSetting, ArySize);
if (retval < 0)
return retval;
@ -1217,13 +1068,8 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
return -EINVAL;
if (!fmt) {
if (sensor->mipi_csi) {
mf->code = ov5640_colour_fmts[1].code;
mf->colorspace = ov5640_colour_fmts[1].colorspace;
} else {
mf->code = ov5640_colour_fmts[0].code;
mf->colorspace = ov5640_colour_fmts[0].colorspace;
}
mf->code = ov5640_colour_fmts[0].code;
mf->colorspace = ov5640_colour_fmts[0].colorspace;
}
mf->field = V4L2_FIELD_NONE;
@ -1250,17 +1096,12 @@ static int ov5640_get_fmt(struct v4l2_subdev *sd,
memset(mf, 0, sizeof(struct v4l2_mbus_framefmt));
if (sensor->mipi_csi) {
mf->code = ov5640_colour_fmts[1].code;
mf->colorspace = ov5640_colour_fmts[1].colorspace;
} else {
mf->code = ov5640_colour_fmts[0].code;
mf->colorspace = ov5640_colour_fmts[0].colorspace;
}
mf->code = ov5640_colour_fmts[0].code;
mf->colorspace = ov5640_colour_fmts[0].colorspace;
mf->width = sensor->pix.width;
mf->height = sensor->pix.height;
mf->field = V4L2_FIELD_NONE;
mf->reserved[1] = (sensor->mipi_csi) ? find_hs_configure(sensor) : 0;
mf->reserved[1] = 0;
dev_dbg(&client->dev, "%s code=0x%x, w/h=(%d,%d), colorspace=%d, field=%d\n",
__func__, mf->code, mf->width, mf->height, mf->colorspace, mf->field);
@ -1419,7 +1260,7 @@ static int ov5640_probe(struct i2c_client *client,
rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
if (!gpio_is_valid(rst_gpio)) {
dev_err(dev, "no sensor reset pin available\n");
devm_gpio_free(dev, pwn_gpio);
devm_gpio_free(dev, rst_gpio);
return -EINVAL;
}
retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_LOW,
@ -1460,8 +1301,6 @@ static int ov5640_probe(struct i2c_client *client,
return retval;
}
ov5640_data.mipi_csi = of_property_read_bool(dev->of_node, "mipi_csi");
/* Set mclk rate before clk on */
ov5640_set_clk_rate();
@ -1474,8 +1313,7 @@ static int ov5640_probe(struct i2c_client *client,
ov5640_data.io_init = ov5640_reset;
ov5640_data.i2c_client = client;
ov5640_data.pix.pixelformat = (ov5640_data.mipi_csi) ?
V4L2_PIX_FMT_UYVY : V4L2_PIX_FMT_YVYU;
ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YVYU;
ov5640_data.pix.width = ov5640_mode_info_data[0].width;
ov5640_data.pix.height = ov5640_mode_info_data[0].height;
ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |