From 11f3d4d0e84dc1215551bc3fe41e09b9f38858e5 Mon Sep 17 00:00:00 2001 From: Shiju Mathew Date: Fri, 22 Apr 2016 17:42:08 -0400 Subject: [PATCH] adv7481: Fix issues with adv7481 driver functionality Fix memory allocation and probing crashes in adv7481 driver. Add support for DT and GPIO configurations. CRs-Fixed: 998927 Change-Id: I056dbecbd2b3c7c2c0bc0314b9c68e992452d84f Signed-off-by: Shiju Mathew --- .../devicetree/bindings/arm/msm/adv7481.txt | 9 ++ drivers/media/i2c/adv7481.c | 139 +++++------------- 2 files changed, 46 insertions(+), 102 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/msm/adv7481.txt b/Documentation/devicetree/bindings/arm/msm/adv7481.txt index ea5fc3025fe2..2f5adf634273 100644 --- a/Documentation/devicetree/bindings/arm/msm/adv7481.txt +++ b/Documentation/devicetree/bindings/arm/msm/adv7481.txt @@ -10,6 +10,9 @@ Required properties - compatible: "qcom,adv7481" - qcom,slave-addr: The i2c slave address of adv7481 driver. - qcom,cci-master: The i2c master id to be used for adv7481 driver. +- gpios: The GPIOs required to be configured for the driver. It should + be in the order I2C data line, i2c clock line, reset line, + interrupt 1, interrupt 2 and interrupt 3. Example: @@ -17,4 +20,10 @@ Example: compatible = "qcom,adv7481"; qcom,cci-master = <0>; qcom,slave-addr = <0x70>; + gpios = <&tlmm 17 0>, /* I2C SDA */ + <&tlmm 18 0>, /* I2C SCL */ + <&pm8994_gpios 4 0>, /* RST */ + <&pm8994_gpios 5 0>, /* INT1 */ + <&pm8994_gpios 6 0>, /* INT2 */ + <&pm8994_gpios 7 0>; /* INT3 */ }; diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c index 27b8a194ce7b..567a7ac85be3 100644 --- a/drivers/media/i2c/adv7481.c +++ b/drivers/media/i2c/adv7481.c @@ -77,22 +77,12 @@ enum adv7481_gpio_t { }; struct adv7481_state { - /* Platform Data */ - struct adv7481_platform_data pdata; struct device *dev; - /* VREG */ - struct camera_vreg_t *cci_vreg; - struct regulator *cci_reg_ptr[MAX_REGULATOR]; - int32_t regulator_count; - /* I2C */ struct msm_camera_i2c_client i2c_client; u32 cci_master; u32 i2c_slave_addr; - u32 i2c_csi_slave_addr; - u32 i2c_vpp_slave_addr; - u32 register_page; /* V4L2 Data */ struct v4l2_subdev sd; @@ -590,7 +580,7 @@ static int adv7481_dev_init(struct adv7481_state *state) ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_MAIN_RST_ADDR, IO_REG_MAIN_RST_VALUE); /* Delay required following I2C reset and I2C transactions */ - usleep_range(I2C_SW_RST_DELAY, I2C_SW_RST_DELAY + 1000); + udelay(I2C_SW_RST_DELAY); chip_rev_id = adv7481_rd_word(&state->i2c_client, state->i2c_io_addr, IO_REG_CHIP_REV_ID_1_ADDR); @@ -679,12 +669,10 @@ static int adv7481_hw_init(struct adv7481_state *state) if (gpio_is_valid(state->gpio_array[ADV7481_GPIO_RST].gpio)) { ret |= gpio_direction_output( state->gpio_array[ADV7481_GPIO_RST].gpio, 0); - usleep_range(GPIO_HW_RST_DELAY_LOW, GPIO_HW_RST_DELAY_LOW + - 1000); + udelay(GPIO_HW_RST_DELAY_LOW); ret |= gpio_direction_output( state->gpio_array[ADV7481_GPIO_RST].gpio, 1); - usleep_range(GPIO_HW_RST_DELAY_HI, GPIO_HW_RST_DELAY_HI + - 1000); + udelay(GPIO_HW_RST_DELAY_HI); if (ret) { pr_err("%s: Set GPIO Fail %d\n", __func__, ret); goto err_exit; @@ -2037,6 +2025,10 @@ static int adv7481_cci_init(struct adv7481_state *state) } cci_client->cci_subdev = msm_cci_get_subdev(); pr_debug("%s cci_subdev: %p\n", __func__, cci_client->cci_subdev); + if (!cci_client->cci_subdev) { + ret = -EPROBE_DEFER; + goto err_cci_init; + } cci_client->cci_i2c_master = state->cci_master; cci_client->sid = state->i2c_slave_addr; cci_client->retries = 3; @@ -2057,77 +2049,47 @@ err_cci_init: static int adv7481_parse_dt(struct adv7481_state *state) { struct device_node *np = state->dev->of_node; - unsigned int i; + uint32_t i = 0; int gpio_count = 0; - int flag_count = 0; - int label_count = 0; int ret = 0; /* config CCI */ ret = of_property_read_u32(np, "qcom,cci-master", &state->cci_master); if (ret < 0 || state->cci_master >= MASTER_MAX) { - pr_err("%s: failed ret %d\n", __func__, ret); + pr_err("%s: failed to read cci master . ret %d\n", + __func__, ret); goto exit; } pr_debug("%s: cci_master: 0x%x\n", __func__, state->cci_master); ret = of_property_read_u32(np, "qcom,slave-addr", &state->i2c_slave_addr); if (ret < 0) { - pr_err("%s: failed ret %d\n", __func__, ret); + pr_err("%s: failed to read slave-addr. ret %d\n", + __func__, ret); goto exit; } pr_debug("%s: i2c_slave_addr: 0x%x\n", __func__, state->i2c_slave_addr); state->i2c_io_addr = (uint8_t)state->i2c_slave_addr; - ret = of_property_read_u32(np, "qcom,csi-slave-addr", - &state->i2c_csi_slave_addr); - if (ret < 0) { - pr_err("%s: failed ret %d\n", __func__, ret); - goto exit; - } - pr_debug("%s: i2c_csi_slave_addr: 0x%x\n", __func__, - state->i2c_csi_slave_addr); - ret = of_property_read_u32(np, "qcom,vpp-slave-addr", - &state->i2c_vpp_slave_addr); - if (ret < 0) { - pr_err("%s: failed ret %d\n", __func__, ret); - goto exit; - } - pr_debug("%s: i2c_vpp_slave_addr: 0x%x\n", __func__, - state->i2c_vpp_slave_addr); - - ret = adv7481_cci_init(state); - if (ret < 0) { - pr_err("%s: failed adv7481_cci_init ret %d\n", __func__, ret); - goto exit; - } - /* Configure GPIOs */ gpio_count = of_gpio_count(np); - pr_debug("%s: of_gpio_count: 0x%x\n", __func__, gpio_count); - flag_count = of_property_count_u32_elems(np, "qcom,gpio-tbl-flags"); - pr_debug("%s: gpio-tbl-flags: 0x%x\n", __func__, flag_count); - label_count = of_property_count_strings(np, "qcom,gpio-tbl-label"); - pr_debug("%s: gpio-tbl-label: 0x%x\n", __func__, label_count); - if (gpio_count != ADV7481_GPIO_MAX || - flag_count != ADV7481_GPIO_MAX || - label_count != ADV7481_GPIO_MAX) { + if (gpio_count != ADV7481_GPIO_MAX) { ret = -EFAULT; - pr_err("%s: failed to configure GPIO ret -EFAULT\n", __func__); + pr_err("%s: dt gpio count %d doesn't match required. ret %d\n", + __func__, gpio_count, ret); goto exit; } for (i = 0; i < ADV7481_GPIO_MAX; i++) { - u32 tmp; - - state->gpio_array[i].gpio = of_get_gpio(np, i); - of_property_read_u32_index(np, "qcom,gpio-tbl-flags", i, &tmp); - state->gpio_array[i].flags = tmp; - of_property_read_string_index(np, "qcom,gpio-tbl-label", i, - &state->gpio_array[i].label); - pr_debug("%s: gpio_array[%d] = %d\n", __func__, i, - state->gpio_array[i].gpio); + state->gpio_array[i].gpio = of_get_gpio_flags(np, i, + (enum of_gpio_flags *)&state->gpio_array[i].flags); + if (!gpio_is_valid(state->gpio_array[i].gpio)) { + pr_err("invalid gpio setting for index %d\n", i); + ret = -EFAULT; + goto exit; + } + pr_debug("%s: gpio_array[%d] = %d flag = %ld\n", __func__, i, + state->gpio_array[i].gpio, state->gpio_array[i].flags); } - pr_debug("%s: End read back gpio from dt...", __func__); exit: return ret; @@ -2143,7 +2105,6 @@ static int adv7481_probe(struct platform_device *pdev) { struct adv7481_state *state; const struct of_device_id *device_id; - struct adv7481_platform_data *pdata = NULL; struct v4l2_subdev *sd; int ret; @@ -2161,44 +2122,19 @@ static int adv7481_probe(struct platform_device *pdev) ret = -ENOMEM; goto err; } + platform_set_drvdata(pdev, state); state->dev = &pdev->dev; mutex_init(&state->mutex); - - /* config VREG */ - ret = msm_camera_get_dt_vreg_data(pdev->dev.of_node, - &(state->cci_vreg), &(state->regulator_count)); - if (ret < 0) { - pr_err("%s:cci get_dt_vreg failed\n", __func__); - goto err_mem_free; - } - - ret = msm_camera_config_vreg(&pdev->dev, state->cci_vreg, - state->regulator_count, NULL, 0, - &state->cci_reg_ptr[0], 1); - if (ret < 0) { - pr_err("%s:cci config_vreg failed\n", __func__); - goto err_mem_free; - } - - ret = msm_camera_enable_vreg(&pdev->dev, state->cci_vreg, - state->regulator_count, NULL, 0, - &state->cci_reg_ptr[0], 1); - if (ret < 0) { - pr_err("%s:cci enable_vreg failed\n", __func__); - goto err_mem_free; - } - pr_debug("%s - VREG Initialized...\n", __func__); - ret = adv7481_parse_dt(state); - pr_debug("%s - Done parsing dt...\n", __func__); + if (ret < 0) { + pr_err("Error parsing dt tree\n"); + goto err_mem_free; + } - /* Get and Check Platform Data */ - pdata = (struct adv7481_platform_data *) pdev->dev.platform_data; - if (!pdata) { - ret = -ENOMEM; - pr_err("%s(%d): Getting Platform data failed\n", - __func__, __LINE__); + ret = adv7481_cci_init(state); + if (ret < 0) { + pr_err("%s: failed adv7481_cci_init ret %d\n", __func__, ret); goto err_mem_free; } @@ -2265,19 +2201,18 @@ static int adv7481_probe(struct platform_device *pdev) err_media_entity: media_entity_cleanup(&sd->entity); + err_mem_free: - kfree(state); + devm_kfree(&pdev->dev, state); + err: - if (!ret) - ret = 1; return ret; } static int adv7481_remove(struct platform_device *pdev) { - struct adv7481_state *state; + struct adv7481_state *state = platform_get_drvdata(pdev); - state = pdev->dev.platform_data; msm_ba_unregister_subdev_node(&state->sd); v4l2_device_unregister_subdev(&state->sd); media_entity_cleanup(&state->sd.entity); @@ -2290,7 +2225,7 @@ static int adv7481_remove(struct platform_device *pdev) cancel_delayed_work(&state->irq_delayed_work); mutex_destroy(&state->mutex); - kfree(state); + devm_kfree(&pdev->dev, state); return 0; }