diff --git a/drivers/media/i2c/imx477.c b/drivers/media/i2c/imx477.c index fb2c409ddf84f2..7acdb6fa01308c 100644 --- a/drivers/media/i2c/imx477.c +++ b/drivers/media/i2c/imx477.c @@ -112,6 +112,9 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink"); #define IMX477_REG_XVS_IO_CTRL 0x3040 #define IMX477_REG_EXTOUT_EN 0x4b81 +/* Temperature sensor */ +#define IMX477_REG_TEMP_SEN_CTL 0x0138 + /* Embedded metadata stream structure */ #define IMX477_EMBEDDED_LINE_WIDTH 16384 #define IMX477_NUM_EMBEDDED_LINES 1 @@ -1833,6 +1836,9 @@ static int imx477_start_streaming(struct imx477 *imx477) /* Set vsync trigger mode: 0=standalone, 1=source, 2=sink */ tm = (imx477->trigger_mode_of >= 0) ? imx477->trigger_mode_of : trigger_mode; + if (tm == 1) + imx477_write_reg(imx477, IMX477_REG_TEMP_SEN_CTL, + IMX477_REG_VALUE_08BIT, 0); imx477_write_reg(imx477, IMX477_REG_MC_MODE, IMX477_REG_VALUE_08BIT, (tm > 0) ? 1 : 0); imx477_write_reg(imx477, IMX477_REG_MS_SEL, @@ -1843,8 +1849,15 @@ static int imx477_start_streaming(struct imx477 *imx477) IMX477_REG_VALUE_08BIT, (tm == 1) ? 1 : 0); /* set stream on register */ - return imx477_write_reg(imx477, IMX477_REG_MODE_SELECT, - IMX477_REG_VALUE_08BIT, IMX477_MODE_STREAMING); + ret = imx477_write_reg(imx477, IMX477_REG_MODE_SELECT, + IMX477_REG_VALUE_08BIT, IMX477_MODE_STREAMING); + + /* now it's safe to re-enable temp sensor without glitching XVS */ + if (tm == 1) + imx477_write_reg(imx477, IMX477_REG_TEMP_SEN_CTL, + IMX477_REG_VALUE_08BIT, 1); + + return ret; } /* Stop streaming */ diff --git a/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c index 28ea3215fff5c1..7eec3e77109eeb 100644 --- a/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c +++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c @@ -149,6 +149,7 @@ static void dphy_init(struct dphy_data *dphy) void dphy_start(struct dphy_data *dphy) { + dw_csi2_host_write(dphy, RESETN, 0); dw_csi2_host_write(dphy, N_LANES, (dphy->active_lanes - 1)); dphy_init(dphy); dw_csi2_host_write(dphy, RESETN, 0xffffffff); @@ -157,9 +158,18 @@ void dphy_start(struct dphy_data *dphy) void dphy_stop(struct dphy_data *dphy) { - /* Set only one lane (lane 0) as active (ON) */ - dw_csi2_host_write(dphy, N_LANES, 0); - dw_csi2_host_write(dphy, RESETN, 0); + /* + * We no longer go into reset here, because the camera might still be + * streaming. If we kill the CSI-2 Host in mid-packet, it can leave the + * IDI interface in a bad state, causing the next packet to be lost. + * + * XXX Is it safe to assume it will be idle before the next dphy_start? + * XXX What happens if the camera itself generates an incomplete packet? + * + * TODO: Instead, should we consider resetting the *entire* MIPI block + * (including CSI2AXI and ISP-FE)? That can't safely be done until + * all AXI traffic has completed. It would cause APB access to hang. + */ } void dphy_probe(struct dphy_data *dphy)