mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
media: i2c: maxim4c: driver version 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 Signed-off-by: Cai Wenzhong <cwz@rock-chips.com> Change-Id: Ife74e6251b09628e8413aa810c995e7a71449f1d
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Author: Cai Wenzhong <cwz@rock-chips.com>
|
||||
*
|
||||
* 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 <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -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 <cwz@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Maxim qual gmsl deserializer driver");
|
||||
MODULE_AUTHOR("Cai Wenzhong <cwz@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Maxim quad gmsl deserializer driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -8,48 +8,129 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user