On Monday, September 19, 2011 07:35:27 Manjunath Hadli wrote: > This patch implements the core additions to the display driver, > mainly controlling the VENC and other encoders for dm365. > This patch also includes addition of amplifier subdevice to the > vpbe driver and interfacing with venc subdevice. > > Signed-off-by: Manjunath Hadli <manjunath.hadli@xxxxxx> > --- > drivers/media/video/davinci/vpbe.c | 55 ++++++++++++++++++++++++++++++++++-- > include/media/davinci/vpbe.h | 16 ++++++++++ > 2 files changed, 68 insertions(+), 3 deletions(-) > > diff --git a/drivers/media/video/davinci/vpbe.c b/drivers/media/video/davinci/vpbe.c > index d773d30..21a8645 100644 > --- a/drivers/media/video/davinci/vpbe.c > +++ b/drivers/media/video/davinci/vpbe.c > @@ -141,11 +141,12 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev, > return 0; > } > > -static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode) > +static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode, > + int output_index) > { > struct vpbe_config *cfg = vpbe_dev->cfg; > struct vpbe_enc_mode_info var; > - int curr_output = vpbe_dev->current_out_index; > + int curr_output = output_index; > int i; > > if (NULL == mode) > @@ -245,6 +246,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index) > struct encoder_config_info *curr_enc_info = > vpbe_current_encoder_info(vpbe_dev); > struct vpbe_config *cfg = vpbe_dev->cfg; > + struct venc_platform_data *venc_device = vpbe_dev->venc_device; > + enum v4l2_mbus_pixelcode if_params; > int enc_out_index; > int sd_index; > int ret = 0; > @@ -274,6 +277,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index) > goto out; > } > > + if_params = cfg->outputs[index].if_params; > + venc_device->setup_if_config(if_params); > if (ret) > goto out; > } > @@ -293,7 +298,7 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index) > * encoder. > */ > ret = vpbe_get_mode_info(vpbe_dev, > - cfg->outputs[index].default_mode); > + cfg->outputs[index].default_mode, index); > if (!ret) { > struct osd_state *osd_device = vpbe_dev->osd_device; > > @@ -367,6 +372,11 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev, > > ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video, > s_dv_preset, dv_preset); > + if (!ret && (vpbe_dev->amp != NULL)) { > + /* Call amplifier subdevice */ > + ret = v4l2_subdev_call(vpbe_dev->amp, video, > + s_dv_preset, dv_preset); > + } > /* set the lcd controller output for the given mode */ > if (!ret) { > struct osd_state *osd_device = vpbe_dev->osd_device; > @@ -566,6 +576,8 @@ static int platform_device_get(struct device *dev, void *data) > > if (strcmp("vpbe-osd", pdev->name) == 0) > vpbe_dev->osd_device = platform_get_drvdata(pdev); > + if (strcmp("vpbe-venc", pdev->name) == 0) > + vpbe_dev->venc_device = dev_get_platdata(&pdev->dev); > > return 0; > } > @@ -584,6 +596,7 @@ static int platform_device_get(struct device *dev, void *data) > static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) > { > struct encoder_config_info *enc_info; > + struct amp_config_info *amp_info; > struct v4l2_subdev **enc_subdev; > struct osd_state *osd_device; > struct i2c_adapter *i2c_adap; > @@ -704,6 +717,39 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) > v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders" > " currently not supported"); > } > + /* Add amplifier subdevice for dm365 */ > + if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) && > + vpbe_dev->cfg->amp != NULL) { > + vpbe_dev->amp = kmalloc(sizeof(struct v4l2_subdev *), > + GFP_KERNEL); Huh? Why alloc a struct v4l2_subdev pointer here? > + if (vpbe_dev->amp == NULL) { > + v4l2_err(&vpbe_dev->v4l2_dev, > + "unable to allocate memory for sub device"); > + ret = -ENOMEM; > + goto vpbe_fail_v4l2_device; > + } > + amp_info = vpbe_dev->cfg->amp; > + if (amp_info->is_i2c) { > + vpbe_dev->amp = v4l2_i2c_new_subdev_board( > + &vpbe_dev->v4l2_dev, i2c_adap, > + &_info->board_info, NULL); Especially since it is overwritten here! And so causes a memory leak. The kmalloc above (and the kfree below) feels like old code that should have been removed. > + if (!vpbe_dev->amp) { > + v4l2_err(&vpbe_dev->v4l2_dev, > + "amplifier %s failed to register", > + amp_info->module_name); > + ret = -ENODEV; > + goto vpbe_fail_amp_register; > + } > + v4l2_info(&vpbe_dev->v4l2_dev, > + "v4l2 sub device %s registered\n", > + amp_info->module_name); > + } else { > + vpbe_dev->amp = NULL; > + v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers" > + " currently not supported"); > + } > + } else > + vpbe_dev->amp = NULL; > > /* set the current encoder and output to that of venc by default */ > vpbe_dev->current_sd_index = 0; > @@ -731,6 +777,8 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) > /* TBD handling of bootargs for default output and mode */ > return 0; > > +vpbe_fail_amp_register: > + kfree(vpbe_dev->amp); > vpbe_fail_sd_register: > kfree(vpbe_dev->encoders); > vpbe_fail_v4l2_device: > @@ -757,6 +805,7 @@ static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev) > if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) > clk_put(vpbe_dev->dac_clk); > > + kfree(vpbe_dev->amp); > kfree(vpbe_dev->encoders); > vpbe_dev->initialized = 0; > /* disable vpss clocks */ > diff --git a/include/media/davinci/vpbe.h b/include/media/davinci/vpbe.h > index 8b11fb0..8bc1b3c 100644 > --- a/include/media/davinci/vpbe.h > +++ b/include/media/davinci/vpbe.h > @@ -63,6 +63,7 @@ struct vpbe_output { > * output basis. If per mode is needed, we may have to move this to > * mode_info structure > */ > + enum v4l2_mbus_pixelcode if_params; > }; > > /* encoder configuration info */ > @@ -74,6 +75,15 @@ struct encoder_config_info { > struct i2c_board_info board_info; > }; > > +/*amplifier configuration info */ > +struct amp_config_info { > + char module_name[32]; > + /* Is this an i2c device ? */ > + unsigned int is_i2c:1; > + /* i2c subdevice board info */ > + struct i2c_board_info board_info; > +}; > + > /* structure for defining vpbe display subsystem components */ > struct vpbe_config { > char module_name[32]; > @@ -84,6 +94,8 @@ struct vpbe_config { > /* external encoder information goes here */ > int num_ext_encoders; > struct encoder_config_info *ext_encoders; > + /* amplifier information goes here */ > + struct amp_config_info *amp; > int num_outputs; > /* Order is venc outputs followed by LCD and then external encoders */ > struct vpbe_output *outputs; > @@ -158,6 +170,8 @@ struct vpbe_device { > struct v4l2_subdev **encoders; > /* current encoder index */ > int current_sd_index; > + /* external amplifier v4l2 subdevice */ > + struct v4l2_subdev *amp; > struct mutex lock; > /* device initialized */ > int initialized; > @@ -165,6 +179,8 @@ struct vpbe_device { > struct clk *dac_clk; > /* osd_device pointer */ > struct osd_state *osd_device; > + /* venc device pointer */ > + struct venc_platform_data *venc_device; > /* > * fields below are accessed by users of vpbe_device. Not the > * ones above > Regards, Hans -- 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