diff --git a/drivers/media/i2c/maxim4c/Kconfig b/drivers/media/i2c/maxim4c/Kconfig index 40e6a22e8c96..667ce82c11cf 100644 --- a/drivers/media/i2c/maxim4c/Kconfig +++ b/drivers/media/i2c/maxim4c/Kconfig @@ -3,42 +3,44 @@ # Maxim Quad GMSL deserializer and serializer devices # config VIDEO_DES_MAXIM4C - tristate "Maxim Qual GMSL deserializer support" + tristate "Maxim Quad GMSL deserializer support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE help - This driver supports the Maxim Qual GMSL2/GMSL1 deserializer. + This driver supports the Maxim Quad GMSL2/GMSL1 deserializer. To compile this driver as a module, choose M here: the module will be called maxim4c. +menu "Maxim Quad GMSL serializer devices support" + visible if VIDEO_DES_MAXIM4C + config MAXIM4C_SER_MAX9295 - tristate "Maxim GMSL serializer support" - depends on I2C - select VIDEO_DES_MAXIM4C + tristate "Maxim GMSL2 serializer max9295 support" + depends on VIDEO_DES_MAXIM4C help - This driver supports the Maxim GMSL2 serializer. + This driver supports the Maxim GMSL2 max9295 serializer. To compile this driver as a module, choose M here: the module will be called remote_max9295. config MAXIM4C_SER_MAX96715 - tristate "Maxim GMSL serializer support" - depends on I2C - select VIDEO_DES_MAXIM4C + tristate "Maxim GMSL1 Serializer max96715 support" + depends on VIDEO_DES_MAXIM4C help - This driver supports the Maxim GMSL1 serializer. + This driver supports the Maxim GMSL1 max96715 serializer. To compile this driver as a module, choose M here: the module will be called remote_max96715. config MAXIM4C_SER_MAX96717 - tristate "Maxim GMSL serializer support" - depends on I2C - select VIDEO_DES_MAXIM4C + tristate "Maxim GMSL2 Serializer max96717 support" + depends on VIDEO_DES_MAXIM4C help - This driver supports the Maxim GMSL2 serializer. + This driver supports the Maxim GMSL2 max96717 serializer. To compile this driver as a module, choose M here: the module will be called remote_max96717. + +endmenu diff --git a/drivers/media/i2c/maxim4c/maxim4c_api.h b/drivers/media/i2c/maxim4c/maxim4c_api.h index 45cba9a0f6a1..6dd3bbca17d7 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_api.h +++ b/drivers/media/i2c/maxim4c/maxim4c_api.h @@ -23,6 +23,9 @@ /* Maxim Deserializer Test Pattern */ #define MAXIM4C_TEST_PATTERN 0 +/* Maxim Deserializer pwdn on/off enable */ +#define MAXIM4C_LOCAL_DES_ON_OFF_EN 0 + /* maxim4c i2c api */ int maxim4c_i2c_write_reg(struct i2c_client *client, u16 reg_addr, u16 reg_len, u16 val_len, u32 reg_val); @@ -77,15 +80,22 @@ int maxim4c_remote_mfd_add_devices(maxim4c_t *maxim4c); int maxim4c_remote_devices_init(maxim4c_t *maxim4c, u8 link_init_mask); int maxim4c_remote_devices_deinit(maxim4c_t *maxim4c, u8 link_init_mask); int maxim4c_remote_load_init_seq(maxim4c_remote_t *remote_device); +int maxim4c_remote_i2c_addr_select(maxim4c_remote_t *remote_device, u32 i2c_id); +int maxim4c_remote_i2c_client_init(maxim4c_remote_t *remote_device, + struct i2c_client *des_client); int maxim4c_remote_device_register(maxim4c_t *maxim4c, - maxim4c_remote_t *remote_device); + maxim4c_remote_t *remote_device); /* maxim4c v4l2 subdev api */ int maxim4c_v4l2_subdev_init(maxim4c_t *maxim4c); void maxim4c_v4l2_subdev_deinit(maxim4c_t *maxim4c); +int maxim4c_module_hw_init(maxim4c_t *maxim4c); + /* maxim4c pattern api */ -int maxim4c_pattern_init(maxim4c_t *maxim4c); +int maxim4c_pattern_hw_init(maxim4c_t *maxim4c); +int maxim4c_pattern_support_mode_init(maxim4c_t *maxim4c); +int maxim4c_pattern_data_init(maxim4c_t *maxim4c); int maxim4c_pattern_enable(maxim4c_t *maxim4c, bool enable); #endif /* __MAXIM4C_API_H__ */ diff --git a/drivers/media/i2c/maxim4c/maxim4c_drv.c b/drivers/media/i2c/maxim4c/maxim4c_drv.c index 68d721f6cd99..88924dce5926 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_drv.c +++ b/drivers/media/i2c/maxim4c/maxim4c_drv.c @@ -6,7 +6,7 @@ * * Author: Cai Wenzhong * - * V2.0.00 maxim serdes qual GMSL2/GMSL1 driver framework. + * V2.00.00 maxim serdes quad GMSL2/GMSL1 driver framework. * 1. local deserializer support: max96712/max96722 * 2. remote serializer support: max9295/max96715/max96717 * 3. support deserializer and serializer auto adaptive @@ -14,6 +14,14 @@ * 5. support remote serializer I2c address mapping * 6. support remote serializer hot plug detection and recovery * + * V2.01.00 + * 1. remote device and local link are bound through link id + * 2. support local and remote port chain check + * 3. drivers/media/i2c/maxim4c/Kconfig support menu select + * 4. optimize delay time and error messages + * 5. power control: local by pwdn gpio, remote by pocen gpio + * 6. local pwdn on/off enable depend on MAXIM4C_LOCAL_DES_ON_OFF_EN + * */ #include #include @@ -43,14 +51,10 @@ #include "maxim4c_api.h" -#define DRIVER_VERSION KERNEL_VERSION(2, 0x00, 0x00) +#define DRIVER_VERSION KERNEL_VERSION(2, 0x01, 0x00) #define MAXIM4C_XVCLK_FREQ 25000000 -/* device compatible */ -#define MAXIM4C_MAX96712_COMPAT "maxim4c,max96712" -#define MAXIM4C_MAX96722_COMPAT "maxim4c,max96722" - static int maxim4c_check_local_chipid(maxim4c_t *maxim4c) { struct i2c_client *client = maxim4c->client; @@ -59,6 +63,11 @@ static int maxim4c_check_local_chipid(maxim4c_t *maxim4c) u8 chipid = 0; for (loop = 0; loop < 5; loop++) { + if (loop != 0) { + dev_info(dev, "check local chipid retry (%d)", loop); + msleep(10); + } + ret = maxim4c_i2c_read_byte(client, MAXIM4C_REG_CHIP_ID, MAXIM4C_I2C_REG_ADDR_16BITS, &chipid); @@ -74,13 +83,10 @@ static int maxim4c_check_local_chipid(maxim4c_t *maxim4c) return 0; } } else { - dev_err(dev, "Unexpected maxim chipid(%02x)\n", chipid); + dev_err(dev, "Unexpected maxim chipid = %02x\n", chipid); return -ENODEV; } } - - dev_info(dev, "retry (%d) to check local chipid", loop + 1); - msleep(10); } dev_err(dev, "maxim check chipid error, ret(%d)\n", ret); @@ -181,13 +187,13 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work) link_id = MAXIM4C_LINK_ID_A; if (curr_lock_state & MAXIM4C_LINK_MASK_A) { - dev_info(dev, "link A plug in\n"); + dev_info(dev, "Link A plug in\n"); maxim4c_remote_devices_init(maxim4c, MAXIM4C_LINK_MASK_A); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, true); } else { - dev_info(dev, "link A plug out\n"); + dev_info(dev, "Link A plug out\n"); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, false); } @@ -197,13 +203,13 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work) link_id = MAXIM4C_LINK_ID_B; if (curr_lock_state & MAXIM4C_LINK_MASK_B) { - dev_info(dev, "link B plug in\n"); + dev_info(dev, "Link B plug in\n"); maxim4c_remote_devices_init(maxim4c, MAXIM4C_LINK_MASK_B); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, true); } else { - dev_info(dev, "link B plug out\n"); + dev_info(dev, "Link B plug out\n"); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, false); } @@ -213,13 +219,13 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work) link_id = MAXIM4C_LINK_ID_C; if (curr_lock_state & MAXIM4C_LINK_MASK_C) { - dev_info(dev, "link C plug in\n"); + dev_info(dev, "Link C plug in\n"); maxim4c_remote_devices_init(maxim4c, MAXIM4C_LINK_MASK_C); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, true); } else { - dev_info(dev, "link C plug out\n"); + dev_info(dev, "Link C plug out\n"); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, false); } @@ -229,13 +235,13 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work) link_id = MAXIM4C_LINK_ID_D; if (curr_lock_state & MAXIM4C_LINK_MASK_D) { - dev_info(dev, "link D plug in\n"); + dev_info(dev, "Link D plug in\n"); maxim4c_remote_devices_init(maxim4c, MAXIM4C_LINK_MASK_D); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, true); } else { - dev_info(dev, "link D plug out\n"); + dev_info(dev, "Link D plug out\n"); maxim4c_video_pipe_linkid_enable(maxim4c, link_id, false); } @@ -290,10 +296,10 @@ static int maxim4c_local_device_power_on(maxim4c_t *maxim4c) { struct device *dev = &maxim4c->client->dev; - if (!IS_ERR(maxim4c->power_gpio)) { - dev_info(dev, "local device power gpio on\n"); + if (!IS_ERR(maxim4c->pwdn_gpio)) { + dev_info(dev, "local device pwdn gpio on\n"); - gpiod_set_value_cansleep(maxim4c->power_gpio, 1); + gpiod_set_value_cansleep(maxim4c->pwdn_gpio, 1); usleep_range(5000, 10000); } @@ -305,10 +311,10 @@ static void maxim4c_local_device_power_off(maxim4c_t *maxim4c) { struct device *dev = &maxim4c->client->dev; - if (!IS_ERR(maxim4c->power_gpio)) { - dev_info(dev, "local device power gpio off\n"); + if (!IS_ERR(maxim4c->pwdn_gpio)) { + dev_info(dev, "local device pwdn gpio off\n"); - gpiod_set_value_cansleep(maxim4c->power_gpio, 0); + gpiod_set_value_cansleep(maxim4c->pwdn_gpio, 0); } } @@ -318,7 +324,7 @@ static int maxim4c_remote_device_power_on(maxim4c_t *maxim4c) // remote PoC enable if (!IS_ERR(maxim4c->pocen_gpio)) { - dev_info(dev, "remote device poc gpio on\n"); + dev_info(dev, "remote device pocen gpio on\n"); gpiod_set_value_cansleep(maxim4c->pocen_gpio, 1); usleep_range(5000, 10000); @@ -333,7 +339,7 @@ static int maxim4c_remote_device_power_off(maxim4c_t *maxim4c) // remote PoC enable if (!IS_ERR(maxim4c->pocen_gpio)) { - dev_info(dev, "remote device poc gpio off\n"); + dev_info(dev, "remote device pocen gpio off\n"); gpiod_set_value_cansleep(maxim4c->pocen_gpio, 0); } @@ -346,8 +352,15 @@ static int maxim4c_runtime_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct maxim4c *maxim4c = v4l2_get_subdevdata(sd); + int ret = 0; - return maxim4c_remote_device_power_on(maxim4c); +#if MAXIM4C_LOCAL_DES_ON_OFF_EN + ret |= maxim4c_local_device_power_on(maxim4c); +#endif /* MAXIM4C_LOCAL_DES_ON_OFF_EN */ + + ret |= maxim4c_remote_device_power_on(maxim4c); + + return ret; } static int maxim4c_runtime_suspend(struct device *dev) @@ -355,8 +368,15 @@ static int maxim4c_runtime_suspend(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct maxim4c *maxim4c = v4l2_get_subdevdata(sd); + int ret = 0; - return maxim4c_remote_device_power_off(maxim4c); + ret |= maxim4c_remote_device_power_off(maxim4c); + +#if MAXIM4C_LOCAL_DES_ON_OFF_EN + maxim4c_local_device_power_off(maxim4c); +#endif /* MAXIM4C_LOCAL_DES_ON_OFF_EN */ + + return ret; } static const struct dev_pm_ops maxim4c_pm_ops = { @@ -378,22 +398,26 @@ static int maxim4c_extra_init_seq_parse(maxim4c_t *maxim4c, struct device_node * struct maxim4c_i2c_init_seq *init_seq = NULL; init_seq_node = of_get_child_by_name(node, "extra-init-sequence"); - if (!IS_ERR_OR_NULL(init_seq_node)) { - if (!of_device_is_available(init_seq_node)) { - dev_info(dev, "%pOF is disabled\n", init_seq_node); + if (IS_ERR_OR_NULL(init_seq_node)) { + dev_dbg(dev, "%pOF no child node extra-init-sequence\n", node); + return 0; + } - return 0; - } - - dev_info(dev, "load extra-init-sequence\n"); - - init_seq = &maxim4c->extra_init_seq; - maxim4c_i2c_load_init_seq(dev, - init_seq_node, init_seq); + if (!of_device_is_available(init_seq_node)) { + dev_dbg(dev, "%pOF is disabled\n", init_seq_node); of_node_put(init_seq_node); + return 0; } + dev_info(dev, "load extra-init-sequence\n"); + + init_seq = &maxim4c->extra_init_seq; + maxim4c_i2c_load_init_seq(dev, + init_seq_node, init_seq); + + of_node_put(init_seq_node); + return 0; } @@ -404,8 +428,12 @@ static int maxim4c_module_parse_dt(maxim4c_t *maxim4c) // maxim serdes local node = of_get_child_by_name(dev->of_node, "serdes-local-device"); - if (IS_ERR_OR_NULL(node)) + if (IS_ERR_OR_NULL(node)) { + dev_err(dev, "%pOF has no child node: serdes-local-device\n", + dev->of_node); + return -ENODEV; + } if (!of_device_is_available(node)) { dev_info(dev, "%pOF is disabled\n", node); @@ -492,36 +520,51 @@ static int maxim4c_module_hw_postinit(maxim4c_t *maxim4c) return ret; } -static int maxim4c_module_hw_init(maxim4c_t *maxim4c) +int maxim4c_module_hw_init(maxim4c_t *maxim4c) { + struct device *dev = &maxim4c->client->dev; int ret = 0; ret = maxim4c_module_hw_previnit(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: hw prev init error\n", __func__); + return ret; + } ret = maxim4c_link_hw_init(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: hw link init error\n", __func__); return ret; + } ret = maxim4c_video_pipe_hw_init(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: hw pipe init error\n", __func__); return ret; + } ret = maxim4c_mipi_txphy_hw_init(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: hw txphy init error\n", __func__); return ret; + } ret = maxim4c_run_extra_init_seq(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: run extra init seq error\n", __func__); return ret; + } ret = maxim4c_module_hw_postinit(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: hw post init error\n", __func__); return ret; + } return 0; } +EXPORT_SYMBOL(maxim4c_module_hw_init); static int maxim4c_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -529,32 +572,30 @@ static int maxim4c_probe(struct i2c_client *client, struct device *dev = &client->dev; struct device_node *node = dev->of_node; maxim4c_t *maxim4c = NULL; - const u32 *chip_id = NULL; + u32 chip_id; int ret = 0; dev_info(dev, "driver version: %02x.%02x.%02x", DRIVER_VERSION >> 16, (DRIVER_VERSION & 0xff00) >> 8, DRIVER_VERSION & 0x00ff); - chip_id = of_device_get_match_data(dev); - if (chip_id == NULL) { - dev_err(dev, "maxim4c driver get match data error\n"); - return -EINVAL; - } - - if (*chip_id == MAX96712_CHIP_ID) { - dev_info(dev, "maxim4c driver for max96712"); - } else if (*chip_id == MAX96722_CHIP_ID) { - dev_info(dev, "maxim4c driver for max96722"); + chip_id = (uintptr_t)of_device_get_match_data(dev); + if (chip_id == MAX96712_CHIP_ID) { + dev_info(dev, "maxim4c driver for max96712\n"); + } else if (chip_id == MAX96722_CHIP_ID) { + dev_info(dev, "maxim4c driver for max96722\n"); } else { - dev_err(dev, "maxim4c driver unknown chip"); + dev_err(dev, "maxim4c driver unknown chip\n"); return -EINVAL; } maxim4c = devm_kzalloc(dev, sizeof(*maxim4c), GFP_KERNEL); - if (!maxim4c) + if (!maxim4c) { + dev_err(dev, "maxim4c probe no memory error\n"); return -ENOMEM; + } + maxim4c->client = client; - maxim4c->chipid = *chip_id; + maxim4c->chipid = chip_id; ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, &maxim4c->module_index); @@ -569,9 +610,9 @@ static int maxim4c_probe(struct i2c_client *client, return -EINVAL; } - maxim4c->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); - if (IS_ERR(maxim4c->power_gpio)) - dev_warn(dev, "Failed to get power-gpios, maybe no use\n"); + maxim4c->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); + if (IS_ERR(maxim4c->pwdn_gpio)) + dev_warn(dev, "Failed to get pwdn-gpios, maybe no use\n"); maxim4c->pocen_gpio = devm_gpiod_get(dev, "pocen", GPIOD_OUT_LOW); if (IS_ERR(maxim4c->pocen_gpio)) @@ -594,13 +635,21 @@ static int maxim4c_probe(struct i2c_client *client, // client->dev->driver_data = subdev // subdev->dev->driver_data = maxim4c ret = maxim4c_v4l2_subdev_init(maxim4c); + if (ret) { + dev_err(dev, "maxim4c probe v4l2 subdev init error\n"); + goto err_power_off; + } + +#if MAXIM4C_TEST_PATTERN + ret = maxim4c_pattern_data_init(maxim4c); if (ret) goto err_power_off; -#if MAXIM4C_TEST_PATTERN - ret = maxim4c_pattern_init(maxim4c); +#if (MAXIM4C_LOCAL_DES_ON_OFF_EN == 0) + ret = maxim4c_pattern_hw_init(maxim4c); if (ret) goto err_power_off; +#endif /* MAXIM4C_LOCAL_DES_ON_OFF_EN */ pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -612,9 +661,11 @@ static int maxim4c_probe(struct i2c_client *client, maxim4c_module_data_init(maxim4c); maxim4c_module_parse_dt(maxim4c); +#if (MAXIM4C_LOCAL_DES_ON_OFF_EN == 0) ret = maxim4c_module_hw_init(maxim4c); if (ret) goto err_subdev_deinit; +#endif /* MAXIM4C_LOCAL_DES_ON_OFF_EN */ ret = maxim4c_remote_mfd_add_devices(maxim4c); if (ret) @@ -657,28 +708,17 @@ static int maxim4c_remove(struct i2c_client *client) return 0; } -#if IS_ENABLED(CONFIG_OF) -static const u32 max96712_chip_id = MAX96712_CHIP_ID; -static const u32 max96722_chip_id = MAX96722_CHIP_ID; - static const struct of_device_id maxim4c_of_match[] = { { - .compatible = MAXIM4C_MAX96712_COMPAT, - .data = &max96712_chip_id, + .compatible = "maxim4c,max96712", + .data = (const void *)MAX96712_CHIP_ID }, { - .compatible = MAXIM4C_MAX96722_COMPAT, - .data = &max96722_chip_id, + .compatible = "maxim4c,max96722", + .data = (const void *)MAX96722_CHIP_ID }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, maxim4c_of_match); -#endif - -static const struct i2c_device_id maxim4c_match_id[] = { - { MAXIM4C_MAX96712_COMPAT, 0 }, - { MAXIM4C_MAX96722_COMPAT, 0 }, - {}, -}; static struct i2c_driver maxim4c_i2c_driver = { .driver = { @@ -688,11 +728,10 @@ static struct i2c_driver maxim4c_i2c_driver = { }, .probe = &maxim4c_probe, .remove = &maxim4c_remove, - .id_table = maxim4c_match_id, }; module_i2c_driver(maxim4c_i2c_driver); -MODULE_AUTHOR("Cai wenzhong "); -MODULE_DESCRIPTION("Maxim qual gmsl deserializer driver"); +MODULE_AUTHOR("Cai Wenzhong "); +MODULE_DESCRIPTION("Maxim quad gmsl deserializer driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/maxim4c/maxim4c_drv.h b/drivers/media/i2c/maxim4c/maxim4c_drv.h index d5cd4a79e7e4..444f20f5d3e8 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_drv.h +++ b/drivers/media/i2c/maxim4c/maxim4c_drv.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -55,7 +56,7 @@ struct maxim4c_mode { typedef struct maxim4c { struct i2c_client *client; struct clk *xvclk; - struct gpio_desc *power_gpio; + struct gpio_desc *pwdn_gpio; struct gpio_desc *pocen_gpio; struct gpio_desc *lock_gpio; @@ -101,6 +102,7 @@ typedef struct maxim4c { struct maxim4c_i2c_init_seq extra_init_seq; + struct mfd_cell remote_mfd_devs[MAXIM4C_LINK_ID_MAX]; maxim4c_remote_t *remote_device[MAXIM4C_LINK_ID_MAX]; } maxim4c_t; diff --git a/drivers/media/i2c/maxim4c/maxim4c_i2c.c b/drivers/media/i2c/maxim4c/maxim4c_i2c.c index 1a88ef2cece8..77aba745428e 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_i2c.c +++ b/drivers/media/i2c/maxim4c/maxim4c_i2c.c @@ -88,7 +88,7 @@ int maxim4c_i2c_read_reg(struct i2c_client *client, ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret != ARRAY_SIZE(msgs)) { dev_err(&client->dev, - "%s: reading register 0x%x from 0x%x failed\n", + "%s: reading register 0x%04x from 0x%02x failed\n", __func__, reg_addr, client->addr); return -EIO; } diff --git a/drivers/media/i2c/maxim4c/maxim4c_link.c b/drivers/media/i2c/maxim4c/maxim4c_link.c index 5dd31d60653d..688dfe85abee 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_link.c +++ b/drivers/media/i2c/maxim4c/maxim4c_link.c @@ -107,16 +107,16 @@ static int maxim4c_link_run_init_seq(maxim4c_t *maxim4c) maxim4c_gmsl_link_t *gmsl_link = &maxim4c->gmsl_link; struct maxim4c_link_cfg *link_cfg = NULL; struct maxim4c_i2c_init_seq *init_seq = NULL; - int i = 0; + int link_idx = 0; int ret = 0; // link init sequence - for (i = 0; i < MAXIM4C_LINK_ID_MAX; i++) { - link_cfg = &gmsl_link->link_cfg[i]; + for (link_idx = 0; link_idx < MAXIM4C_LINK_ID_MAX; link_idx++) { + link_cfg = &gmsl_link->link_cfg[link_idx]; init_seq = &link_cfg->link_init_seq; ret = maxim4c_i2c_run_init_seq(client, init_seq); if (ret) { - dev_err(dev, "link id = %d init sequence error\n", i); + dev_err(dev, "link id = %d init sequence error\n", link_idx); return ret; } } @@ -386,6 +386,11 @@ int maxim4c_link_wait_linklock(struct maxim4c *maxim4c, u8 link_mask) msleep(time_ms); for (loop_idx = 0; loop_idx < 20; loop_idx++) { + if (loop_idx != 0) { + msleep(10); + time_ms += 10; + } + for (link_idx = 0; link_idx < MAXIM4C_LINK_ID_MAX; link_idx++) { link_bit_mask = BIT(link_idx); @@ -405,9 +410,6 @@ int maxim4c_link_wait_linklock(struct maxim4c *maxim4c, u8 link_mask) maxim4c->link_lock_state = lock_state; return 0; } - - msleep(10); - time_ms += 10; } if ((lock_state & link_mask) != 0) { @@ -554,9 +556,7 @@ static int maxim4c_gmsl_link_config_parse_dt(struct device *dev, struct device_node *init_seq_node = NULL; struct maxim4c_i2c_init_seq *init_seq = NULL; struct maxim4c_link_cfg *link_cfg = NULL; - struct maxim4c_remote_info *remote_info; const char *link_cfg_name = "gmsl-link-config"; - const char *prop_str = NULL; u32 value = 0; u32 sub_idx = 0, link_id = 0; int ret = 0; @@ -568,7 +568,8 @@ static int maxim4c_gmsl_link_config_parse_dt(struct device *dev, link_cfg_name, strlen(link_cfg_name))) { if (sub_idx >= MAXIM4C_LINK_ID_MAX) { - dev_err(dev, "Too many matching %s node\n", link_cfg_name); + dev_err(dev, "%pOF: Too many matching %s node\n", + parent_node, link_cfg_name); of_node_put(node); break; @@ -622,20 +623,6 @@ static int maxim4c_gmsl_link_config_parse_dt(struct device *dev, link_cfg->link_rx_rate = value; } - /* remote info */ - remote_info = &link_cfg->remote_info; - ret = of_property_read_string(node, "remote-name", &prop_str); - if (ret == 0) { - dev_info(dev, "remote-name property: %s", prop_str); - remote_info->remote_name = prop_str; - } - - ret = of_property_read_string(node, "remote-compatible", &prop_str); - if (ret == 0) { - dev_info(dev, "remote-compatible property: %s", prop_str); - remote_info->remote_compatible = prop_str; - } - /* link init sequence */ init_seq_node = of_get_child_by_name(node, "link-init-sequence"); if (!IS_ERR_OR_NULL(init_seq_node)) { @@ -666,8 +653,11 @@ int maxim4c_link_parse_dt(maxim4c_t *maxim4c, struct device_node *of_node) dev_info(dev, "=== maxim4c link parse dt ===\n"); node = of_get_child_by_name(of_node, "gmsl-links"); - if (IS_ERR_OR_NULL(node)) + if (IS_ERR_OR_NULL(node)) { + dev_err(dev, "%pOF has no child node: gmsl-links\n", + of_node); return -ENODEV; + } if (!of_device_is_available(node)) { dev_info(dev, "%pOF is disabled\n", node); @@ -699,29 +689,42 @@ EXPORT_SYMBOL(maxim4c_link_parse_dt); int maxim4c_link_hw_init(maxim4c_t *maxim4c) { + struct device *dev = &maxim4c->client->dev; maxim4c_gmsl_link_t *gmsl_link = &maxim4c->gmsl_link; int ret = 0; // All links disable at beginning. ret = maxim4c_link_status_init(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: link status error\n", __func__); return ret; + } if (gmsl_link->link_vdd_ldo1_en) ret |= maxim4c_link_enable_vdd_ldo1(maxim4c); if (gmsl_link->link_vdd_ldo2_en) ret |= maxim4c_link_enable_vdd_ldo2(maxim4c); + if (ret) { + dev_err(dev, "%s: link vdd ldo enable error\n", __func__); + return ret; + } // Link Rate Setting - ret |= maxim4c_link_set_rate(maxim4c); - if (ret) + ret = maxim4c_link_set_rate(maxim4c); + if (ret) { + dev_err(dev, "%s: link set rate error\n", __func__); return ret; + } // link init sequence ret = maxim4c_link_run_init_seq(maxim4c); + if (ret) { + dev_err(dev, "%s: link run init seq error\n", __func__); + return ret; + } - return ret; + return 0; } EXPORT_SYMBOL(maxim4c_link_hw_init); @@ -745,8 +748,6 @@ void maxim4c_link_data_init(maxim4c_t *maxim4c) else link_cfg->link_rx_rate = MAXIM4C_LINK_RX_RATE_6GBPS; link_cfg->link_tx_rate = MAXIM4C_LINK_TX_RATE_187_5MPS; - link_cfg->remote_info.remote_name = NULL; - link_cfg->remote_info.remote_compatible = NULL; link_cfg->link_init_seq.reg_init_seq = NULL; } } diff --git a/drivers/media/i2c/maxim4c/maxim4c_link.h b/drivers/media/i2c/maxim4c/maxim4c_link.h index 575cb6e55fb9..f25d4cb9fd04 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_link.h +++ b/drivers/media/i2c/maxim4c/maxim4c_link.h @@ -63,18 +63,12 @@ enum maxim4c_link_tx_rate { MAXIM4C_LINK_TX_RATE_187_5MPS = 0, }; -struct maxim4c_remote_info { - const char *remote_name; - const char *remote_compatible; -}; - struct maxim4c_link_cfg { u8 link_enable; u8 link_type; u8 link_rx_rate; u8 link_tx_rate; - struct maxim4c_remote_info remote_info; struct maxim4c_i2c_init_seq link_init_seq; }; diff --git a/drivers/media/i2c/maxim4c/maxim4c_mipi_txphy.c b/drivers/media/i2c/maxim4c/maxim4c_mipi_txphy.c index f56ded63c186..cdad54f34302 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_mipi_txphy.c +++ b/drivers/media/i2c/maxim4c/maxim4c_mipi_txphy.c @@ -259,7 +259,8 @@ static int maxim4c_mipi_txphy_config_parse_dt(struct device *dev, txphy_cfg_name, strlen(txphy_cfg_name))) { if (sub_idx >= MAXIM4C_TXPHY_ID_MAX) { - dev_err(dev, "Too many matching %s node\n", txphy_cfg_name); + dev_err(dev, "%pOF: Too many matching %s node\n", + parent_node, txphy_cfg_name); of_node_put(node); break; @@ -355,8 +356,11 @@ int maxim4c_mipi_txphy_parse_dt(maxim4c_t *maxim4c, struct device_node *of_node) dev_info(dev, "=== maxim4c mipi txphy parse dt ===\n"); node = of_get_child_by_name(of_node, "mipi-txphys"); - if (IS_ERR_OR_NULL(node)) + if (IS_ERR_OR_NULL(node)) { + dev_err(dev, "%pOF has no child node: mipi-txphys\n", + of_node); return -ENODEV; + } if (!of_device_is_available(node)) { dev_info(dev, "%pOF is disabled\n", node); @@ -404,6 +408,7 @@ EXPORT_SYMBOL(maxim4c_mipi_txphy_parse_dt); int maxim4c_mipi_txphy_hw_init(maxim4c_t *maxim4c) { struct i2c_client *client = maxim4c->client; + struct device *dev = &client->dev; maxim4c_mipi_txphy_t *mipi_txphy = &maxim4c->mipi_txphy; struct maxim4c_txphy_cfg *phy_cfg = NULL; u8 mode = 0; @@ -497,7 +502,12 @@ int maxim4c_mipi_txphy_hw_init(maxim4c_t *maxim4c) // mipi txphy auto init deskew ret |= maxim4c_txphy_auto_init_deskew(maxim4c); - return ret; + if (ret) { + dev_err(dev, "%s: txphy hw init error\n", __func__); + return ret; + } + + return 0; } EXPORT_SYMBOL(maxim4c_mipi_txphy_hw_init); diff --git a/drivers/media/i2c/maxim4c/maxim4c_pattern.c b/drivers/media/i2c/maxim4c/maxim4c_pattern.c index 816f2c6e0fad..09d170e5a85a 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_pattern.c +++ b/drivers/media/i2c/maxim4c/maxim4c_pattern.c @@ -91,6 +91,13 @@ static int maxim4c_pattern_previnit(maxim4c_t *maxim4c) if (ret) return ret; + // video pipe disable. + ret = maxim4c_i2c_write_byte(client, + 0x00F4, MAXIM4C_I2C_REG_ADDR_16BITS, + 0x00); + if (ret) + return ret; + // MIPI CSI output disable. ret = maxim4c_i2c_write_byte(client, 0x040B, MAXIM4C_I2C_REG_ADDR_16BITS, @@ -108,7 +115,7 @@ static int maxim4c_pattern_previnit(maxim4c_t *maxim4c) return 0; } -static int maxim4c_pattern_hw_init(maxim4c_t *maxim4c) +static int maxim4c_pattern_config(maxim4c_t *maxim4c) { const u32 h_active = PATTERN_WIDTH; const u32 h_fp = 88; @@ -249,7 +256,25 @@ static int maxim4c_pattern_hw_init(maxim4c_t *maxim4c) return ret; } -int maxim4c_pattern_init(maxim4c_t *maxim4c) +int maxim4c_pattern_support_mode_init(maxim4c_t *maxim4c) +{ + struct device *dev = &maxim4c->client->dev; + struct maxim4c_mode *supported_mode = NULL; + + dev_info(dev, "=== maxim4c pattern support mode init ===\n"); + + maxim4c->cfg_modes_num = 1; + maxim4c->cur_mode = &maxim4c->supported_mode; + supported_mode = &maxim4c->supported_mode; + + // init using def mode + memcpy(supported_mode, &maxim4c_pattern_mode, sizeof(struct maxim4c_mode)); + + return 0; +} +EXPORT_SYMBOL(maxim4c_pattern_support_mode_init); + +int maxim4c_pattern_data_init(maxim4c_t *maxim4c) { struct device *dev = &maxim4c->client->dev; struct device_node *node = NULL; @@ -259,8 +284,11 @@ int maxim4c_pattern_init(maxim4c_t *maxim4c) // maxim serdes local node = of_get_child_by_name(dev->of_node, "serdes-local-device"); - if (IS_ERR_OR_NULL(node)) + if (IS_ERR_OR_NULL(node)) { + dev_err(dev, "%pOF has no child node: serdes-local-device\n", + dev->of_node); return -ENODEV; + } if (!of_device_is_available(node)) { dev_info(dev, "%pOF is disabled\n", node); @@ -273,23 +301,10 @@ int maxim4c_pattern_init(maxim4c_t *maxim4c) /* mipi txphy parse dt */ ret = maxim4c_mipi_txphy_parse_dt(maxim4c, node); - if (ret) + if (ret) { + dev_err(dev, "%s: txphy parse dt error\n", __func__); return ret; - - ret = maxim4c_pattern_previnit(maxim4c); - if (ret) - return ret; - - ret = maxim4c_mipi_txphy_hw_init(maxim4c); - if (ret) - return ret; - - maxim4c->cfg_modes_num = 1; - maxim4c->cur_mode = &maxim4c->supported_mode; - supported_mode = &maxim4c->supported_mode; - - // init using def mode - memcpy(supported_mode, &maxim4c_pattern_mode, sizeof(struct maxim4c_mode)); + } // pattern generator and mode init pattern = &maxim4c->pattern; @@ -297,6 +312,7 @@ int maxim4c_pattern_init(maxim4c_t *maxim4c) pattern->pattern_mode = PATTERN_CHECKERBOARD; pattern->pattern_pclk = PATTERN_PCLK_75M; + supported_mode = &maxim4c->supported_mode; switch (pattern->pattern_pclk) { case PATTERN_PCLK_25M: supported_mode->max_fps.denominator = 100000; @@ -307,13 +323,13 @@ int maxim4c_pattern_init(maxim4c_t *maxim4c) case PATTERN_PCLK_150M: supported_mode->max_fps.denominator = 600000; if (supported_mode->link_freq_idx < 12) - dev_info(dev, "link_freq_idx = %d is too low\n", + dev_warn(dev, "link_freq_idx = %d is too low\n", supported_mode->link_freq_idx); break; case PATTERN_PCLK_375M: supported_mode->max_fps.denominator = 1500000; if (supported_mode->link_freq_idx < 22) - dev_info(dev, "link_freq_idx = %d is too low\n", + dev_warn(dev, "link_freq_idx = %d is too low\n", supported_mode->link_freq_idx); break; } @@ -321,8 +337,33 @@ int maxim4c_pattern_init(maxim4c_t *maxim4c) dev_info(dev, "video pattern: generator = %d, mode = %d, pclk = %d\n", pattern->pattern_generator, pattern->pattern_mode, pattern->pattern_pclk); - ret = maxim4c_pattern_hw_init(maxim4c); - - return ret; + return 0; } -EXPORT_SYMBOL(maxim4c_pattern_init); +EXPORT_SYMBOL(maxim4c_pattern_data_init); + +int maxim4c_pattern_hw_init(maxim4c_t *maxim4c) +{ + struct device *dev = &maxim4c->client->dev; + int ret = 0; + + ret = maxim4c_pattern_previnit(maxim4c); + if (ret) { + dev_err(dev, "%s: pattern previnit error\n", __func__); + return ret; + } + + ret = maxim4c_mipi_txphy_hw_init(maxim4c); + if (ret) { + dev_err(dev, "%s: txphy hw init error\n", __func__); + return ret; + } + + ret = maxim4c_pattern_config(maxim4c); + if (ret) { + dev_err(dev, "%s: pattern config error\n", __func__); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(maxim4c_pattern_hw_init); diff --git a/drivers/media/i2c/maxim4c/maxim4c_remote.c b/drivers/media/i2c/maxim4c/maxim4c_remote.c index 3f09cdd72898..5835e0b9f4a5 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_remote.c +++ b/drivers/media/i2c/maxim4c/maxim4c_remote.c @@ -8,48 +8,129 @@ * */ #include +#include #include #include "maxim4c_api.h" -static struct mfd_cell maxim4c_remote_devs[MAXIM4C_LINK_ID_MAX]; +static const char *maxim4c_remote_devs_name[MAXIM4C_LINK_ID_MAX] = { + "remote0", "remote1", "remote2", "remote3" +}; + +static const char *maxim4c_remote_link_compat[MAXIM4C_LINK_ID_MAX] = { + "maxim4c,link0", "maxim4c,link1", "maxim4c,link2", "maxim4c,link3" +}; + +static int maxim4c_remote_dev_info_parse(struct device *dev, + struct mfd_cell *remote_mfd_dev, u8 link_id) +{ + struct device_node *node = NULL; + const char *remote_device_name = "serdes-remote-device"; + const char *prop_str = NULL, *link_compat = NULL; + u32 sub_idx = 0, remote_id = 0; + int ret = 0; + + node = NULL; + sub_idx = 0; + while ((node = of_get_next_child(dev->of_node, node))) { + if (!strncasecmp(node->name, + remote_device_name, + strlen(remote_device_name))) { + if (sub_idx >= MAXIM4C_LINK_ID_MAX) { + dev_err(dev, "%pOF: Too many matching %s node\n", + dev->of_node, remote_device_name); + + of_node_put(node); + break; + } + + if (!of_device_is_available(node)) { + dev_info(dev, "%pOF is disabled\n", node); + + sub_idx++; + + continue; + } + + /* remote id */ + ret = of_property_read_u32(node, "remote-id", &remote_id); + if (ret) { + sub_idx++; + + continue; + } + if (remote_id >= MAXIM4C_LINK_ID_MAX) { + sub_idx++; + + continue; + } + + if (remote_id != link_id) { + sub_idx++; + + continue; + } + + dev_info(dev, "remote device id = %d\n", remote_id); + + ret = of_property_read_string(node, "compatible", &prop_str); + if (ret) { + dev_err(dev, "%pOF no compatible error\n", node); + + of_node_put(node); + return -EINVAL; + } + + link_compat = maxim4c_remote_link_compat[remote_id]; + if (!strncasecmp(prop_str, + link_compat, strlen(link_compat))) { + dev_info(dev, "compatible property: %s\n", prop_str); + + remote_mfd_dev->name = maxim4c_remote_devs_name[remote_id]; + remote_mfd_dev->of_compatible = prop_str; + + of_node_put(node); + return 0; + } + + dev_err(dev, "%pOF compatible and remote_id mismatch\n", node); + + of_node_put(node); + return -EINVAL; + } + } + + return -EINVAL; +} static int maxim4c_remote_mfd_devs_init(maxim4c_t *maxim4c) { struct device *dev = &maxim4c->client->dev; maxim4c_gmsl_link_t *gmsl_link = &maxim4c->gmsl_link; - struct maxim4c_link_cfg *link_cfg = NULL; struct mfd_cell *remote_mfd_dev = NULL; - const char *remote_name = NULL, *remote_compatible = NULL; int link_idx = 0, nr_mfd_cell = 0; + int ret = 0; - remote_mfd_dev = maxim4c_remote_devs; + remote_mfd_dev = maxim4c->remote_mfd_devs; nr_mfd_cell = 0; for (link_idx = 0; link_idx < MAXIM4C_LINK_ID_MAX; link_idx++) { - link_cfg = &gmsl_link->link_cfg[link_idx]; - if (link_cfg->link_enable == 0) - continue; + remote_mfd_dev->name = NULL; + remote_mfd_dev->of_compatible = NULL; - remote_name = link_cfg->remote_info.remote_name; - remote_compatible = link_cfg->remote_info.remote_compatible; - if (remote_compatible == NULL) { - dev_err(dev, "%s: link id = %d, remote compatible = NULL", - __func__, link_idx); + if (gmsl_link->link_cfg[link_idx].link_enable == 0) { + dev_dbg(dev, "%s: link id = %d is disabled\n", + __func__, link_idx); continue; } - if (remote_name == NULL) { - dev_err(dev, "%s: link id = %d, remote name = NULL", - __func__, link_idx); - continue; + ret = maxim4c_remote_dev_info_parse(dev, remote_mfd_dev, link_idx); + if (ret == 0) { + remote_mfd_dev++; + nr_mfd_cell++; } - - remote_mfd_dev->name = remote_name; - remote_mfd_dev->of_compatible = remote_compatible; - - remote_mfd_dev++; - nr_mfd_cell++; } + dev_info(dev, "Total number of remote devices is %d", nr_mfd_cell); + return nr_mfd_cell; } @@ -58,19 +139,21 @@ int maxim4c_remote_mfd_add_devices(maxim4c_t *maxim4c) struct device *dev = &maxim4c->client->dev; int nr_mfd_cell = 0, ret = 0; + dev_info(dev, "=== maxim4c add remote devices ==="); + nr_mfd_cell = maxim4c_remote_mfd_devs_init(maxim4c); if (nr_mfd_cell == 0) { dev_err(dev, "%s: remote mfd devices init error\n", - __func__); + __func__); return -EINVAL; } ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, - maxim4c_remote_devs, nr_mfd_cell, + maxim4c->remote_mfd_devs, nr_mfd_cell, NULL, 0, NULL); if (ret) dev_err(dev, "%s: add remote mfd devices error: %d\n", - __func__, ret); + __func__, ret); return ret; } @@ -87,14 +170,14 @@ int maxim4c_remote_devices_init(maxim4c_t *maxim4c, u8 link_init_mask) dev_dbg(dev, "%s: link init mask = 0x%02x\n", __func__, link_init_mask); for (i = 0; i < MAXIM4C_LINK_ID_MAX; i++) { - link_enable = maxim4c->gmsl_link.link_cfg[i].link_enable; - if (link_enable == 0) { - dev_info(dev, "link id = %d is disabled\n", i); + if ((link_init_mask & BIT(i)) == 0) { + dev_dbg(dev, "link id = %d init mask is disabled\n", i); continue; } - if ((link_init_mask & BIT(i)) == 0) { - dev_info(dev, "link id = %d init mask is disabled\n", i); + link_enable = maxim4c->gmsl_link.link_cfg[i].link_enable; + if (link_enable == 0) { + dev_info(dev, "link id = %d is disabled\n", i); continue; } @@ -143,14 +226,14 @@ int maxim4c_remote_devices_deinit(maxim4c_t *maxim4c, u8 link_init_mask) dev_dbg(dev, "%s: link init mask = 0x%02x\n", __func__, link_init_mask); for (i = 0; i < MAXIM4C_LINK_ID_MAX; i++) { - link_enable = maxim4c->gmsl_link.link_cfg[i].link_enable; - if (link_enable == 0) { - dev_info(dev, "link id = %d is disabled\n", i); + if ((link_init_mask & BIT(i)) == 0) { + dev_dbg(dev, "link id = %d init mask is disabled\n", i); continue; } - if ((link_init_mask & BIT(i)) == 0) { - dev_info(dev, "link id = %d init mask is disabled\n", i); + link_enable = maxim4c->gmsl_link.link_cfg[i].link_enable; + if (link_enable == 0) { + dev_info(dev, "link id = %d is disabled\n", i); continue; } @@ -196,54 +279,156 @@ int maxim4c_remote_load_init_seq(maxim4c_remote_t *remote_device) node = of_get_child_by_name(dev->of_node, "remote-init-sequence"); if (!IS_ERR_OR_NULL(node)) { + dev_info(dev, "load remote-init-sequence\n"); + ret = maxim4c_i2c_load_init_seq(dev, node, &remote_device->remote_init_seq); of_node_put(node); - - } else { - ret = 0; - dev_info(dev, "no node remote-init-sequence\n"); + return ret; } - return ret; + return 0; } EXPORT_SYMBOL(maxim4c_remote_load_init_seq); +int maxim4c_remote_i2c_addr_select(maxim4c_remote_t *remote_device, u32 i2c_id) +{ + struct device *dev = remote_device->dev; + struct i2c_client *client = remote_device->client; + + if (i2c_id == MAXIM4C_I2C_SER_DEF) { + client->addr = remote_device->ser_i2c_addr_def; + dev_info(dev, "ser select default i2c addr = 0x%02x\n", client->addr); + } else if (i2c_id == MAXIM4C_I2C_SER_MAP) { + client->addr = remote_device->ser_i2c_addr_map; + dev_info(dev, "ser select mapping i2c addr = 0x%02x\n", client->addr); + } else { + dev_err(dev, "i2c select id = %d error\n", i2c_id); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(maxim4c_remote_i2c_addr_select); + +int maxim4c_remote_i2c_client_init(maxim4c_remote_t *remote_device, + struct i2c_client *des_client) +{ + struct device *dev = remote_device->dev; + struct i2c_client *ser_client = NULL; + u16 ser_client_addr = 0; + + if (remote_device->ser_i2c_addr_map) + ser_client_addr = remote_device->ser_i2c_addr_map; + else + ser_client_addr = remote_device->ser_i2c_addr_def; + ser_client = devm_i2c_new_dummy_device(&des_client->dev, + des_client->adapter, ser_client_addr); + if (IS_ERR(ser_client)) { + dev_err(dev, "failed to alloc i2c client.\n"); + return -PTR_ERR(ser_client); + } + ser_client->addr = remote_device->ser_i2c_addr_def; + + remote_device->client = ser_client; + i2c_set_clientdata(ser_client, remote_device); + + dev_info(dev, "remote i2c client init, i2c_addr = 0x%02x\n", + ser_client_addr); + + return 0; +} +EXPORT_SYMBOL(maxim4c_remote_i2c_client_init); + +static int maxim4c_remote_device_chain_check(maxim4c_remote_t *remote_device) +{ + struct device *dev = NULL; + struct device_node *endpoint = NULL; + struct device_node *link_node = NULL; + u8 remote_id, link_id; + u32 value; + int ret = 0; + + if (remote_device == NULL) { + dev_err(dev, "%s: input parameter is error\n", __func__); + return -EINVAL; + } + + dev = remote_device->dev; + remote_id = remote_device->remote_id; + + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!endpoint) { + dev_err(dev, "%s: no endpoint error\n", __func__); + return -EINVAL; + } + + link_node = of_graph_get_remote_port_parent(endpoint); + if (!link_node) { + dev_err(dev, "%pOF: endpoint has no remote port parent error\n", + endpoint); + return -EINVAL; + } + + ret = of_property_read_u32(link_node, "link-id", &value); + if (ret) { + dev_err(dev, "%pOF: no property link_id error\n", link_node); + + of_node_put(link_node); + return -EINVAL; + } + of_node_put(link_node); + link_id = value; + + if (remote_id != link_id) { + dev_err(dev, "remote_id (%d) != link_id (%d) of %pOF\n", + remote_id, link_id, link_node); + return -EINVAL; + } + + return 0; +} + int maxim4c_remote_device_register(maxim4c_t *maxim4c, maxim4c_remote_t *remote_device) { struct device *dev = NULL; u8 remote_id; + int ret = 0; if ((maxim4c == NULL) || (remote_device == NULL)) { - dev_err(dev, "%s: input parameter is error!\n", - __func__); + dev_err(dev, "%s: input parameter is error!\n", __func__); return -EINVAL; } dev = remote_device->dev; remote_id = remote_device->remote_id; - if (remote_id < MAXIM4C_LINK_ID_MAX) { - if (maxim4c->remote_device[remote_id] == NULL) { - remote_device->remote_enable = 1; - maxim4c->remote_device[remote_id] = remote_device; - dev_dbg(dev, "%s: remote_id = %d is success\n", - __func__, remote_id); - - return 0; - } else { - dev_err(dev, "%s: remote_id = %d is conflict\n", - __func__, remote_id); - - return -EINVAL; - } - } else { + if (remote_id >= MAXIM4C_LINK_ID_MAX) { dev_err(dev, "%s: remote_id = %d is error\n", - __func__, remote_id); + __func__, remote_id); return -EINVAL; } + + if (maxim4c->remote_device[remote_id] != NULL) { + dev_err(dev, "%s: remote_id = %d is conflict\n", + __func__, remote_id); + + return -EINVAL; + } + + ret = maxim4c_remote_device_chain_check(remote_device); + if (ret) { + dev_err(dev, "%s: remote device id = %d chain error\n", + __func__, remote_id); + return -EINVAL; + } + + remote_device->remote_enable = 1; + maxim4c->remote_device[remote_id] = remote_device; + + return 0; } EXPORT_SYMBOL(maxim4c_remote_device_register); diff --git a/drivers/media/i2c/maxim4c/maxim4c_v4l2.c b/drivers/media/i2c/maxim4c/maxim4c_v4l2.c index f8838d6615c2..37df9a622f59 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_v4l2.c +++ b/drivers/media/i2c/maxim4c/maxim4c_v4l2.c @@ -95,6 +95,11 @@ static int maxim4c_support_mode_init(maxim4c_t *maxim4c) dev_info(dev, "=== maxim4c support mode init ===\n"); +#if MAXIM4C_TEST_PATTERN + ret = maxim4c_pattern_support_mode_init(maxim4c); + return ret; +#endif + maxim4c->cfg_modes_num = 1; maxim4c->cur_mode = &maxim4c->supported_mode; mode = &maxim4c->supported_mode; @@ -311,14 +316,12 @@ static long maxim4c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) break; case RKMODULE_SET_CSI_DPHY_PARAM: dphy_param = (struct rkmodule_csi_dphy_param *)arg; - if (dphy_param->vendor == rk3588_dcphy_param.vendor) - rk3588_dcphy_param = *dphy_param; + rk3588_dcphy_param = *dphy_param; dev_dbg(&maxim4c->client->dev, "set dcphy param\n"); break; case RKMODULE_GET_CSI_DPHY_PARAM: dphy_param = (struct rkmodule_csi_dphy_param *)arg; - if (dphy_param->vendor == rk3588_dcphy_param.vendor) - *dphy_param = rk3588_dcphy_param; + *dphy_param = rk3588_dcphy_param; dev_dbg(&maxim4c->client->dev, "get dcphy param\n"); break; default: @@ -430,6 +433,22 @@ static int __maxim4c_start_stream(struct maxim4c *maxim4c) u8 link_mask = 0, link_freq_idx = 0; u8 video_pipe_mask = 0; +#if MAXIM4C_LOCAL_DES_ON_OFF_EN +#if MAXIM4C_TEST_PATTERN + ret = maxim4c_pattern_hw_init(maxim4c); + if (ret) { + dev_err(dev, "test pattern hw init error\n"); + return ret; + } +#else + ret = maxim4c_module_hw_init(maxim4c); + if (ret) { + dev_err(dev, "maxim4c module hw init error\n"); + return ret; + } +#endif /* MAXIM4C_TEST_PATTERN */ +#endif /* MAXIM4C_LOCAL_DES_ON_OFF_EN */ + link_mask = maxim4c->gmsl_link.link_enable_mask; video_pipe_mask = maxim4c->video_pipe.pipe_enable_mask; diff --git a/drivers/media/i2c/maxim4c/maxim4c_video_pipe.c b/drivers/media/i2c/maxim4c/maxim4c_video_pipe.c index 71adca30b13a..e47e778a289a 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_video_pipe.c +++ b/drivers/media/i2c/maxim4c/maxim4c_video_pipe.c @@ -100,8 +100,8 @@ static int maxim4c_video_pipe_config_parse_dt(struct device *dev, pipe_cfg_name, strlen(pipe_cfg_name))) { if (sub_idx >= MAXIM4C_PIPE_O_ID_MAX) { - dev_err(dev, "Too many matching %s node\n", - pipe_cfg_name); + dev_err(dev, "%pOF: Too many matching %s node\n", + parent_node, pipe_cfg_name); of_node_put(node); break; @@ -205,8 +205,11 @@ int maxim4c_video_pipe_parse_dt(maxim4c_t *maxim4c, struct device_node *of_node) dev_info(dev, "=== maxim4c video pipe parse dt ===\n"); node = of_get_child_by_name(of_node, "video-pipes"); - if (IS_ERR_OR_NULL(node)) + if (IS_ERR_OR_NULL(node)) { + dev_err(dev, "%pOF has no child node: video-pipes\n", + of_node); return -ENODEV; + } if (!of_device_is_available(node)) { dev_info(dev, "%pOF is disabled\n", node); @@ -325,21 +328,28 @@ EXPORT_SYMBOL(maxim4c_video_pipe_data_init); int maxim4c_video_pipe_hw_init(maxim4c_t *maxim4c) { + struct device *dev = &maxim4c->client->dev; u8 pipe_enable_mask = 0; int ret = 0; ret = maxim4c_video_pipe_select(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: video pipe select error\n", __func__); return ret; + } pipe_enable_mask = maxim4c->video_pipe.pipe_enable_mask; ret = maxim4c_video_pipe_mask_enable(maxim4c, pipe_enable_mask, true); - if (ret) + if (ret) { + dev_err(dev, "%s: video pipe mask enable error\n", __func__); return ret; + } ret = maxim4c_video_pipe_run_init_seq(maxim4c); - if (ret) + if (ret) { + dev_err(dev, "%s: video pipe run init seq error\n", __func__); return ret; + } return 0; } diff --git a/drivers/media/i2c/maxim4c/remote_max9295.c b/drivers/media/i2c/maxim4c/remote_max9295.c index 78cd2b3555bd..b0505164e26e 100644 --- a/drivers/media/i2c/maxim4c/remote_max9295.c +++ b/drivers/media/i2c/maxim4c/remote_max9295.c @@ -20,25 +20,6 @@ #define MAX9295_CHIP_ID 0x91 #define MAX9295_REG_CHIP_ID 0x0D -static int max9295_i2c_addr_select(maxim4c_remote_t *max9295, u32 i2c_id) -{ - struct device *dev = max9295->dev; - struct i2c_client *client = max9295->client; - - if (i2c_id == MAXIM4C_I2C_SER_DEF) { - client->addr = max9295->ser_i2c_addr_def; - dev_info(dev, "select default i2c addr = 0x%x\n", client->addr); - } else if (i2c_id == MAXIM4C_I2C_SER_MAP) { - client->addr = max9295->ser_i2c_addr_map; - dev_info(dev, "select mapping i2c addr = 0x%x\n", client->addr); - } else { - dev_err(dev, "i2c select id = %d error\n", i2c_id); - return -EINVAL; - } - - return 0; -} - static int max9295_i2c_addr_remap(maxim4c_remote_t *max9295) { struct device *dev = max9295->dev; @@ -49,7 +30,7 @@ static int max9295_i2c_addr_remap(maxim4c_remote_t *max9295) if (max9295->ser_i2c_addr_map) { dev_info(dev, "Serializer i2c address remap\n"); - max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); i2c_8bit_addr = (max9295->ser_i2c_addr_map << 1); ret = maxim4c_i2c_write_byte(client, @@ -60,7 +41,7 @@ static int max9295_i2c_addr_remap(maxim4c_remote_t *max9295) return ret; } - max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_MAP); } if (max9295->cam_i2c_addr_map) { @@ -98,7 +79,7 @@ static int max9295_i2c_addr_def(maxim4c_remote_t *max9295) if (max9295->ser_i2c_addr_map) { dev_info(dev, "Serializer i2c address def\n"); - max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_MAP); i2c_8bit_addr = (max9295->ser_i2c_addr_def << 1); ret = maxim4c_i2c_write_byte(client, @@ -109,7 +90,7 @@ static int max9295_i2c_addr_def(maxim4c_remote_t *max9295) return ret; } - max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); } return 0; @@ -128,13 +109,13 @@ static int max9295_check_chipid(maxim4c_remote_t *max9295) &chip_id); if (ret != 0) { dev_info(dev, "Retry check chipid using map address\n"); - max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_MAP); ret = maxim4c_i2c_read_byte(client, MAX9295_REG_CHIP_ID, MAXIM4C_I2C_REG_ADDR_16BITS, &chip_id); if (ret != 0) { dev_err(dev, "MAX9295 detect error, ret(%d)\n", ret); - max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); return -ENODEV; } @@ -143,13 +124,13 @@ static int max9295_check_chipid(maxim4c_remote_t *max9295) } if (chip_id != MAX9295_CHIP_ID) { - dev_err(dev, "Unexpected MAX9295 chip id(%02x)\n", chip_id); + dev_err(dev, "Unexpected chip id = %02x\n", chip_id); return -ENODEV; } - dev_info(dev, "Detected MAX9295 chipid: 0x%02x\n", chip_id); + dev_info(dev, "Detected MAX9295 chip id: 0x%02x\n", chip_id); - return ret; + return 0; } static int max9295_soft_power_down(maxim4c_remote_t *max9295) @@ -175,7 +156,7 @@ static int max9295_module_init(maxim4c_remote_t *max9295) struct i2c_client *client = max9295->client; int ret = 0; - ret = max9295_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); + ret = maxim4c_remote_i2c_addr_select(max9295, MAXIM4C_I2C_SER_DEF); if (ret) return ret; @@ -263,47 +244,30 @@ static int max9295_parse_dt(maxim4c_remote_t *max9295) return 0; } -static int max9295_i2c_client_init(maxim4c_remote_t *max9295, - struct i2c_client *local_client) -{ - struct device *dev = max9295->dev; - struct i2c_client *remote_client = NULL; - u16 remote_client_addr = 0; - - if (max9295->ser_i2c_addr_map) - remote_client_addr = max9295->ser_i2c_addr_map; - else - remote_client_addr = max9295->ser_i2c_addr_def; - remote_client = devm_i2c_new_dummy_device(&local_client->dev, - local_client->adapter, remote_client_addr); - if (IS_ERR(remote_client)) { - dev_err(dev, "failed to alloc i2c client.\n"); - return -PTR_ERR(remote_client); - } - remote_client->addr = max9295->ser_i2c_addr_def; - - max9295->client = remote_client; - i2c_set_clientdata(remote_client, max9295); - - dev_info(dev, "remote i2c client init, i2c_addr = 0x%x\n", - remote_client_addr); - - return 0; -} - static int max9295_probe(struct platform_device *pdev) { struct i2c_client *client = to_i2c_client(pdev->dev.parent); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct maxim4c *maxim4c = v4l2_get_subdevdata(sd); struct maxim4c_remote *max9295 = NULL; + u32 link_id = MAXIM4C_LINK_ID_MAX; int ret = 0; dev_info(&pdev->dev, "max9295 serializer probe\n"); + link_id = (uintptr_t)of_device_get_match_data(&pdev->dev); + link_id = link_id - MAXIM4C_LINK_ID_MAX; + if (link_id >= MAXIM4C_LINK_ID_MAX) { + dev_err(&pdev->dev, "max9295 probe match data error\n"); + return -EINVAL; + } + dev_info(&pdev->dev, "max9295 probe link id = %d\n", link_id); + max9295 = devm_kzalloc(&pdev->dev, sizeof(*max9295), GFP_KERNEL); - if (!max9295) + if (!max9295) { + dev_err(&pdev->dev, "max9295 probe no memory error\n"); return -ENOMEM; + } max9295->dev = &pdev->dev; max9295->remote_ops = &max9295_ops; @@ -312,11 +276,22 @@ static int max9295_probe(struct platform_device *pdev) max9295_parse_dt(max9295); - max9295_i2c_client_init(max9295, client); + if (max9295->remote_id != link_id) { + dev_err(&pdev->dev, "max9295 probe remote_id error\n"); + return -EINVAL; + } + + ret = maxim4c_remote_i2c_client_init(max9295, client); + if (ret) { + dev_err(&pdev->dev, "remote i2c client init error\n"); + return ret; + } ret = maxim4c_remote_device_register(maxim4c, max9295); - if (ret) + if (ret) { + dev_err(&pdev->dev, "remote serializer register error\n"); return ret; + } maxim4c_remote_load_init_seq(max9295); @@ -329,10 +304,21 @@ static int max9295_remove(struct platform_device *pdev) } static const struct of_device_id max9295_of_table[] = { - { .compatible = "maxim4c,max9295", }, + { + .compatible = "maxim4c,link0,max9295", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_A) + }, { + .compatible = "maxim4c,link1,max9295", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_B) + }, { + .compatible = "maxim4c,link2,max9295", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_C) + }, { + .compatible = "maxim4c,link3,max9295", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_D) + }, { /* Sentinel */ }, }; - MODULE_DEVICE_TABLE(of, max9295_of_table); static struct platform_driver max9295_driver = { diff --git a/drivers/media/i2c/maxim4c/remote_max96715.c b/drivers/media/i2c/maxim4c/remote_max96715.c index 63ebfb798f03..3f2689a1b8df 100644 --- a/drivers/media/i2c/maxim4c/remote_max96715.c +++ b/drivers/media/i2c/maxim4c/remote_max96715.c @@ -34,43 +34,28 @@ static int __maybe_unused max96715_link_mode_select(maxim4c_remote_t *max96715, struct device *dev = max96715->dev; struct i2c_client *client = max96715->client; u8 reg_mask = 0, reg_value = 0; + u32 delay_ms = 0; int ret = 0; dev_dbg(dev, "%s: mode = %d\n", __func__, mode); reg_mask = BIT(7) | BIT(6); - if (mode == LINK_MODE_CONFIG) + if (mode == LINK_MODE_CONFIG) { reg_value = BIT(6); - else + delay_ms = 5; + } else { reg_value = BIT(7); + delay_ms = 50; + } ret |= maxim4c_i2c_update_byte(client, 0x04, MAXIM4C_I2C_REG_ADDR_08BITS, reg_mask, reg_value); - mdelay(5); + msleep(delay_ms); return ret; } -static int max96715_i2c_addr_select(maxim4c_remote_t *max96715, u32 i2c_id) -{ - struct device *dev = max96715->dev; - struct i2c_client *client = max96715->client; - - if (i2c_id == MAXIM4C_I2C_SER_DEF) { - client->addr = max96715->ser_i2c_addr_def; - dev_info(dev, "select default i2c addr = 0x%x\n", client->addr); - } else if (i2c_id == MAXIM4C_I2C_SER_MAP) { - client->addr = max96715->ser_i2c_addr_map; - dev_info(dev, "select mapping i2c addr = 0x%x\n", client->addr); - } else { - dev_err(dev, "i2c select id = %d error\n", i2c_id); - return -EINVAL; - } - - return 0; -} - static int max96715_i2c_addr_remap(maxim4c_remote_t *max96715) { struct device *dev = max96715->dev; @@ -81,7 +66,7 @@ static int max96715_i2c_addr_remap(maxim4c_remote_t *max96715) if (max96715->ser_i2c_addr_map) { dev_info(dev, "Serializer i2c address remap\n"); - max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); i2c_8bit_addr = (max96715->ser_i2c_addr_map << 1); ret = maxim4c_i2c_write_byte(client, @@ -92,7 +77,7 @@ static int max96715_i2c_addr_remap(maxim4c_remote_t *max96715) return ret; } - max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_MAP); } if (max96715->cam_i2c_addr_map) { @@ -130,7 +115,7 @@ static int max96715_i2c_addr_def(maxim4c_remote_t *max96715) if (max96715->ser_i2c_addr_map) { dev_info(dev, "Serializer i2c address def\n"); - max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_MAP); i2c_8bit_addr = (max96715->ser_i2c_addr_def << 1); ret = maxim4c_i2c_write_byte(client, @@ -141,7 +126,7 @@ static int max96715_i2c_addr_def(maxim4c_remote_t *max96715) return ret; } - max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); } return 0; @@ -160,13 +145,13 @@ static int max96715_check_chipid(maxim4c_remote_t *max96715) &chip_id); if (ret != 0) { dev_info(dev, "Retry check chipid using map address\n"); - max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_MAP); ret = maxim4c_i2c_read_byte(client, MAX96715_REG_CHIP_ID, MAXIM4C_I2C_REG_ADDR_08BITS, &chip_id); if (ret != 0) { dev_err(dev, "MAX96715 detect error, ret(%d)\n", ret); - max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); return -ENODEV; } @@ -175,13 +160,13 @@ static int max96715_check_chipid(maxim4c_remote_t *max96715) } if (chip_id != MAX96715_CHIP_ID) { - dev_err(dev, "Unexpected MAX96715 chip id(%02x)\n", chip_id); + dev_err(dev, "Unexpected chip id = %02x\n", chip_id); return -ENODEV; } - dev_info(dev, "Detected MAX96715 chipid: 0x%02x\n", chip_id); + dev_info(dev, "Detected MAX96715 chip id: 0x%02x\n", chip_id); - return ret; + return 0; } static int max96715_soft_power_down(maxim4c_remote_t *max96715) @@ -208,7 +193,7 @@ static int max96715_module_init(maxim4c_remote_t *max96715) struct maxim4c *maxim4c = max96715->local; int ret = 0; - ret = max96715_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); + ret = maxim4c_remote_i2c_addr_select(max96715, MAXIM4C_I2C_SER_DEF); if (ret) return ret; @@ -322,47 +307,30 @@ static int max96715_parse_dt(maxim4c_remote_t *max96715) return 0; } -static int max96715_i2c_client_init(maxim4c_remote_t *max96715, - struct i2c_client *local_client) -{ - struct device *dev = max96715->dev; - struct i2c_client *remote_client = NULL; - u16 remote_client_addr = 0; - - if (max96715->ser_i2c_addr_map) - remote_client_addr = max96715->ser_i2c_addr_map; - else - remote_client_addr = max96715->ser_i2c_addr_def; - remote_client = devm_i2c_new_dummy_device(&local_client->dev, - local_client->adapter, remote_client_addr); - if (IS_ERR(remote_client)) { - dev_err(dev, "failed to alloc i2c client.\n"); - return -PTR_ERR(remote_client); - } - remote_client->addr = max96715->ser_i2c_addr_def; - - max96715->client = remote_client; - i2c_set_clientdata(remote_client, max96715); - - dev_info(dev, "remote i2c client init, i2c_addr = 0x%x\n", - remote_client_addr); - - return 0; -} - static int max96715_probe(struct platform_device *pdev) { struct i2c_client *client = to_i2c_client(pdev->dev.parent); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct maxim4c *maxim4c = v4l2_get_subdevdata(sd); struct maxim4c_remote *max96715 = NULL; + u32 link_id = MAXIM4C_LINK_ID_MAX; int ret = 0; dev_info(&pdev->dev, "max96715 serializer probe\n"); + link_id = (uintptr_t)of_device_get_match_data(&pdev->dev); + link_id = link_id - MAXIM4C_LINK_ID_MAX; + if (link_id >= MAXIM4C_LINK_ID_MAX) { + dev_err(&pdev->dev, "max96715 probe match data error\n"); + return -EINVAL; + } + dev_info(&pdev->dev, "max96715 probe link id = %d\n", link_id); + max96715 = devm_kzalloc(&pdev->dev, sizeof(*max96715), GFP_KERNEL); - if (!max96715) + if (!max96715) { + dev_err(&pdev->dev, "max96715 probe no memory error\n"); return -ENOMEM; + } max96715->dev = &pdev->dev; max96715->remote_ops = &max96715_ops; @@ -371,11 +339,22 @@ static int max96715_probe(struct platform_device *pdev) max96715_parse_dt(max96715); - max96715_i2c_client_init(max96715, client); + if (max96715->remote_id != link_id) { + dev_err(&pdev->dev, "max96715 probe remote_id error\n"); + return -EINVAL; + } + + ret = maxim4c_remote_i2c_client_init(max96715, client); + if (ret) { + dev_err(&pdev->dev, "remote i2c client init error\n"); + return ret; + } ret = maxim4c_remote_device_register(maxim4c, max96715); - if (ret) + if (ret) { + dev_err(&pdev->dev, "remote serializer register error\n"); return ret; + } maxim4c_remote_load_init_seq(max96715); @@ -388,10 +367,21 @@ static int max96715_remove(struct platform_device *pdev) } static const struct of_device_id max96715_of_table[] = { - { .compatible = "maxim4c,max96715", }, + { + .compatible = "maxim4c,link0,max96715", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_A) + }, { + .compatible = "maxim4c,link1,max96715", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_B) + }, { + .compatible = "maxim4c,link2,max96715", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_C) + }, { + .compatible = "maxim4c,link3,max96715", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_D) + }, { /* Sentinel */ }, }; - MODULE_DEVICE_TABLE(of, max96715_of_table); static struct platform_driver max96715_driver = { diff --git a/drivers/media/i2c/maxim4c/remote_max96717.c b/drivers/media/i2c/maxim4c/remote_max96717.c index f8740e35d446..d0a3b7d55d64 100644 --- a/drivers/media/i2c/maxim4c/remote_max96717.c +++ b/drivers/media/i2c/maxim4c/remote_max96717.c @@ -20,25 +20,6 @@ #define MAX96717_CHIP_ID 0xBF #define MAX96717_REG_CHIP_ID 0x0D -static int max96717_i2c_addr_select(maxim4c_remote_t *max96717, u32 i2c_id) -{ - struct device *dev = max96717->dev; - struct i2c_client *client = max96717->client; - - if (i2c_id == MAXIM4C_I2C_SER_DEF) { - client->addr = max96717->ser_i2c_addr_def; - dev_info(dev, "select default i2c addr = 0x%x\n", client->addr); - } else if (i2c_id == MAXIM4C_I2C_SER_MAP) { - client->addr = max96717->ser_i2c_addr_map; - dev_info(dev, "select mapping i2c addr = 0x%x\n", client->addr); - } else { - dev_err(dev, "i2c select id = %d error\n", i2c_id); - return -EINVAL; - } - - return 0; -} - static int max96717_i2c_addr_remap(maxim4c_remote_t *max96717) { struct device *dev = max96717->dev; @@ -49,7 +30,7 @@ static int max96717_i2c_addr_remap(maxim4c_remote_t *max96717) if (max96717->ser_i2c_addr_map) { dev_info(dev, "Serializer i2c address remap\n"); - max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); i2c_8bit_addr = (max96717->ser_i2c_addr_map << 1); ret = maxim4c_i2c_write_byte(client, @@ -60,7 +41,7 @@ static int max96717_i2c_addr_remap(maxim4c_remote_t *max96717) return ret; } - max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_MAP); } if (max96717->cam_i2c_addr_map) { @@ -98,7 +79,7 @@ static int max96717_i2c_addr_def(maxim4c_remote_t *max96717) if (max96717->ser_i2c_addr_map) { dev_info(dev, "Serializer i2c address def\n"); - max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_MAP); i2c_8bit_addr = (max96717->ser_i2c_addr_def << 1); ret = maxim4c_i2c_write_byte(client, @@ -109,7 +90,7 @@ static int max96717_i2c_addr_def(maxim4c_remote_t *max96717) return ret; } - max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); } return 0; @@ -128,13 +109,13 @@ static int max96717_check_chipid(maxim4c_remote_t *max96717) &chip_id); if (ret != 0) { dev_info(dev, "Retry check chipid using map address\n"); - max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_MAP); + maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_MAP); ret = maxim4c_i2c_read_byte(client, MAX96717_REG_CHIP_ID, MAXIM4C_I2C_REG_ADDR_16BITS, &chip_id); if (ret != 0) { dev_err(dev, "MAX96717 detect error, ret(%d)\n", ret); - max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); + maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); return -ENODEV; } @@ -143,27 +124,10 @@ static int max96717_check_chipid(maxim4c_remote_t *max96717) } if (chip_id != MAX96717_CHIP_ID) { - dev_err(dev, "Unexpected MAX96717 chip id(%02x)\n", chip_id); + dev_err(dev, "Unexpected chip id = %02x\n", chip_id); return -ENODEV; } - dev_info(dev, "Detected MAX96717 chipid: 0x%02x\n", chip_id); - - return ret; -} - -static int max96717_soft_power_down(maxim4c_remote_t *max96717) -{ - struct device *dev = max96717->dev; - struct i2c_client *client = max96717->client; - int ret = 0; - - ret = maxim4c_i2c_write_byte(client, - 0x10, MAXIM4C_I2C_REG_ADDR_16BITS, - BIT(7)); - if (ret) { - dev_err(dev, "soft power down setting error!\n"); - return ret; - } + dev_info(dev, "Detected MAX96717 chip id: 0x%02x\n", chip_id); return 0; } @@ -174,7 +138,7 @@ static int max96717_module_init(maxim4c_remote_t *max96717) struct i2c_client *client = max96717->client; int ret = 0; - ret = max96717_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); + ret = maxim4c_remote_i2c_addr_select(max96717, MAXIM4C_I2C_SER_DEF); if (ret) return ret; @@ -201,10 +165,7 @@ static int max96717_module_deinit(maxim4c_remote_t *max96717) { int ret = 0; -#if 0 ret |= max96717_i2c_addr_def(max96717); -#endif - ret |= max96717_soft_power_down(max96717); return ret; } @@ -262,47 +223,30 @@ static int max96717_parse_dt(maxim4c_remote_t *max96717) return 0; } -static int max96717_i2c_client_init(maxim4c_remote_t *max96717, - struct i2c_client *local_client) -{ - struct device *dev = max96717->dev; - struct i2c_client *remote_client = NULL; - u16 remote_client_addr = 0; - - if (max96717->ser_i2c_addr_map) - remote_client_addr = max96717->ser_i2c_addr_map; - else - remote_client_addr = max96717->ser_i2c_addr_def; - remote_client = devm_i2c_new_dummy_device(&local_client->dev, - local_client->adapter, remote_client_addr); - if (IS_ERR(remote_client)) { - dev_err(dev, "failed to alloc i2c client.\n"); - return -PTR_ERR(remote_client); - } - remote_client->addr = max96717->ser_i2c_addr_def; - - max96717->client = remote_client; - i2c_set_clientdata(remote_client, max96717); - - dev_info(dev, "remote i2c client init, i2c_addr = 0x%x\n", - remote_client_addr); - - return 0; -} - static int max96717_probe(struct platform_device *pdev) { struct i2c_client *client = to_i2c_client(pdev->dev.parent); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct maxim4c *maxim4c = v4l2_get_subdevdata(sd); struct maxim4c_remote *max96717 = NULL; + u32 link_id = MAXIM4C_LINK_ID_MAX; int ret = 0; dev_info(&pdev->dev, "max96717 serializer probe\n"); + link_id = (uintptr_t)of_device_get_match_data(&pdev->dev); + link_id = link_id - MAXIM4C_LINK_ID_MAX; + if (link_id >= MAXIM4C_LINK_ID_MAX) { + dev_err(&pdev->dev, "max96717 probe match data error\n"); + return -EINVAL; + } + dev_info(&pdev->dev, "max96717 probe link id = %d\n", link_id); + max96717 = devm_kzalloc(&pdev->dev, sizeof(*max96717), GFP_KERNEL); - if (!max96717) + if (!max96717) { + dev_err(&pdev->dev, "max96717 probe no memory error\n"); return -ENOMEM; + } max96717->dev = &pdev->dev; max96717->remote_ops = &max96717_ops; @@ -311,11 +255,22 @@ static int max96717_probe(struct platform_device *pdev) max96717_parse_dt(max96717); - max96717_i2c_client_init(max96717, client); + if (max96717->remote_id != link_id) { + dev_err(&pdev->dev, "max96717 probe remote_id error\n"); + return -EINVAL; + } + + ret = maxim4c_remote_i2c_client_init(max96717, client); + if (ret) { + dev_err(&pdev->dev, "remote i2c client init error\n"); + return ret; + } ret = maxim4c_remote_device_register(maxim4c, max96717); - if (ret) + if (ret) { + dev_err(&pdev->dev, "remote serializer register error\n"); return ret; + } maxim4c_remote_load_init_seq(max96717); @@ -328,10 +283,21 @@ static int max96717_remove(struct platform_device *pdev) } static const struct of_device_id max96717_of_table[] = { - { .compatible = "maxim4c,max96717", }, + { + .compatible = "maxim4c,link0,max96717", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_A) + }, { + .compatible = "maxim4c,link1,max96717", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_B) + }, { + .compatible = "maxim4c,link2,max96717", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_C) + }, { + .compatible = "maxim4c,link3,max96717", + .data = (const void *)(MAXIM4C_LINK_ID_MAX + MAXIM4C_LINK_ID_D) + }, { /* Sentinel */ }, }; - MODULE_DEVICE_TABLE(of, max96717_of_table); static struct platform_driver max96717_driver = {