Hi Philipp, Thank you for the patch. On Tuesday 03 June 2014 11:35:55 Philipp Zabel wrote: > This switches all register accesses to use regmap. It allows to > use the regmap cache, tracing, and debug register dump facilities, > and removes the need to open code read-modify-writes. > > Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx> This looks good to me, but I have two small questions: - How does regmap handle endianness ? It seems to hardcode a big endian byte order, which is fortunately what we need here. I suppose you've successfully tested this patch :-) - How does regmap handle the register cache ? Will it try to populate it when initialized, or will it only read registers on demand due to a read or an update bits operation ? > --- > This patch was not included before. > --- > drivers/media/i2c/Kconfig | 1 + > drivers/media/i2c/mt9v032.c | 112 +++++++++++++++++------------------------ > 2 files changed, 46 insertions(+), 67 deletions(-) > > diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig > index 441053b..f40b4cf 100644 > --- a/drivers/media/i2c/Kconfig > +++ b/drivers/media/i2c/Kconfig > @@ -551,6 +551,7 @@ config VIDEO_MT9V032 > tristate "Micron MT9V032 sensor support" > depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API > depends on MEDIA_CAMERA_SUPPORT > + select REGMAP_I2C > ---help--- > This is a Video4Linux2 sensor-level driver for the Micron > MT9V032 752x480 CMOS sensor. > diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c > index cb7c6df..e756d50 100644 > --- a/drivers/media/i2c/mt9v032.c > +++ b/drivers/media/i2c/mt9v032.c > @@ -17,6 +17,7 @@ > #include <linux/i2c.h> > #include <linux/log2.h> > #include <linux/mutex.h> > +#include <linux/regmap.h> > #include <linux/slab.h> > #include <linux/videodev2.h> > #include <linux/v4l2-mediabus.h> > @@ -245,6 +246,7 @@ struct mt9v032 { > struct mutex power_lock; > int power_count; > > + struct regmap *regmap; > struct clk *clk; > > struct mt9v032_platform_data *pdata; > @@ -252,7 +254,6 @@ struct mt9v032 { > const struct mt9v032_model_version *version; > > u32 sysclk; > - u16 chip_control; > u16 aec_agc; > u16 hblank; > struct { > @@ -266,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev > *sd) return container_of(sd, struct mt9v032, subdev); > } > > -static int mt9v032_read(struct i2c_client *client, const u8 reg) > -{ > - s32 data = i2c_smbus_read_word_swapped(client, reg); > - dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__, > - data, reg); > - return data; > -} > - > -static int mt9v032_write(struct i2c_client *client, const u8 reg, > - const u16 data) > -{ > - dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__, > - data, reg); > - return i2c_smbus_write_word_swapped(client, reg, data); > -} > - > -static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 > set) -{ > - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); > - u16 value = (mt9v032->chip_control & ~clear) | set; > - int ret; > - > - ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value); > - if (ret < 0) > - return ret; > - > - mt9v032->chip_control = value; > - return 0; > -} > - > static int > mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable) > { > - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); > + struct regmap *map = mt9v032->regmap; > u16 value = mt9v032->aec_agc; > int ret; > > @@ -308,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 > which, int enable) else > value &= ~which; > > - ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value); > + ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value); > if (ret < 0) > return ret; > > @@ -319,7 +290,6 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 > which, int enable) static int > mt9v032_update_hblank(struct mt9v032 *mt9v032) > { > - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); > struct v4l2_rect *crop = &mt9v032->crop; > unsigned int min_hblank = mt9v032->model->data->min_hblank; > unsigned int hblank; > @@ -330,12 +300,13 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032) > min_hblank); > hblank = max_t(unsigned int, mt9v032->hblank, min_hblank); > > - return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank); > + return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING, > + hblank); > } > > static int mt9v032_power_on(struct mt9v032 *mt9v032) > { > - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); > + struct regmap *map = mt9v032->regmap; > unsigned long rate; > int ret; > > @@ -350,7 +321,7 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) > udelay(1); > > /* Reset the chip and stop data read out */ > - ret = mt9v032_write(client, MT9V032_RESET, 1); > + ret = regmap_write(map, MT9V032_RESET, 1); > if (ret < 0) > return ret; > > @@ -358,7 +329,7 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) > rate = clk_get_rate(mt9v032->clk); > ndelay(DIV_ROUND_UP(15 * 125000000, rate >> 3)); > > - return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0); > + return regmap_write(map, MT9V032_CHIP_CONTROL, 0); > } > > static void mt9v032_power_off(struct mt9v032 *mt9v032) > @@ -368,7 +339,7 @@ static void mt9v032_power_off(struct mt9v032 *mt9v032) > > static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) > { > - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); > + struct regmap *map = mt9v032->regmap; > int ret; > > if (!on) { > @@ -382,14 +353,14 @@ static int __mt9v032_set_power(struct mt9v032 > *mt9v032, bool on) > > /* Configure the pixel clock polarity */ > if (mt9v032->pdata && mt9v032->pdata->clk_pol) { > - ret = mt9v032_write(client, mt9v032->model->data->pclk_reg, > + ret = regmap_write(map, mt9v032->model->data->pclk_reg, > MT9V032_PIXEL_CLOCK_INV_PXL_CLK); > if (ret < 0) > return ret; > } > > /* Disable the noise correction algorithm and restore the controls. */ > - ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0); > + ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0); > if (ret < 0) > return ret; > > @@ -433,43 +404,39 @@ static int mt9v032_s_stream(struct v4l2_subdev > *subdev, int enable) const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE > > | MT9V032_CHIP_CONTROL_DOUT_ENABLE > | MT9V032_CHIP_CONTROL_SEQUENTIAL; > > - struct i2c_client *client = v4l2_get_subdevdata(subdev); > struct mt9v032 *mt9v032 = to_mt9v032(subdev); > struct v4l2_rect *crop = &mt9v032->crop; > - unsigned int read_mode; > + struct regmap *map = mt9v032->regmap; > unsigned int hbin; > unsigned int vbin; > int ret; > > if (!enable) > - return mt9v032_set_chip_control(mt9v032, mode, 0); > + return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0); > > /* Configure the window size and row/column bin */ > hbin = fls(mt9v032->hratio) - 1; > vbin = fls(mt9v032->vratio) - 1; > - read_mode = mt9v032_read(client, MT9V032_READ_MODE); > - if (read_mode < 0) > - return read_mode; > - read_mode &= MT9V032_READ_MODE_RESERVED; > - read_mode |= hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT | > - vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT; > - ret = mt9v032_write(client, MT9V032_READ_MODE, read_mode); > + ret = regmap_update_bits(map, MT9V032_READ_MODE, > + ~MT9V032_READ_MODE_RESERVED, > + hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT | > + vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT); > if (ret < 0) > return ret; > > - ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left); > + ret = regmap_write(map, MT9V032_COLUMN_START, crop->left); > if (ret < 0) > return ret; > > - ret = mt9v032_write(client, MT9V032_ROW_START, crop->top); > + ret = regmap_write(map, MT9V032_ROW_START, crop->top); > if (ret < 0) > return ret; > > - ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width); > + ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width); > if (ret < 0) > return ret; > > - ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height); > + ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height); > if (ret < 0) > return ret; > > @@ -478,7 +445,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, > int enable) return ret; > > /* Switch to master "normal" mode */ > - return mt9v032_set_chip_control(mt9v032, 0, mode); > + return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode); > } > > static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, > @@ -660,7 +627,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) > { > struct mt9v032 *mt9v032 = > container_of(ctrl->handler, struct mt9v032, ctrls); > - struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); > + struct regmap *map = mt9v032->regmap; > u32 freq; > u16 data; > > @@ -670,23 +637,23 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) > ctrl->val); > > case V4L2_CID_GAIN: > - return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val); > + return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val); > > case V4L2_CID_EXPOSURE_AUTO: > return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE, > !ctrl->val); > > case V4L2_CID_EXPOSURE: > - return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH, > - ctrl->val); > + return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH, > + ctrl->val); > > case V4L2_CID_HBLANK: > mt9v032->hblank = ctrl->val; > return mt9v032_update_hblank(mt9v032); > > case V4L2_CID_VBLANK: > - return mt9v032_write(client, MT9V032_VERTICAL_BLANKING, > - ctrl->val); > + return regmap_write(map, MT9V032_VERTICAL_BLANKING, > + ctrl->val); > > case V4L2_CID_PIXEL_RATE: > case V4L2_CID_LINK_FREQ: > @@ -723,7 +690,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl) > > | MT9V032_TEST_PATTERN_FLIP; > > break; > } > - return mt9v032_write(client, MT9V032_TEST_PATTERN, data); > + return regmap_write(map, MT9V032_TEST_PATTERN, data); > } > > return 0; > @@ -791,7 +758,7 @@ static int mt9v032_registered(struct v4l2_subdev > *subdev) struct i2c_client *client = v4l2_get_subdevdata(subdev); > struct mt9v032 *mt9v032 = to_mt9v032(subdev); > unsigned int i; > - s32 version; > + u32 version; > int ret; > > dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", > @@ -804,10 +771,10 @@ static int mt9v032_registered(struct v4l2_subdev > *subdev) } > > /* Read and check the sensor version */ > - version = mt9v032_read(client, MT9V032_CHIP_VERSION); > - if (version < 0) { > + ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version); > + if (ret < 0) { > dev_err(&client->dev, "Failed reading chip version\n"); > - return version; > + return ret; > } > > for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) { > @@ -894,6 +861,13 @@ static const struct v4l2_subdev_internal_ops > mt9v032_subdev_internal_ops = { .close = mt9v032_close, > }; > > +static const struct regmap_config mt9v032_regmap_config = { > + .reg_bits = 8, > + .val_bits = 16, > + .max_register = 0xff, > + .cache_type = REGCACHE_RBTREE, > +}; > + > /* > --------------------------------------------------------------------------- > -- * Driver initialization and probing > */ > @@ -917,6 +891,10 @@ static int mt9v032_probe(struct i2c_client *client, > if (!mt9v032) > return -ENOMEM; > > + mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config); > + if (IS_ERR(mt9v032->regmap)) > + return PTR_ERR(mt9v032->regmap); > + > mt9v032->clk = devm_clk_get(&client->dev, NULL); > if (IS_ERR(mt9v032->clk)) > return PTR_ERR(mt9v032->clk); -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html