media: i2c: max96712: version 1.03.00

Signed-off-by: Cai Wenzhong <cwz@rock-chips.com>
Change-Id: I3faa1465a4db3edd7337cad2afbdc16f0495f905
This commit is contained in:
Cai Wenzhong
2023-05-31 14:28:18 +08:00
committed by Tao Huang
parent 2196ad1ae9
commit 25030c287c

View File

@@ -11,6 +11,8 @@
* support modes enable select.
* auto initial deskew enable configure.
* frame sync period enable configure.
* V1.3.00 t_lpx timing adjust from 53.4ns to 106.7ns.
* mipi dpll predef rate set api.
*
*/
@@ -38,13 +40,13 @@
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#define DRIVER_VERSION KERNEL_VERSION(1, 0x02, 0x00)
#define DRIVER_VERSION KERNEL_VERSION(1, 0x03, 0x00)
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
#endif
#define MAX96712_LINK_FREQ_1000MHZ 1000000000UL
#define MAX96712_LINK_FREQ_MHZ(x) ((x) * 1000000UL)
#define MAX96712_XVCLK_FREQ 25000000
#define MAX96712_CHIP_ID 0xA0
@@ -242,16 +244,7 @@ static const struct regval max96712_mipi_4lane_1920x1440_30fps[] = {
{ 0x29, 0x090A, 0xc0, 0x00 }, // MIPI PHY 0: 4 lanes, DPHY, 2bit VC
{ 0x29, 0x094A, 0xc0, 0x00 }, // MIPI PHY 1: 4 lanes, DPHY, 2bit VC
// Turn on MIPI PHYs
{ 0x29, 0x08A2, 0x30, 0x00 }, // Enable MIPI PHY 0/1
// Hold DPLL in reset (config_soft_rst_n = 0) before changing the rate
{ 0x29, 0x1C00, 0xf4, 0x00 },
{ 0x29, 0x1D00, 0xf4, 0x00 },
// Set Data rate to be 2000Mbps/lane for port A and enable software override
{ 0x29, 0x0415, 0x34, 0x00 }, // Enable freq fine tuning, 2000Mbps
{ 0x29, 0x0418, 0x34, 0x00 }, // Enable freq fine tuning, 2000Mbps
// Release reset to DPLL (config_soft_rst_n = 1)
{ 0x29, 0x1C00, 0xf5, 0x00 },
{ 0x29, 0x1D00, 0xf5, 0x00 },
{ 0x29, 0x08A2, 0x34, 0x00 }, // Enable MIPI PHY 0/1, t_lpx = 106.7ns
// YUV422 8bit software override for all pipes since connected GMSL1 is under parallel mode
{ 0x29, 0x040B, 0x80, 0x00 }, // pipe 0 bpp=0x10: Datatypes = 0x22, 0x1E, 0x2E
{ 0x29, 0x040E, 0x5e, 0x00 }, // pipe 0 DT=0x1E: YUV422 8-bit
@@ -278,7 +271,7 @@ static const struct max96712_mode supported_modes_4lane[] = {
.denominator = 300000,
},
.reg_list = max96712_mipi_4lane_1920x1440_30fps,
.link_freq_idx = 0,
.link_freq_idx = 10,
.bus_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
.bpp = 16,
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
@@ -288,8 +281,34 @@ static const struct max96712_mode supported_modes_4lane[] = {
},
};
/* link freq = index * MAX96712_LINK_FREQ_MHZ(50) */
static const s64 link_freq_items[] = {
MAX96712_LINK_FREQ_1000MHZ,
MAX96712_LINK_FREQ_MHZ(0),
MAX96712_LINK_FREQ_MHZ(50),
MAX96712_LINK_FREQ_MHZ(100),
MAX96712_LINK_FREQ_MHZ(150),
MAX96712_LINK_FREQ_MHZ(200),
MAX96712_LINK_FREQ_MHZ(250),
MAX96712_LINK_FREQ_MHZ(300),
MAX96712_LINK_FREQ_MHZ(350),
MAX96712_LINK_FREQ_MHZ(400),
MAX96712_LINK_FREQ_MHZ(450),
MAX96712_LINK_FREQ_MHZ(500),
MAX96712_LINK_FREQ_MHZ(550),
MAX96712_LINK_FREQ_MHZ(600),
MAX96712_LINK_FREQ_MHZ(650),
MAX96712_LINK_FREQ_MHZ(700),
MAX96712_LINK_FREQ_MHZ(750),
MAX96712_LINK_FREQ_MHZ(800),
MAX96712_LINK_FREQ_MHZ(850),
MAX96712_LINK_FREQ_MHZ(900),
MAX96712_LINK_FREQ_MHZ(950),
MAX96712_LINK_FREQ_MHZ(1000),
MAX96712_LINK_FREQ_MHZ(1050),
MAX96712_LINK_FREQ_MHZ(1100),
MAX96712_LINK_FREQ_MHZ(1150),
MAX96712_LINK_FREQ_MHZ(1200),
MAX96712_LINK_FREQ_MHZ(1250),
};
/* Write registers up to 4 at a time */
@@ -589,6 +608,108 @@ static irqreturn_t max96712_hot_plug_detect_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __maybe_unused max96712_dphy_dpll_predef_set(struct i2c_client *client,
u32 link_freq_mhz)
{
int ret = 0;
u8 dpll_val = 0, dpll_lock = 0;
u8 mipi_tx_phy_enable = 0;
ret = max96712_read_reg(client, MAX96712_I2C_ADDR,
0x08A2, MAX96712_REG_VALUE_08BIT, &mipi_tx_phy_enable);
if (ret)
return ret;
mipi_tx_phy_enable = (mipi_tx_phy_enable & 0xF0) >> 4;
dev_info(&client->dev, "DPLL predef set: mipi_tx_phy_enable = 0x%02x, link_freq_mhz = %d\n",
mipi_tx_phy_enable, link_freq_mhz);
// dphy max data rate is 2500MHz
if (link_freq_mhz > (2500 >> 1))
link_freq_mhz = (2500 >> 1);
dpll_val = DIV_ROUND_UP(link_freq_mhz * 2, 100) & 0x1F;
// Disable software override for frequency fine tuning
dpll_val |= BIT(5);
// MIPI PHY0
if (mipi_tx_phy_enable & BIT(0)) {
// Hold DPLL in reset (config_soft_rst_n = 0) before changing the rate
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1C00,
MAX96712_REG_VALUE_08BIT,
0xf4);
// Set data rate and enable software override
ret |= max96712_update_reg_bits(client, MAX96712_I2C_ADDR,
0x0415, 0x3F, dpll_val);
// Release reset to DPLL (config_soft_rst_n = 1)
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1C00,
MAX96712_REG_VALUE_08BIT,
0xf5);
}
// MIPI PHY1
if (mipi_tx_phy_enable & BIT(1)) {
// Hold DPLL in reset (config_soft_rst_n = 0) before changing the rate
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1D00,
MAX96712_REG_VALUE_08BIT,
0xf4);
// Set data rate and enable software override
ret |= max96712_update_reg_bits(client, MAX96712_I2C_ADDR,
0x0418, 0x3F, dpll_val);
// Release reset to DPLL (config_soft_rst_n = 1)
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1D00,
MAX96712_REG_VALUE_08BIT,
0xf5);
}
// MIPI PHY2
if (mipi_tx_phy_enable & BIT(2)) {
// Hold DPLL in reset (config_soft_rst_n = 0) before changing the rate
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1E00,
MAX96712_REG_VALUE_08BIT,
0xf4);
// Set data rate and enable software override
ret |= max96712_update_reg_bits(client, MAX96712_I2C_ADDR,
0x041B, 0x3F, dpll_val);
// Release reset to DPLL (config_soft_rst_n = 1)
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1E00,
MAX96712_REG_VALUE_08BIT,
0xf5);
}
// MIPI PHY3
if (mipi_tx_phy_enable & BIT(3)) {
// Hold DPLL in reset (config_soft_rst_n = 0) before changing the rate
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1F00,
MAX96712_REG_VALUE_08BIT,
0xf4);
// Set data rate and enable software override
ret |= max96712_update_reg_bits(client, MAX96712_I2C_ADDR,
0x041E, 0x3F, dpll_val);
// Release reset to DPLL (config_soft_rst_n = 1)
ret |= max96712_write_reg(client, MAX96712_I2C_ADDR,
0x1F00,
MAX96712_REG_VALUE_08BIT,
0xf5);
}
ret |= max96712_read_reg(client, MAX96712_I2C_ADDR,
0x0400, MAX96712_REG_VALUE_08BIT, &dpll_lock);
if (ret)
return ret;
dev_info(&client->dev, "DPLL predef set: dpll_lock = 0x%02x\n", dpll_lock);
return ret;
}
static int max96712_auto_init_deskew(struct i2c_client *client, u32 deskew_mask)
{
int ret = 0;
@@ -1070,6 +1191,7 @@ static long max96712_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
static int __max96712_start_stream(struct max96712 *max96712)
{
int ret;
u32 link_freq_mhz, link_freq_idx;
ret = max96712_check_link_lock_state(max96712);
if (ret)
@@ -1090,6 +1212,12 @@ static int __max96712_start_stream(struct max96712 *max96712)
return ret;
}
link_freq_idx = max96712->cur_mode->link_freq_idx;
link_freq_mhz = (u32)div_s64(link_freq_items[link_freq_idx], 1000000L);
ret = max96712_dphy_dpll_predef_set(max96712->client, link_freq_mhz);
if (ret)
return ret;
if (max96712->frame_sync_period != 0) {
ret = max96712_frame_sync_period(max96712->client,
max96712->frame_sync_period);
@@ -1201,10 +1329,10 @@ static int __max96712_power_on(struct max96712 *max96712)
u32 delay_us;
struct device *dev = &max96712->client->dev;
if (!IS_ERR(max96712->power_gpio))
if (!IS_ERR(max96712->power_gpio)) {
gpiod_set_value_cansleep(max96712->power_gpio, 1);
usleep_range(1000, 2000);
usleep_range(5000, 10000);
}
if (!IS_ERR_OR_NULL(max96712->pins_default)) {
ret = pinctrl_select_state(max96712->pinctrl,
@@ -1221,10 +1349,11 @@ static int __max96712_power_on(struct max96712 *max96712)
dev_err(dev, "Failed to enable regulators\n");
goto disable_clk;
}
if (!IS_ERR(max96712->reset_gpio))
if (!IS_ERR(max96712->reset_gpio)) {
gpiod_set_value_cansleep(max96712->reset_gpio, 1);
usleep_range(500, 1000);
}
usleep_range(500, 1000);
if (!IS_ERR(max96712->pwdn_gpio))
gpiod_set_value_cansleep(max96712->pwdn_gpio, 1);
@@ -1258,10 +1387,11 @@ static void __max96712_power_off(struct max96712 *max96712)
if (ret < 0)
dev_dbg(dev, "could not set pins\n");
}
if (!IS_ERR(max96712->power_gpio))
gpiod_set_value_cansleep(max96712->power_gpio, 0);
regulator_bulk_disable(MAX96712_NUM_SUPPLIES, max96712->supplies);
if (!IS_ERR(max96712->power_gpio))
gpiod_set_value_cansleep(max96712->power_gpio, 0);
}
static int max96712_runtime_resume(struct device *dev)
@@ -1332,7 +1462,7 @@ static int max96712_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
u8 data_lanes = max96712->bus_cfg.bus.mipi_csi2.num_data_lanes;
val |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
val |= 1 << (data_lanes - 1);
val |= (1 << (data_lanes - 1));
switch (data_lanes) {
case 4:
val |= V4L2_MBUS_CSI2_CHANNEL_3;