Message ID | 20200310134603.30260-1-robert.foss@linaro.org |
---|---|
Headers | show |
Series | media: ov8856: Add sensor modes & devicetree support | expand |
On Tue, Mar 10, 2020 at 10:47 AM Robert Foss <robert.foss@linaro.org> wrote: > +static int __ov8856_power_on(struct ov8856 *ov8856) > +{ > + struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); > + int ret; > + > + ret = clk_prepare_enable(ov8856->xvclk); > + if (ret < 0) { > + dev_err(&client->dev, "failed to enable xvclk\n"); > + return ret; > + } > + > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > + > + ret = regulator_bulk_enable(OV8856_NUM_SUPPLIES, ov8856->supplies); > + if (ret < 0) { > + dev_err(&client->dev, "failed to enable regulators\n"); > + goto disable_clk; > + } > + > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); To power it up you probably only need: gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, 0); And use reset-gpios as active low in your device tree. Assuming the reset-gpios is active low like other OmniVision sensors. > + > + usleep_range(1500, 1800); > + > + return 0; > + > +disable_clk: > + clk_disable_unprepare(ov8856->xvclk); > + > + return ret; > +} > + > +static void __ov8856_power_off(struct ov8856 *ov8856) > +{ > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > + clk_disable_unprepare(ov8856->xvclk); > +} > + > + Unneede extra blank line. > v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops); > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > + if (IS_ERR(ov8856->xvclk)) { > + dev_err(&client->dev, "failed to get xvclk\n"); > + return -EINVAL; You should better return the real error insteald PTR_ERR(ov8856->xvclk). This way defer probe could work. > + } > + > + ret = clk_set_rate(ov8856->xvclk, OV8856_XVCLK_24); > + if (ret < 0) { > + dev_err(&client->dev, "failed to set xvclk rate (24MHz)\n"); > + return ret; > + } > + > + ov8856->n_shutdn_gpio = devm_gpiod_get(&client->dev, "reset", > + GPIOD_OUT_LOW); > + if (IS_ERR(ov8856->n_shutdn_gpio)) { > + dev_err(&client->dev, "failed to get reset-gpios\n"); > + return -EINVAL; Please return the real error.
On Tue, Mar 10, 2020 at 02:46:02PM +0100, Robert Foss wrote: > Add devicetree match table, and enable ov8856_probe() > to initialize power, clocks and reset pins. ... > +#define OV8856_NUM_SUPPLIES ARRAY_SIZE(ov8856_supply_names) Use ARRAY_SIZE() directly. Have you seen Sakari's comments? Sakari, do I have déjà vu or you indeed commented this driver? ... > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); Yes, seems this one is inverted. ... > +{ > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > + clk_disable_unprepare(ov8856->xvclk); > +} > + > + One blank line is enough. ... > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > + if (IS_ERR(ov8856->xvclk)) { > + dev_err(&client->dev, "failed to get xvclk\n"); > + return -EINVAL; > + } Previously it worked without clock provider, now you make a dependency. This won't work.
On Tue, Mar 10, 2020 at 02:46:03PM +0100, Robert Foss wrote: > Query the sensor for its module revision, and compare it > to known revisions. > Currently only the '1B' revision has been added. Are you sure you send latest version? I have a déjà vu that I have seen this already and this one doesn't address any comment given. ... > + dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n", > + val, > + val == OV8856_1B_MODULE ? "1B" : "unknown revision", This is weird. Can you add a bit more general way of showing revision? > + client->addr);
On Tue, 10 Mar 2020 at 15:03, Fabio Estevam <festevam@gmail.com> wrote: > > On Tue, Mar 10, 2020 at 10:47 AM Robert Foss <robert.foss@linaro.org> wrote: > > > +static int __ov8856_power_on(struct ov8856 *ov8856) > > +{ > > + struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd); > > + int ret; > > + > > + ret = clk_prepare_enable(ov8856->xvclk); > > + if (ret < 0) { > > + dev_err(&client->dev, "failed to enable xvclk\n"); > > + return ret; > > + } > > + > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > + > > + ret = regulator_bulk_enable(OV8856_NUM_SUPPLIES, ov8856->supplies); > > + if (ret < 0) { > > + dev_err(&client->dev, "failed to enable regulators\n"); > > + goto disable_clk; > > + } > > + > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); > > To power it up you probably only need: > > gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, 0); > > And use reset-gpios as active low in your device tree. Assuming the > reset-gpios is active low like other OmniVision sensors. Ack. > > > + > > + usleep_range(1500, 1800); > > + > > + return 0; > > + > > +disable_clk: > > + clk_disable_unprepare(ov8856->xvclk); > > + > > + return ret; > > +} > > + > > +static void __ov8856_power_off(struct ov8856 *ov8856) > > +{ > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > > + clk_disable_unprepare(ov8856->xvclk); > > +} > > + > > + > > Unneede extra blank line. Ack. > > > v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops); > > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > > + if (IS_ERR(ov8856->xvclk)) { > > + dev_err(&client->dev, "failed to get xvclk\n"); > > + return -EINVAL; > > You should better return the real error insteald > PTR_ERR(ov8856->xvclk). This way defer probe could work. > Ack. > > + } > > + > > + ret = clk_set_rate(ov8856->xvclk, OV8856_XVCLK_24); > > + if (ret < 0) { > > + dev_err(&client->dev, "failed to set xvclk rate (24MHz)\n"); > > + return ret; > > + } > > + > > + ov8856->n_shutdn_gpio = devm_gpiod_get(&client->dev, "reset", > > + GPIOD_OUT_LOW); > > + if (IS_ERR(ov8856->n_shutdn_gpio)) { > > + dev_err(&client->dev, "failed to get reset-gpios\n"); > > + return -EINVAL; > > Please return the real error. Ack.
Hi Andy, On Tue, 10 Mar 2020 at 15:26, Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > On Tue, Mar 10, 2020 at 02:46:02PM +0100, Robert Foss wrote: > > Add devicetree match table, and enable ov8856_probe() > > to initialize power, clocks and reset pins. > > ... > > > +#define OV8856_NUM_SUPPLIES ARRAY_SIZE(ov8856_supply_names) > > Use ARRAY_SIZE() directly. Ack. > > Have you seen Sakari's comments? > Sakari, do I have déją vu or you indeed commented this driver? Yes, I may have missed some part of it, so please tell me if I have. There is a patchset floating around that implements a larger chunk of functionality, including a couple of new modes. This is based on that series. > > ... > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); > > Yes, seems this one is inverted. > > ... > > > +{ > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > > + clk_disable_unprepare(ov8856->xvclk); > > +} > > + > > + > > One blank line is enough. > > ... > > > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > > + if (IS_ERR(ov8856->xvclk)) { > > + dev_err(&client->dev, "failed to get xvclk\n"); > > + return -EINVAL; > > + } > > Previously it worked without clock provider, now you make a dependency. > > This won't work. So the ideal behavior would be to only use the xclk if it is provided?
On Tue, Mar 10, 2020 at 04:55:20PM +0100, Robert Foss wrote: > On Tue, 10 Mar 2020 at 15:26, Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: > > On Tue, Mar 10, 2020 at 02:46:02PM +0100, Robert Foss wrote: ... > > > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > > > + if (IS_ERR(ov8856->xvclk)) { > > > + dev_err(&client->dev, "failed to get xvclk\n"); > > > + return -EINVAL; > > > + } > > > > Previously it worked without clock provider, now you make a dependency. > > > > This won't work. > > So the ideal behavior would be to only use the xclk if it is provided? Yes, make it optional.
Hi Robert, On Tue, Mar 10, 2020 at 04:55:20PM +0100, Robert Foss wrote: > Hi Andy, > > On Tue, 10 Mar 2020 at 15:26, Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: > > > > On Tue, Mar 10, 2020 at 02:46:02PM +0100, Robert Foss wrote: > > > Add devicetree match table, and enable ov8856_probe() > > > to initialize power, clocks and reset pins. > > > > ... > > > > > +#define OV8856_NUM_SUPPLIES ARRAY_SIZE(ov8856_supply_names) > > > > Use ARRAY_SIZE() directly. > > Ack. > > > > > Have you seen Sakari's comments? > > Sakari, do I have déją vu or you indeed commented this driver? > > Yes, I may have missed some part of it, so please tell me if I have. > > There is a patchset floating around that implements a larger chunk of > functionality, > including a couple of new modes. This is based on that series. Please see earlier comments given against an earlier variant of this set. They're on LMML. > > > > > ... > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); > > > > Yes, seems this one is inverted. > > > > ... > > > > > +{ > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > > > + clk_disable_unprepare(ov8856->xvclk); > > > +} > > > + > > > + > > > > One blank line is enough. > > > > ... > > > > > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > > > + if (IS_ERR(ov8856->xvclk)) { > > > + dev_err(&client->dev, "failed to get xvclk\n"); > > > + return -EINVAL; > > > + } > > > > Previously it worked without clock provider, now you make a dependency. > > > > This won't work. > > So the ideal behavior would be to only use the xclk if it is provided? See e.g. the smiapp driver on how to do this so it continues to work on ACPI. I think it'd be also appropriate to add the usleep() after lifting reset only if the reset GPIO is defined for the device. Also do consider dropping some people from the distribution. For many this is just noise.
Hey Sakari, On Wed, 11 Mar 2020 at 12:49, Sakari Ailus <sakari.ailus@iki.fi> wrote: > > Hi Robert, > > On Tue, Mar 10, 2020 at 04:55:20PM +0100, Robert Foss wrote: > > Hi Andy, > > > > On Tue, 10 Mar 2020 at 15:26, Andy Shevchenko > > <andriy.shevchenko@linux.intel.com> wrote: > > > > > > On Tue, Mar 10, 2020 at 02:46:02PM +0100, Robert Foss wrote: > > > > Add devicetree match table, and enable ov8856_probe() > > > > to initialize power, clocks and reset pins. > > > > > > ... > > > > > > > +#define OV8856_NUM_SUPPLIES ARRAY_SIZE(ov8856_supply_names) > > > > > > Use ARRAY_SIZE() directly. > > > > Ack. > > > > > > > > Have you seen Sakari's comments? > > > Sakari, do I have déją vu or you indeed commented this driver? > > > > Yes, I may have missed some part of it, so please tell me if I have. > > > > There is a patchset floating around that implements a larger chunk of > > functionality, > > including a couple of new modes. This is based on that series. > > Please see earlier comments given against an earlier variant of this set. > They're on LMML. > > > > > > > > > ... > > > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); > > > > > > Yes, seems this one is inverted. > > > > > > ... > > > > > > > +{ > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > > > > + clk_disable_unprepare(ov8856->xvclk); > > > > +} > > > > + > > > > + > > > > > > One blank line is enough. > > > > > > ... > > > > > > > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > > > > + if (IS_ERR(ov8856->xvclk)) { > > > > + dev_err(&client->dev, "failed to get xvclk\n"); > > > > + return -EINVAL; > > > > + } > > > > > > Previously it worked without clock provider, now you make a dependency. > > > > > > This won't work. > > > > So the ideal behavior would be to only use the xclk if it is provided? > > See e.g. the smiapp driver on how to do this so it continues to work on > ACPI. Thanks for the pointer! > > I think it'd be also appropriate to add the usleep() after lifting reset > only if the reset GPIO is defined for the device. Ack
On Wed, Mar 11, 2020 at 02:32:30PM +0100, Robert Foss wrote: > Hey Sakari, > > On Wed, 11 Mar 2020 at 12:49, Sakari Ailus <sakari.ailus@iki.fi> wrote: > > > > Hi Robert, > > > > On Tue, Mar 10, 2020 at 04:55:20PM +0100, Robert Foss wrote: > > > Hi Andy, > > > > > > On Tue, 10 Mar 2020 at 15:26, Andy Shevchenko > > > <andriy.shevchenko@linux.intel.com> wrote: > > > > > > > > On Tue, Mar 10, 2020 at 02:46:02PM +0100, Robert Foss wrote: > > > > > Add devicetree match table, and enable ov8856_probe() > > > > > to initialize power, clocks and reset pins. > > > > > > > > ... > > > > > > > > > +#define OV8856_NUM_SUPPLIES ARRAY_SIZE(ov8856_supply_names) > > > > > > > > Use ARRAY_SIZE() directly. > > > > > > Ack. > > > > > > > > > > > Have you seen Sakari's comments? > > > > Sakari, do I have déją vu or you indeed commented this driver? > > > > > > Yes, I may have missed some part of it, so please tell me if I have. > > > > > > There is a patchset floating around that implements a larger chunk of > > > functionality, > > > including a couple of new modes. This is based on that series. > > > > Please see earlier comments given against an earlier variant of this set. > > They're on LMML. > > > > > > > > > > > > > ... > > > > > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > > > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_HIGH); > > > > > > > > Yes, seems this one is inverted. > > > > > > > > ... > > > > > > > > > +{ > > > > > + gpiod_set_value_cansleep(ov8856->n_shutdn_gpio, GPIOD_OUT_LOW); > > > > > + regulator_bulk_disable(OV8856_NUM_SUPPLIES, ov8856->supplies); > > > > > + clk_disable_unprepare(ov8856->xvclk); > > > > > +} > > > > > + > > > > > + > > > > > > > > One blank line is enough. > > > > > > > > ... > > > > > > > > > + ov8856->xvclk = devm_clk_get(&client->dev, "xvclk"); > > > > > + if (IS_ERR(ov8856->xvclk)) { > > > > > + dev_err(&client->dev, "failed to get xvclk\n"); > > > > > + return -EINVAL; > > > > > + } > > > > > > > > Previously it worked without clock provider, now you make a dependency. > > > > > > > > This won't work. > > > > > > So the ideal behavior would be to only use the xclk if it is provided? > > > > See e.g. the smiapp driver on how to do this so it continues to work on > > ACPI. > > Thanks for the pointer! > > > > > I think it'd be also appropriate to add the usleep() after lifting reset > > only if the reset GPIO is defined for the device. > > Ack On second thought, that probably applies if any of the resources needed for powering the device on are defined. It could be that there's no reset GPIO but a regulator is still there, in which case a delay is needed.
Hey Andy, On Tue, 10 Mar 2020 at 15:30, Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > On Tue, Mar 10, 2020 at 02:46:03PM +0100, Robert Foss wrote: > > Query the sensor for its module revision, and compare it > > to known revisions. > > Currently only the '1B' revision has been added. > > Are you sure you send latest version? > > I have a déją vu that I have seen this already and this one doesn't address any > comment given. I think pulled a series Dongchun Zhus earlier series apart and used some of it, I may have missed some of the feedback given to his v3. Sorry about that. > > ... > > > + dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n", > > + val, > > > + val == OV8856_1B_MODULE ? "1B" : "unknown revision", > > This is weird. Can you add a bit more general way of showing revision? This is modeled after the ov7251 driver, since that output came in handy during bringup. dev_info(dev, "OV7251 revision %x (%s) detected at address 0x%02x\n", chip_rev, chip_rev == 0x4 ? "1A / 1B" : chip_rev == 0x5 ? "1C / 1D" : chip_rev == 0x6 ? "1E" : chip_rev == 0x7 ? "1F" : "unknown", client->addr); To me this is pretty general approach, at least until this revision information is used in other places. I'm not quite sure what you had in mind. Maybe the current implementation is a little bit clunky in the case of ov8856 since there's only one revision number known currently. Either way, I'll happily change it. But I don't quite know what you have in mind. > > > + client->addr); > > -- > With Best Regards, > Andy Shevchenko > >