From ebdaf5ec6d7040c1c7c9a3486ea16ea60f5f127f Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 29 Apr 2020 01:31:03 +0300 Subject: [PATCH] media: i2c: max9296: add MIPI GMSL2 support This adds MIPI stream from serializer Signed-off-by: Vladimir Barinov Signed-off-by: Andrey Gusakov --- drivers/media/i2c/soc_camera/gmsl/max9296.c | 75 +++++++++++++++++------------ drivers/media/i2c/soc_camera/gmsl/max9296.h | 6 +-- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/drivers/media/i2c/soc_camera/gmsl/max9296.c b/drivers/media/i2c/soc_camera/gmsl/max9296.c index a6d286f..85b45ca 100644 --- a/drivers/media/i2c/soc_camera/gmsl/max9296.c +++ b/drivers/media/i2c/soc_camera/gmsl/max9296.c @@ -94,7 +94,7 @@ static int gmsl = MODE_GMSL2; module_param(gmsl, int, 0644); MODULE_PARM_DESC(gmsl, " GMSL mode (default: 2 - GMSL2)"); -static char *mbus = "dvp"; +static char *mbus = mbus_default; module_param(mbus, charp, 0644); MODULE_PARM_DESC(mbus, " Interfaces mipi,dvp (default: dvp)"); @@ -165,7 +165,7 @@ static void max9296_reset_oneshot(struct max9296_priv *priv) if (!(reg & BIT(5))) break; - msleep(1); + mdelay(1); } if (reg & BIT(5)) @@ -745,9 +745,12 @@ static int max9296_gmsl2_reverse_channel_setup(struct max9296_priv *priv, int li des_update_bits(MAX9296_CTRL0, 0x13, BIT(link_n)); /* enable GMSL link# */ max9296_reset_oneshot(priv); - /* wait 100ms for link to be established, indicated when status bit LOCKED goes high */ - while ((!max9296_gmsl2_get_link_lock(priv, link_n)) && (--timeout)) - msleep(1); + /* wait the link to be established, indicated when status bit LOCKED goes high */ + for (; timeout > 0; timeout--) { + if (max9296_gmsl2_get_link_lock(priv, link_n)) + break; + mdelay(1); + } if (!timeout) { ret = -ETIMEDOUT; @@ -785,36 +788,42 @@ static int max9296_gmsl2_link_serializer_setup(struct max9296_priv *priv, int li struct max9296_link *link = priv->link[link_n]; int i; - //ser_write(MAX9295_CTRL0, 0x31); /* link reset */ - //msleep(100); - ser_write(MAX9295_REG2, 0x03); /* disable all pipes */ - if (strcmp(priv->mbus, "dvp") == 0) { - ser_write(MAX9295_VIDEO_TX0(0), BIT(6) | /* line CRC enable */ + ser_write(MAX9295_VIDEO_TX0(0), BIT(6) | /* line CRC enable */ (priv->hven ? BIT(5) : 0)); /* HS/VS encoding */ ser_write(MAX9295_VIDEO_TX1(0), 0x0a); /* BPP = 10 */ ser_write(MAX9295_REG7, 0x07); /* DVP stream, enable HS/VS, rising edge */ - } - - ser_write(MAX9295_REG2, 0x13); /* enable Pipe X */ - switch (priv->dt) { - case MIPI_DT_YUV8: - case MIPI_DT_RAW12: - /* setup crossbar: strait DVP mapping */ - ser_write(MAX9295_CROSS(0), priv->cb[0]); - ser_write(MAX9295_CROSS(1), priv->cb[1]); - ser_write(MAX9295_CROSS(2), priv->cb[2]); - ser_write(MAX9295_CROSS(3), priv->cb[3]); - ser_write(MAX9295_CROSS(4), priv->cb[4]); - ser_write(MAX9295_CROSS(5), priv->cb[5]); - ser_write(MAX9295_CROSS(6), priv->cb[6]); - ser_write(MAX9295_CROSS(7), priv->cb[7]); - ser_write(MAX9295_CROSS(8), priv->cb[8]); - ser_write(MAX9295_CROSS(9), priv->cb[9]); - ser_write(MAX9295_CROSS(10), priv->cb[10]); - ser_write(MAX9295_CROSS(11), priv->cb[11]); - break; + switch (priv->dt) { + case MIPI_DT_YUV8: + case MIPI_DT_RAW12: + /* setup crossbar: strait DVP mapping */ + ser_write(MAX9295_CROSS(0), priv->cb[0]); + ser_write(MAX9295_CROSS(1), priv->cb[1]); + ser_write(MAX9295_CROSS(2), priv->cb[2]); + ser_write(MAX9295_CROSS(3), priv->cb[3]); + ser_write(MAX9295_CROSS(4), priv->cb[4]); + ser_write(MAX9295_CROSS(5), priv->cb[5]); + ser_write(MAX9295_CROSS(6), priv->cb[6]); + ser_write(MAX9295_CROSS(7), priv->cb[7]); + ser_write(MAX9295_CROSS(8), priv->cb[8]); + ser_write(MAX9295_CROSS(9), priv->cb[9]); + ser_write(MAX9295_CROSS(10), priv->cb[10]); + ser_write(MAX9295_CROSS(11), priv->cb[11]); + break; + } + } else { + /* defaults: + * REG2 - video enable Pipex X,Z + * MIPI_RX0 - 1x4 mode (1-port x 4-lanes) + * MIPI_RX1 - 4-lanes + * MIPI_RX2, MIPI_RX3 - merge PHY1,PHY2 to 1x4-mode + * FRONTTOP_9 - start Pipes X,Z from CSI_A,CSI_B + */ + + ser_write(MAX9295_FRONTTOP_0, 0x71); /* enable Pipe X from from CSI_A,CSI_B */ + ser_write(MAX9295_FRONTTOP_12, BIT(6) | priv->dt); /* primary DT for Pipe X */ + ser_write(MAX9295_FRONTTOP_13, BIT(6) | MIPI_DT_EMB); /* secondary DT for Pipe X */ } for (i = 0; i < 11; i++) { @@ -856,7 +865,9 @@ static struct { } gmsl2_pipe_maps[] = { {0x00, 0x00}, /* FS */ {0x01, 0x01}, /* FE */ - {MIPI_DT_YUV8, MIPI_DT_YUV8} /* payload data */ + {MIPI_DT_YUV8, MIPI_DT_YUV8}, /* payload data */ + {MIPI_DT_RAW8, MIPI_DT_RAW8}, + {MIPI_DT_RAW12, MIPI_DT_RAW12}, }; static void max9296_gmsl2_pipe_set_source(struct max9296_priv *priv, int pipe, int phy, int in_pipe) @@ -1193,6 +1204,8 @@ static int max9296_parse_dt(struct i2c_client *client) priv->gpio[7] = gpio7; if (gpio8 >= 0) priv->gpio[8] = gpio8; + if (strcmp(mbus, "dvp")) + priv->mbus = mbus; /* parse serializer crossbar setup */ for (i = 0; i < 16; i++) { diff --git a/drivers/media/i2c/soc_camera/gmsl/max9296.h b/drivers/media/i2c/soc_camera/gmsl/max9296.h index 800df43..985b77e 100644 --- a/drivers/media/i2c/soc_camera/gmsl/max9296.h +++ b/drivers/media/i2c/soc_camera/gmsl/max9296.h @@ -254,11 +254,11 @@ static inline int max9296_ser_write(struct max9296_link *link, int reg, int val) return ret; } -static inline int max9296_ser_read(struct max9296_link *link, int reg, u8 *val) +static inline int max9296_ser_read(struct max9296_link *link, int reg, int *val) { int ret; - ret = regmap_read(link->regmap, reg, (int *)val); + ret = regmap_read(link->regmap, reg, val); if (ret) dev_dbg(&link->client->dev, "read register 0x%04x failed (%d)\n", reg, ret); @@ -276,6 +276,6 @@ static inline int max9296_ser_update_bits(struct max9296_link *link, int reg, in return ret; } -#define ser_read(reg, val) max9296_ser_read(link, reg, val) +#define ser_read(reg, val) max9296_ser_read(link, reg, (int *)val) #define ser_write(reg, val) max9296_ser_write(link, reg, val) #define ser_update_bits(reg, mask, bits) max9296_ser_update_bits(link, reg, mask, bits) -- 2.7.4