diff options
Diffstat (limited to 'drivers/media/platform/davinci')
-rw-r--r-- | drivers/media/platform/davinci/vpbe.c | 136 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_display.c | 80 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpbe_venc.c | 25 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpfe_capture.c | 17 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_capture.c | 370 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_capture.h | 16 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_display.c | 275 | ||||
-rw-r--r-- | drivers/media/platform/davinci/vpif_display.h | 18 |
8 files changed, 485 insertions, 452 deletions
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c index c4a82a1a8a97..69d7a58c92c3 100644 --- a/drivers/media/platform/davinci/vpbe.c +++ b/drivers/media/platform/davinci/vpbe.c @@ -174,26 +174,6 @@ static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev, return 0; } -static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev, - unsigned int dv_preset) -{ - struct vpbe_config *cfg = vpbe_dev->cfg; - struct vpbe_enc_mode_info var; - int curr_output = vpbe_dev->current_out_index; - int i; - - for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) { - var = cfg->outputs[curr_output].modes[i]; - if ((var.timings_type & VPBE_ENC_DV_PRESET) && - (var.timings.dv_preset == dv_preset)) { - vpbe_dev->current_timings = var; - return 0; - } - } - - return -EINVAL; -} - /* Get std by std id */ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev, v4l2_std_id std_id) @@ -206,7 +186,7 @@ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev, for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) { var = cfg->outputs[curr_output].modes[i]; if ((var.timings_type & VPBE_ENC_STD) && - (var.timings.std_id & std_id)) { + (var.std_id & std_id)) { vpbe_dev->current_timings = var; return 0; } @@ -344,38 +324,42 @@ static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev) } /** - * vpbe_s_dv_preset - Set the given preset timings in the encoder + * vpbe_s_dv_timings - Set the given preset timings in the encoder * - * Sets the preset if supported by the current encoder. Return the status. + * Sets the timings if supported by the current encoder. Return the status. * 0 - success & -EINVAL on error */ -static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev, - struct v4l2_dv_preset *dv_preset) +static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev, + struct v4l2_dv_timings *dv_timings) { struct vpbe_config *cfg = vpbe_dev->cfg; int out_index = vpbe_dev->current_out_index; + struct vpbe_output *output = &cfg->outputs[out_index]; int sd_index = vpbe_dev->current_sd_index; - int ret; + int ret, i; if (!(cfg->outputs[out_index].output.capabilities & - V4L2_OUT_CAP_PRESETS)) + V4L2_OUT_CAP_DV_TIMINGS)) return -EINVAL; - ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset); - - if (ret) - return ret; - + for (i = 0; i < output->num_modes; i++) { + if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS && + !memcmp(&output->modes[i].dv_timings, + dv_timings, sizeof(*dv_timings))) + break; + } + if (i >= output->num_modes) + return -EINVAL; + vpbe_dev->current_timings = output->modes[i]; mutex_lock(&vpbe_dev->lock); - ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video, - s_dv_preset, dv_preset); + s_dv_timings, dv_timings); if (!ret && (vpbe_dev->amp != NULL)) { /* Call amplifier subdevice */ ret = v4l2_subdev_call(vpbe_dev->amp, video, - s_dv_preset, dv_preset); + s_dv_timings, dv_timings); } /* set the lcd controller output for the given mode */ if (!ret) { @@ -392,17 +376,17 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev, } /** - * vpbe_g_dv_preset - Get the preset in the current encoder + * vpbe_g_dv_timings - Get the timings in the current encoder * - * Get the preset in the current encoder. Return the status. 0 - success + * Get the timings in the current encoder. Return the status. 0 - success * -EINVAL on error */ -static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev, - struct v4l2_dv_preset *dv_preset) +static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev, + struct v4l2_dv_timings *dv_timings) { if (vpbe_dev->current_timings.timings_type & - VPBE_ENC_DV_PRESET) { - dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset; + VPBE_ENC_CUSTOM_TIMINGS) { + *dv_timings = vpbe_dev->current_timings.dv_timings; return 0; } @@ -410,13 +394,13 @@ static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev, } /** - * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder + * vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder * - * Get the preset in the current encoder. Return the status. 0 - success + * Get the timings in the current encoder. Return the status. 0 - success * -EINVAL on error */ -static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev, - struct v4l2_dv_enum_preset *preset_info) +static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev, + struct v4l2_enum_dv_timings *timings) { struct vpbe_config *cfg = vpbe_dev->cfg; int out_index = vpbe_dev->current_out_index; @@ -424,12 +408,12 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev, int j = 0; int i; - if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS)) + if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS)) return -EINVAL; for (i = 0; i < output->num_modes; i++) { - if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) { - if (j == preset_info->index) + if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) { + if (j == timings->index) break; j++; } @@ -437,9 +421,8 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev, if (i == output->num_modes) return -EINVAL; - - return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset, - preset_info); + timings->timings = output->modes[i].dv_timings; + return 0; } /** @@ -489,10 +472,10 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id) */ static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id) { - struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings; + struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings; - if (cur_timings.timings_type & VPBE_ENC_STD) { - *std_id = cur_timings.timings.std_id; + if (cur_timings->timings_type & VPBE_ENC_STD) { + *std_id = cur_timings->std_id; return 0; } @@ -511,7 +494,7 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev, { struct vpbe_enc_mode_info *preset_mode = NULL; struct vpbe_config *cfg = vpbe_dev->cfg; - struct v4l2_dv_preset dv_preset; + struct v4l2_dv_timings dv_timings; struct osd_state *osd_device; int out_index = vpbe_dev->current_out_index; int ret = 0; @@ -530,11 +513,12 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev, */ if (preset_mode->timings_type & VPBE_ENC_STD) return vpbe_s_std(vpbe_dev, - &preset_mode->timings.std_id); - if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) { - dv_preset.preset = - preset_mode->timings.dv_preset; - return vpbe_s_dv_preset(vpbe_dev, &dv_preset); + &preset_mode->std_id); + if (preset_mode->timings_type & + VPBE_ENC_CUSTOM_TIMINGS) { + dv_timings = + preset_mode->dv_timings; + return vpbe_s_dv_timings(vpbe_dev, &dv_timings); } } } @@ -626,11 +610,11 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac"); if (IS_ERR(vpbe_dev->dac_clk)) { ret = PTR_ERR(vpbe_dev->dac_clk); - goto vpbe_unlock; + goto fail_mutex_unlock; } if (clk_enable(vpbe_dev->dac_clk)) { ret = -ENODEV; - goto vpbe_unlock; + goto fail_mutex_unlock; } } @@ -642,7 +626,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) if (ret) { v4l2_err(dev->driver, "Unable to register v4l2 device.\n"); - goto vpbe_fail_clock; + goto fail_clk_put; } v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n"); @@ -658,7 +642,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) v4l2_err(&vpbe_dev->v4l2_dev, "vpbe unable to init venc sub device\n"); ret = -ENODEV; - goto vpbe_fail_v4l2_device; + goto fail_dev_unregister; } /* initialize osd device */ osd_device = vpbe_dev->osd_device; @@ -669,7 +653,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) v4l2_err(&vpbe_dev->v4l2_dev, "unable to initialize the OSD device"); err = -ENOMEM; - goto vpbe_fail_v4l2_device; + goto fail_dev_unregister; } } @@ -685,7 +669,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) v4l2_err(&vpbe_dev->v4l2_dev, "unable to allocate memory for encoders sub devices"); ret = -ENOMEM; - goto vpbe_fail_v4l2_device; + goto fail_dev_unregister; } i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id); @@ -711,7 +695,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) " failed to register", enc_info->module_name); ret = -ENODEV; - goto vpbe_fail_sd_register; + goto fail_kfree_encoders; } } else v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders" @@ -730,7 +714,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) "amplifier %s failed to register", amp_info->module_name); ret = -ENODEV; - goto vpbe_fail_amp_register; + goto fail_kfree_encoders; } v4l2_info(&vpbe_dev->v4l2_dev, "v4l2 sub device %s registered\n", @@ -770,16 +754,14 @@ 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: +fail_kfree_encoders: kfree(vpbe_dev->encoders); -vpbe_fail_v4l2_device: +fail_dev_unregister: v4l2_device_unregister(&vpbe_dev->v4l2_dev); -vpbe_fail_clock: +fail_clk_put: if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) clk_put(vpbe_dev->dac_clk); -vpbe_unlock: +fail_mutex_unlock: mutex_unlock(&vpbe_dev->lock); return ret; } @@ -810,9 +792,9 @@ static struct vpbe_device_ops vpbe_dev_ops = { .enum_outputs = vpbe_enum_outputs, .set_output = vpbe_set_output, .get_output = vpbe_get_output, - .s_dv_preset = vpbe_s_dv_preset, - .g_dv_preset = vpbe_g_dv_preset, - .enum_dv_presets = vpbe_enum_dv_presets, + .s_dv_timings = vpbe_s_dv_timings, + .g_dv_timings = vpbe_g_dv_timings, + .enum_dv_timings = vpbe_enum_dv_timings, .s_std = vpbe_s_std, .g_std = vpbe_g_std, .initialize = vpbe_initialize, diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 239f37bfa313..161c77650e2f 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -393,7 +393,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev, int h_scale; int v_scale; - v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id; + v4l2_std_id standard_id = vpbe_dev->current_timings.std_id; /* * Application initially set the image format. Current display @@ -637,7 +637,7 @@ static int vpbe_display_s_crop(struct file *file, void *priv, struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev; struct osd_layer_config *cfg = &layer->layer_info.config; struct osd_state *osd_device = disp_dev->osd_device; - struct v4l2_rect *rect = &crop->c; + struct v4l2_rect rect = crop->c; int ret; v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, @@ -648,21 +648,21 @@ static int vpbe_display_s_crop(struct file *file, void *priv, return -EINVAL; } - if (rect->top < 0) - rect->top = 0; - if (rect->left < 0) - rect->left = 0; + if (rect.top < 0) + rect.top = 0; + if (rect.left < 0) + rect.left = 0; - vpbe_disp_check_window_params(disp_dev, rect); + vpbe_disp_check_window_params(disp_dev, &rect); osd_device->ops.get_layer_config(osd_device, layer->layer_info.id, cfg); vpbe_disp_calculate_scale_factor(disp_dev, layer, - rect->width, - rect->height); - vpbe_disp_adj_position(disp_dev, layer, rect->top, - rect->left); + rect.width, + rect.height); + vpbe_disp_adj_position(disp_dev, layer, rect.top, + rect.left); ret = osd_device->ops.set_layer_config(osd_device, layer->layer_info.id, cfg); if (ret < 0) { @@ -943,7 +943,7 @@ static int vpbe_display_g_std(struct file *file, void *priv, /* Get the standard from the current encoder */ if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) { - *std_id = vpbe_dev->current_timings.timings.std_id; + *std_id = vpbe_dev->current_timings.std_id; return 0; } @@ -1029,29 +1029,29 @@ static int vpbe_display_g_output(struct file *file, void *priv, } /** - * vpbe_display_enum_dv_presets - Enumerate the dv presets + * vpbe_display_enum_dv_timings - Enumerate the dv timings * - * enum the preset in the current encoder. Return the status. 0 - success + * enum the timings in the current encoder. Return the status. 0 - success * -EINVAL on error */ static int -vpbe_display_enum_dv_presets(struct file *file, void *priv, - struct v4l2_dv_enum_preset *preset) +vpbe_display_enum_dv_timings(struct file *file, void *priv, + struct v4l2_enum_dv_timings *timings) { struct vpbe_fh *fh = priv; struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; int ret; - v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n"); + v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n"); /* Enumerate outputs */ - if (NULL == vpbe_dev->ops.enum_dv_presets) + if (NULL == vpbe_dev->ops.enum_dv_timings) return -EINVAL; - ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset); + ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings); if (ret) { v4l2_err(&vpbe_dev->v4l2_dev, - "Failed to enumerate dv presets info\n"); + "Failed to enumerate dv timings info\n"); return -EINVAL; } @@ -1059,21 +1059,21 @@ vpbe_display_enum_dv_presets(struct file *file, void *priv, } /** - * vpbe_display_s_dv_preset - Set the dv presets + * vpbe_display_s_dv_timings - Set the dv timings * - * Set the preset in the current encoder. Return the status. 0 - success + * Set the timings in the current encoder. Return the status. 0 - success * -EINVAL on error */ static int -vpbe_display_s_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *preset) +vpbe_display_s_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) { struct vpbe_fh *fh = priv; struct vpbe_layer *layer = fh->layer; struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; int ret; - v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n"); + v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n"); /* If streaming is started, return error */ @@ -1083,13 +1083,13 @@ vpbe_display_s_dv_preset(struct file *file, void *priv, } /* Set the given standard in the encoder */ - if (!vpbe_dev->ops.s_dv_preset) + if (!vpbe_dev->ops.s_dv_timings) return -EINVAL; - ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset); + ret = vpbe_dev->ops.s_dv_timings(vpbe_dev, timings); if (ret) { v4l2_err(&vpbe_dev->v4l2_dev, - "Failed to set the dv presets info\n"); + "Failed to set the dv timings info\n"); return -EINVAL; } /* set the current norm to zero to be consistent. If STD is used @@ -1101,26 +1101,25 @@ vpbe_display_s_dv_preset(struct file *file, void *priv, } /** - * vpbe_display_g_dv_preset - Set the dv presets + * vpbe_display_g_dv_timings - Set the dv timings * - * Get the preset in the current encoder. Return the status. 0 - success + * Get the timings in the current encoder. Return the status. 0 - success * -EINVAL on error */ static int -vpbe_display_g_dv_preset(struct file *file, void *priv, - struct v4l2_dv_preset *dv_preset) +vpbe_display_g_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *dv_timings) { struct vpbe_fh *fh = priv; struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; - v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n"); + v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n"); /* Get the given standard in the encoder */ if (vpbe_dev->current_timings.timings_type & - VPBE_ENC_DV_PRESET) { - dv_preset->preset = - vpbe_dev->current_timings.timings.dv_preset; + VPBE_ENC_CUSTOM_TIMINGS) { + *dv_timings = vpbe_dev->current_timings.dv_timings; } else { return -EINVAL; } @@ -1572,9 +1571,9 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { .vidioc_enum_output = vpbe_display_enum_output, .vidioc_s_output = vpbe_display_s_output, .vidioc_g_output = vpbe_display_g_output, - .vidioc_s_dv_preset = vpbe_display_s_dv_preset, - .vidioc_g_dv_preset = vpbe_display_g_dv_preset, - .vidioc_enum_dv_presets = vpbe_display_enum_dv_presets, + .vidioc_s_dv_timings = vpbe_display_s_dv_timings, + .vidioc_g_dv_timings = vpbe_display_g_dv_timings, + .vidioc_enum_dv_timings = vpbe_display_enum_dv_timings, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vpbe_display_g_register, .vidioc_s_register = vpbe_display_s_register, @@ -1639,8 +1638,7 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev, VPBE_ENC_STD) { vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50); vbd->current_norm = - disp_dev->vpbe_dev-> - current_timings.timings.std_id; + disp_dev->vpbe_dev->current_timings.std_id; } else vbd->current_norm = 0; diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 0302669622d6..aed7369b962a 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c @@ -298,7 +298,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd) return -EINVAL; /* Setup clock at VPSS & VENC for SD */ - if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0) + if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0) return -EINVAL; venc_enabledigitaloutput(sd, 0); @@ -345,7 +345,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd) (pdata->venc_type != VPBE_VERSION_2)) return -EINVAL; /* Setup clock at VPSS & VENC for SD */ - if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0) + if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0) return -EINVAL; venc_enabledigitaloutput(sd, 0); @@ -385,7 +385,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd) struct venc_state *venc = to_state(sd); struct venc_platform_data *pdata = venc->pdata; - if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0) + if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0) return -EINVAL; venc_enabledigitaloutput(sd, 0); @@ -413,7 +413,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd) struct venc_state *venc = to_state(sd); struct venc_platform_data *pdata = venc->pdata; - if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0) + if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0) return -EINVAL; venc_enabledigitaloutput(sd, 0); @@ -446,26 +446,27 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) return -EINVAL; } -static int venc_s_dv_preset(struct v4l2_subdev *sd, - struct v4l2_dv_preset *dv_preset) +static int venc_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *dv_timings) { struct venc_state *venc = to_state(sd); + u32 height = dv_timings->bt.height; int ret; - v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n"); + v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n"); - if (dv_preset->preset == V4L2_DV_576P50) + if (height == 576) return venc_set_576p50(sd); - else if (dv_preset->preset == V4L2_DV_480P59_94) + else if (height == 480) return venc_set_480p59_94(sd); - else if ((dv_preset->preset == V4L2_DV_720P60) && + else if ((height == 720) && (venc->pdata->venc_type == VPBE_VERSION_2)) { /* TBD setup internal 720p mode here */ ret = venc_set_720p60_internal(sd); /* for DM365 VPBE, there is DAC inside */ vdaccfg_write(sd, VDAC_CONFIG_HD_V2); return ret; - } else if ((dv_preset->preset == V4L2_DV_1080I30) && + } else if ((height == 1080) && (venc->pdata->venc_type == VPBE_VERSION_2)) { /* TBD setup internal 1080i mode here */ ret = venc_set_1080i30_internal(sd); @@ -518,7 +519,7 @@ static const struct v4l2_subdev_core_ops venc_core_ops = { static const struct v4l2_subdev_video_ops venc_video_ops = { .s_routing = venc_s_routing, .s_std_output = venc_s_std_output, - .s_dv_preset = venc_s_dv_preset, + .s_dv_timings = venc_s_dv_timings, }; static const struct v4l2_subdev_ops venc_ops = { diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 48052cbffc2b..8be492cd8ed4 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -1669,6 +1669,7 @@ static int vpfe_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) { struct vpfe_device *vpfe_dev = video_drvdata(file); + struct v4l2_rect rect = crop->c; int ret = 0; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n"); @@ -1684,7 +1685,7 @@ static int vpfe_s_crop(struct file *file, void *priv, if (ret) return ret; - if (crop->c.top < 0 || crop->c.left < 0) { + if (rect.top < 0 || rect.left < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "doesn't support negative values for top & left\n"); ret = -EINVAL; @@ -1692,26 +1693,26 @@ static int vpfe_s_crop(struct file *file, void *priv, } /* adjust the width to 16 pixel boundary */ - crop->c.width = ((crop->c.width + 15) & ~0xf); + rect.width = ((rect.width + 15) & ~0xf); /* make sure parameters are valid */ - if ((crop->c.left + crop->c.width > + if ((rect.left + rect.width > vpfe_dev->std_info.active_pixels) || - (crop->c.top + crop->c.height > + (rect.top + rect.height > vpfe_dev->std_info.active_lines)) { v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n"); ret = -EINVAL; goto unlock_out; } - ccdc_dev->hw_ops.set_image_window(&crop->c); - vpfe_dev->fmt.fmt.pix.width = crop->c.width; - vpfe_dev->fmt.fmt.pix.height = crop->c.height; + ccdc_dev->hw_ops.set_image_window(&rect); + vpfe_dev->fmt.fmt.pix.width = rect.width; + vpfe_dev->fmt.fmt.pix.height = rect.height; vpfe_dev->fmt.fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length(); vpfe_dev->fmt.fmt.pix.sizeimage = vpfe_dev->fmt.fmt.pix.bytesperline * vpfe_dev->fmt.fmt.pix.height; - vpfe_dev->crop = crop->c; + vpfe_dev->crop = rect; unlock_out: mutex_unlock(&vpfe_dev->lock); return ret; diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 0bafecac4923..fcabc023885d 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -311,12 +311,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) } /* configure 1 or 2 channel mode */ - ret = vpif_config_data->setup_input_channel_mode - (vpif->std_info.ycmux_mode); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set vpif channel mode\n"); - return ret; + if (vpif_config_data->setup_input_channel_mode) { + ret = vpif_config_data-> + setup_input_channel_mode(vpif->std_info.ycmux_mode); + if (ret < 0) { + vpif_dbg(1, debug, "can't set vpif channel mode\n"); + return ret; + } } /* Call vpif_set_params function to set the parameters and addresses */ @@ -863,13 +864,11 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait) */ static int vpif_open(struct file *filep) { - struct vpif_capture_config *config = vpif_dev->platform_data; struct video_device *vdev = video_devdata(filep); struct common_obj *common; struct video_obj *vid_ch; struct channel_obj *ch; struct vpif_fh *fh; - int i; vpif_dbg(2, debug, "vpif_open\n"); @@ -878,26 +877,6 @@ static int vpif_open(struct file *filep) vid_ch = &ch->video; common = &ch->common[VPIF_VIDEO_INDEX]; - if (NULL == ch->curr_subdev_info) { - /** - * search through the sub device to see a registered - * sub device and make it as current sub device - */ - for (i = 0; i < config->subdev_count; i++) { - if (vpif_obj.sd[i]) { - /* the sub device is registered */ - ch->curr_subdev_info = &config->subdev_info[i]; - /* make first input as the current input */ - vid_ch->input_idx = 0; - break; - } - } - if (i == config->subdev_count) { - vpif_err("No sub device registered\n"); - return -ENOENT; - } - } - /* Allocate memory for the file handle object */ fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); if (NULL == fh) { @@ -997,6 +976,7 @@ static int vpif_reqbufs(struct file *file, void *priv, struct common_obj *common; u8 index = 0; struct vb2_queue *q; + int ret; vpif_dbg(2, debug, "vpif_reqbufs\n"); @@ -1036,8 +1016,12 @@ static int vpif_reqbufs(struct file *file, void *priv, q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct vpif_cap_buffer); - vb2_queue_init(q); - + ret = vb2_queue_init(q); + if (ret) { + vpif_err("vpif_capture: vb2_queue_init() failed\n"); + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); + return ret; + } /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; /* Increment io usrs member of channel object to 1 */ @@ -1175,10 +1159,9 @@ static int vpif_streamon(struct file *file, void *priv, return ret; /* Enable streamon on the sub device */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, - s_stream, 1); + ret = v4l2_subdev_call(ch->sd, video, s_stream, 1); - if (ret && (ret != -ENOIOCTLCMD)) { + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { vpif_dbg(1, debug, "stream on failed in subdev\n"); return ret; } @@ -1238,73 +1221,105 @@ static int vpif_streamoff(struct file *file, void *priv, common->started = 0; - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, - s_stream, 0); + ret = v4l2_subdev_call(ch->sd, video, s_stream, 0); - if (ret && (ret != -ENOIOCTLCMD)) + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) vpif_dbg(1, debug, "stream off failed in subdev\n"); return vb2_streamoff(&common->buffer_queue, buftype); } /** - * vpif_map_sub_device_to_input() - Maps sub device to input - * @ch - ptr to channel - * @config - ptr to capture configuration + * vpif_input_to_subdev() - Maps input to sub device + * @vpif_cfg - global config ptr + * @chan_cfg - channel config ptr * @input_index - Given input index from application - * @sub_device_index - index into sd table * * lookup the sub device information for a given input index. * we report all the inputs to application. inputs table also * has sub device name for the each input */ -static struct vpif_subdev_info *vpif_map_sub_device_to_input( - struct channel_obj *ch, - struct vpif_capture_config *vpif_cfg, - int input_index, - int *sub_device_index) +static int vpif_input_to_subdev( + struct vpif_capture_config *vpif_cfg, + struct vpif_capture_chan_config *chan_cfg, + int input_index) { - struct vpif_capture_chan_config *chan_cfg; - struct vpif_subdev_info *subdev_info = NULL; - const char *subdev_name = NULL; + struct vpif_subdev_info *subdev_info; + const char *subdev_name; int i; - vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n"); + vpif_dbg(2, debug, "vpif_input_to_subdev\n"); - chan_cfg = &vpif_cfg->chan_config[ch->channel_id]; - - /** - * search through the inputs to find the sub device supporting - * the input - */ - for (i = 0; i < chan_cfg->input_count; i++) { - /* For each sub device, loop through input */ - if (i == input_index) { - subdev_name = chan_cfg->inputs[i].subdev_name; - break; - } - } - - /* if reached maximum. return null */ - if (i == chan_cfg->input_count || (NULL == subdev_name)) - return subdev_info; + subdev_name = chan_cfg->inputs[input_index].subdev_name; + if (subdev_name == NULL) + return -1; /* loop through the sub device list to get the sub device info */ for (i = 0; i < vpif_cfg->subdev_count; i++) { subdev_info = &vpif_cfg->subdev_info[i]; if (!strcmp(subdev_info->name, subdev_name)) - break; + return i; + } + return -1; +} + +/** + * vpif_set_input() - Select an input + * @vpif_cfg - global config ptr + * @ch - channel + * @_index - Given input index from application + * + * Select the given input. + */ +static int vpif_set_input( + struct vpif_capture_config *vpif_cfg, + struct channel_obj *ch, + int index) +{ + struct vpif_capture_chan_config *chan_cfg = + &vpif_cfg->chan_config[ch->channel_id]; + struct vpif_subdev_info *subdev_info = NULL; + struct v4l2_subdev *sd = NULL; + u32 input = 0, output = 0; + int sd_index; + int ret; + + sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index); + if (sd_index >= 0) { + sd = vpif_obj.sd[sd_index]; + subdev_info = &vpif_cfg->subdev_info[sd_index]; } - if (i == vpif_cfg->subdev_count) - return subdev_info; + /* first setup input path from sub device to vpif */ + if (sd && vpif_cfg->setup_input_path) { + ret = vpif_cfg->setup_input_path(ch->channel_id, + subdev_info->name); + if (ret < 0) { + vpif_dbg(1, debug, "couldn't setup input path for the" \ + " sub device %s, for input index %d\n", + subdev_info->name, index); + return ret; + } + } - /* check if the sub device is registered */ - if (NULL == vpif_obj.sd[i]) - return NULL; + if (sd) { + input = chan_cfg->inputs[index].input_route; + output = chan_cfg->inputs[index].output_route; + ret = v4l2_subdev_call(sd, video, s_routing, + input, output, 0); + if (ret < 0 && ret != -ENOIOCTLCMD) { + vpif_dbg(1, debug, "Failed to set input\n"); + return ret; + } + } + ch->input_idx = index; + ch->sd = sd; + /* copy interface parameters to vpif */ + ch->vpifparams.iface = chan_cfg->vpif_if; - *sub_device_index = i; - return subdev_info; + /* update tvnorms from the sub device input info */ + ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; + return 0; } /** @@ -1324,12 +1339,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) vpif_dbg(2, debug, "vpif_querystd\n"); /* Call querystd function of decoder device */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, - querystd, std_id); - if (ret < 0) - vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); + ret = v4l2_subdev_call(ch->sd, video, querystd, std_id); - return ret; + if (ret == -ENOIOCTLCMD || ret == -ENODEV) + return -ENODATA; + if (ret) { + vpif_dbg(1, debug, "Failed to query standard for sub devices\n"); + return ret; + } + + return 0; } /** @@ -1397,11 +1416,12 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) vpif_config_format(ch); /* set standard in the sub device */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, - s_std, *std_id); - if (ret < 0) + ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id); + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) { vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); - return ret; + return ret; + } + return 0; } /** @@ -1441,10 +1461,8 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - - *index = vid_ch->input_idx; + *index = ch->input_idx; return 0; } @@ -1461,13 +1479,13 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct video_obj *vid_ch = &ch->video; - struct vpif_subdev_info *subdev_info; - int ret = 0, sd_index = 0; - u32 input = 0, output = 0; + int ret; chan_cfg = &config->chan_config[ch->channel_id]; + if (index >= chan_cfg->input_count) + return -EINVAL; + if (common->started) { vpif_err("Streaming in progress\n"); return -EBUSY; @@ -1486,45 +1504,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) return ret; fh->initialized = 1; - subdev_info = vpif_map_sub_device_to_input(ch, config, index, - &sd_index); - if (NULL == subdev_info) { - vpif_dbg(1, debug, - "couldn't lookup sub device for the input index\n"); - return -EINVAL; - } - - /* first setup input path from sub device to vpif */ - if (config->setup_input_path) { - ret = config->setup_input_path(ch->channel_id, - subdev_info->name); - if (ret < 0) { - vpif_dbg(1, debug, "couldn't setup input path for the" - " sub device %s, for input index %d\n", - subdev_info->name, index); - return ret; - } - } - - if (subdev_info->can_route) { - input = subdev_info->input; - output = subdev_info->output; - ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing, - input, output, 0); - if (ret < 0) { - vpif_dbg(1, debug, "Failed to set input\n"); - return ret; - } - } - vid_ch->input_idx = index; - ch->curr_subdev_info = subdev_info; - ch->curr_sd_index = sd_index; - /* copy interface parameters to vpif */ - ch->vpifparams.iface = subdev_info->vpif_if; - - /* update tvnorms from the sub device input info */ - ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; - return ret; + return vpif_set_input(config, ch, index); } /** @@ -1655,9 +1635,11 @@ static int vpif_querycap(struct file *file, void *priv, { struct vpif_capture_config *config = vpif_dev->platform_data; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - strlcpy(cap->driver, "vpif capture", sizeof(cap->driver)); - strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", + dev_name(vpif_dev)); strlcpy(cap->card, config->card_name, sizeof(cap->card)); return 0; @@ -1730,9 +1712,12 @@ vpif_enum_dv_timings(struct file *file, void *priv, { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; + int ret; - return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], - video, enum_dv_timings, timings); + ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); + if (ret == -ENOIOCTLCMD && ret == -ENODEV) + return -EINVAL; + return ret; } /** @@ -1747,9 +1732,12 @@ vpif_query_dv_timings(struct file *file, void *priv, { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; + int ret; - return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], - video, query_dv_timings, timings); + ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings); + if (ret == -ENOIOCTLCMD && ret == -ENODEV) + return -ENODATA; + return ret; } /** @@ -1775,13 +1763,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv, } /* Configure subdevice timings, if any */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], - video, s_dv_timings, timings); - if (ret == -ENOIOCTLCMD) { - vpif_dbg(2, debug, "Custom DV timings not supported by " - "subdevice\n"); - return -EINVAL; - } + ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); + if (ret == -ENOIOCTLCMD || ret == -ENODEV) + ret = 0; if (ret < 0) { vpif_dbg(2, debug, "Error setting custom DV timings\n"); return ret; @@ -1906,8 +1890,7 @@ static int vpif_dbg_g_register(struct file *file, void *priv, struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, - g_register, reg); + return v4l2_subdev_call(ch->sd, core, g_register, reg); } /* @@ -1924,8 +1907,7 @@ static int vpif_dbg_s_register(struct file *file, void *priv, struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, - s_register, reg); + return v4l2_subdev_call(ch->sd, core, s_register, reg); } #endif @@ -2063,7 +2045,8 @@ static __init int vpif_probe(struct platform_device *pdev) { struct vpif_subdev_info *subdevdata; struct vpif_capture_config *config; - int i, j, k, m, q, err; + int i, j, k, err; + int res_idx = 0; struct i2c_adapter *i2c_adap; struct channel_obj *ch; struct common_obj *common; @@ -2086,18 +2069,19 @@ static __init int vpif_probe(struct platform_device *pdev) return err; } - k = 0; - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { + while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { for (i = res->start; i <= res->end; i++) { if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Capture", - (void *)(&vpif_obj.dev[k]->channel_id))) { + "VPIF_Capture", (void *) + (&vpif_obj.dev[res_idx]->channel_id))) { err = -EBUSY; - i--; + for (j = 0; j < i; j++) + free_irq(j, (void *) + (&vpif_obj.dev[res_idx]->channel_id)); goto vpif_int_err; } } - k++; + res_idx++; } for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { @@ -2111,7 +2095,7 @@ static __init int vpif_probe(struct platform_device *pdev) video_device_release(ch->video_dev); } err = -ENOMEM; - goto vpif_dev_alloc_err; + goto vpif_int_err; } /* Initialize field of video device */ @@ -2142,24 +2126,6 @@ static __init int vpif_probe(struct platform_device *pdev) } } - for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { - ch = vpif_obj.dev[j]; - ch->channel_id = j; - common = &(ch->common[VPIF_VIDEO_INDEX]); - spin_lock_init(&common->irqlock); - mutex_init(&common->lock); - ch->video_dev->lock = &common->lock; - /* Initialize prio member of channel object */ - v4l2_prio_init(&ch->prio); - err = video_register_device(ch->video_dev, - VFL_TYPE_GRABBER, (j ? 1 : 0)); - if (err) - goto probe_out; - - video_set_drvdata(ch->video_dev, ch); - - } - i2c_adap = i2c_get_adapter(1); config = pdev->dev.platform_data; @@ -2169,7 +2135,7 @@ static __init int vpif_probe(struct platform_device *pdev) if (vpif_obj.sd == NULL) { vpif_err("unable to allocate memory for subdevice pointers\n"); err = -ENOMEM; - goto probe_out; + goto vpif_sd_error; } for (i = 0; i < subdev_count; i++) { @@ -2186,19 +2152,32 @@ static __init int vpif_probe(struct platform_device *pdev) } v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", subdevdata->name); - - if (vpif_obj.sd[i]) - vpif_obj.sd[i]->grp_id = 1 << i; } + for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { + ch = vpif_obj.dev[j]; + ch->channel_id = j; + common = &(ch->common[VPIF_VIDEO_INDEX]); + spin_lock_init(&common->irqlock); + mutex_init(&common->lock); + ch->video_dev->lock = &common->lock; + /* Initialize prio member of channel object */ + v4l2_prio_init(&ch->prio); + video_set_drvdata(ch->video_dev, ch); + + /* select input 0 */ + err = vpif_set_input(config, ch, 0); + if (err) + goto probe_out; + + err = video_register_device(ch->video_dev, + VFL_TYPE_GRABBER, (j ? 1 : 0)); + if (err) + goto probe_out; + } v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n"); return 0; -probe_subdev_out: - /* free sub devices memory */ - kfree(vpif_obj.sd); - - j = VPIF_CAPTURE_MAX_DEVICES; probe_out: for (k = 0; k < j; k++) { /* Get the pointer to the channel object */ @@ -2206,22 +2185,23 @@ probe_out: /* Unregister video device */ video_unregister_device(ch->video_dev); } +probe_subdev_out: + /* free sub devices memory */ + kfree(vpif_obj.sd); -vpif_dev_alloc_err: - k = VPIF_CAPTURE_MAX_DEVICES-1; - res = platform_get_resource(pdev, IORESOURCE_IRQ, k); - i = res->end; - -vpif_int_err: - for (q = k; q >= 0; q--) { - for (m = i; m >= (int)res->start; m--) - free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id)); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1); - if (res) - i = res->end; +vpif_sd_error: + for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { + ch = vpif_obj.dev[i]; + /* Note: does nothing if ch->video_dev == NULL */ + video_device_release(ch->video_dev); } +vpif_int_err: v4l2_device_unregister(&vpif_obj.v4l2_dev); + for (i = 0; i < res_idx; i++) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + for (j = res->start; j <= res->end; j++) + free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); + } return err; } diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index d24efc17e4c8..3d3c1e5cd5d4 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -54,8 +54,6 @@ struct video_obj { /* Currently selected or default standard */ v4l2_std_id stdid; struct v4l2_dv_timings dv_timings; - /* This is to track the last input that is passed to application */ - u32 input_idx; }; struct vpif_cap_buffer { @@ -119,10 +117,10 @@ struct channel_obj { u8 initialized; /* Identifies channel */ enum vpif_channel_id channel_id; - /* index into sd table */ - int curr_sd_index; - /* ptr to current sub device information */ - struct vpif_subdev_info *curr_subdev_info; + /* Current input */ + u32 input_idx; + /* subdev corresponding to the current input, may be NULL */ + struct v4l2_subdev *sd; /* vpif configuration params */ struct vpif_params vpifparams; /* common object array */ @@ -159,10 +157,6 @@ struct vpif_config_params { u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS]; u8 max_device_type; }; -/* Struct which keeps track of the line numbers for the sliced vbi service */ -struct vpif_service_line { - u16 service_id; - u16 service_line[2]; -}; + #endif /* End of __KERNEL__ */ #endif /* VPIF_CAPTURE_H */ diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index a5b88689abad..b716fbd4241f 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -280,12 +280,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) } /* clock settings */ - ret = - vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, - ch->vpifparams.std_info.hd_sd); - if (ret < 0) { - vpif_err("can't set clock\n"); - return ret; + if (vpif_config_data->set_clock) { + ret = vpif_config_data->set_clock(ch->vpifparams.std_info. + ycmux_mode, ch->vpifparams.std_info.hd_sd); + if (ret < 0) { + vpif_err("can't set clock\n"); + return ret; + } } /* set the parameters and addresses */ @@ -307,7 +308,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) channel2_intr_assert(); channel2_intr_enable(1); enable_channel2(1); - if (vpif_config_data->ch2_clip_en) + if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en) channel2_clipping_enable(1); } @@ -316,7 +317,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) channel3_intr_assert(); channel3_intr_enable(1); enable_channel3(1); - if (vpif_config_data->ch3_clip_en) + if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en) channel3_clipping_enable(1); } @@ -826,9 +827,11 @@ static int vpif_querycap(struct file *file, void *priv, { struct vpif_display_config *config = vpif_dev->platform_data; - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - strlcpy(cap->driver, "vpif display", sizeof(cap->driver)); - strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", + dev_name(vpif_dev)); strlcpy(cap->card, config->card_name, sizeof(cap->card)); return 0; @@ -935,6 +938,7 @@ static int vpif_reqbufs(struct file *file, void *priv, enum v4l2_field field; struct vb2_queue *q; u8 index = 0; + int ret; /* This file handle has not initialized the channel, It is not allowed to do settings */ @@ -980,8 +984,12 @@ static int vpif_reqbufs(struct file *file, void *priv, q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct vpif_disp_buffer); - vb2_queue_init(q); - + ret = vb2_queue_init(q); + if (ret) { + vpif_err("vpif_display: vb2_queue_init() failed\n"); + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); + return ret; + } /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; /* Increment io usrs member of channel object to 1 */ @@ -1173,14 +1181,16 @@ static int vpif_streamoff(struct file *file, void *priv, if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* disable channel */ if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { - if (vpif_config_data->ch2_clip_en) + if (vpif_config_data-> + chan_config[VPIF_CHANNEL2_VIDEO].clip_en) channel2_clipping_enable(0); enable_channel2(0); channel2_intr_enable(0); } if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || (2 == common->started)) { - if (vpif_config_data->ch3_clip_en) + if (vpif_config_data-> + chan_config[VPIF_CHANNEL3_VIDEO].clip_en) channel3_clipping_enable(0); enable_channel3(0); channel3_intr_enable(0); @@ -1213,49 +1223,126 @@ static int vpif_enum_output(struct file *file, void *fh, { struct vpif_display_config *config = vpif_dev->platform_data; + struct vpif_display_chan_config *chan_cfg; + struct vpif_fh *vpif_handler = fh; + struct channel_obj *ch = vpif_handler->channel; - if (output->index >= config->output_count) { + chan_cfg = &config->chan_config[ch->channel_id]; + if (output->index >= chan_cfg->output_count) { vpif_dbg(1, debug, "Invalid output index\n"); return -EINVAL; } - strcpy(output->name, config->output[output->index]); - output->type = V4L2_OUTPUT_TYPE_ANALOG; - output->std = VPIF_V4L2_STD; + *output = chan_cfg->outputs[output->index].output; + return 0; +} + +/** + * vpif_output_to_subdev() - Maps output to sub device + * @vpif_cfg - global config ptr + * @chan_cfg - channel config ptr + * @index - Given output index from application + * + * lookup the sub device information for a given output index. + * we report all the output to application. output table also + * has sub device name for the each output + */ +static int +vpif_output_to_subdev(struct vpif_display_config *vpif_cfg, + struct vpif_display_chan_config *chan_cfg, int index) +{ + struct vpif_subdev_info *subdev_info; + const char *subdev_name; + int i; + + vpif_dbg(2, debug, "vpif_output_to_subdev\n"); + + if (chan_cfg->outputs == NULL) + return -1; + + subdev_name = chan_cfg->outputs[index].subdev_name; + if (subdev_name == NULL) + return -1; + + /* loop through the sub device list to get the sub device info */ + for (i = 0; i < vpif_cfg->subdev_count; i++) { + subdev_info = &vpif_cfg->subdevinfo[i]; + if (!strcmp(subdev_info->name, subdev_name)) + return i; + } + return -1; +} + +/** + * vpif_set_output() - Select an output + * @vpif_cfg - global config ptr + * @ch - channel + * @index - Given output index from application + * + * Select the given output. + */ +static int vpif_set_output(struct vpif_display_config *vpif_cfg, + struct channel_obj *ch, int index) +{ + struct vpif_display_chan_config *chan_cfg = + &vpif_cfg->chan_config[ch->channel_id]; + struct vpif_subdev_info *subdev_info = NULL; + struct v4l2_subdev *sd = NULL; + u32 input = 0, output = 0; + int sd_index; + int ret; + + sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index); + if (sd_index >= 0) { + sd = vpif_obj.sd[sd_index]; + subdev_info = &vpif_cfg->subdevinfo[sd_index]; + } + + if (sd) { + input = chan_cfg->outputs[index].input_route; + output = chan_cfg->outputs[index].output_route; + ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0); + if (ret < 0 && ret != -ENOIOCTLCMD) { + vpif_err("Failed to set output\n"); + return ret; + } + } + ch->output_idx = index; + ch->sd = sd; + if (chan_cfg->outputs != NULL) + /* update tvnorms from the sub device output info */ + ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std; return 0; } static int vpif_s_output(struct file *file, void *priv, unsigned int i) { + struct vpif_display_config *config = vpif_dev->platform_data; + struct vpif_display_chan_config *chan_cfg; struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; + + chan_cfg = &config->chan_config[ch->channel_id]; + + if (i >= chan_cfg->output_count) + return -EINVAL; if (common->started) { vpif_err("Streaming in progress\n"); return -EBUSY; } - ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, - s_routing, 0, i, 0); - - if (ret < 0) - vpif_err("Failed to set output standard\n"); - - vid_ch->output_id = i; - return ret; + return vpif_set_output(config, ch, i); } static int vpif_g_output(struct file *file, void *priv, unsigned int *i) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - *i = vid_ch->output_id; + *i = ch->output_idx; return 0; } @@ -1290,10 +1377,12 @@ vpif_enum_dv_timings(struct file *file, void *priv, { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; + int ret; - return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], - video, enum_dv_timings, timings); + ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings); + if (ret == -ENOIOCTLCMD && ret == -ENODEV) + return -EINVAL; + return ret; } /** @@ -1319,13 +1408,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv, } /* Configure subdevice timings, if any */ - ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], - video, s_dv_timings, timings); - if (ret == -ENOIOCTLCMD) { - vpif_dbg(2, debug, "Custom DV timings not supported by " - "subdevice\n"); - return -EINVAL; - } + ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings); + if (ret == -ENOIOCTLCMD || ret == -ENODEV) + ret = 0; if (ret < 0) { vpif_dbg(2, debug, "Error setting custom DV timings\n"); return ret; @@ -1450,10 +1535,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg){ struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core, - g_register, reg); + return v4l2_subdev_call(ch->sd, core, g_register, reg); } /* @@ -1469,10 +1552,8 @@ static int vpif_dbg_s_register(struct file *file, void *priv, struct v4l2_dbg_register *reg){ struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core, - s_register, reg); + return v4l2_subdev_call(ch->sd, core, s_register, reg); } #endif @@ -1536,9 +1617,6 @@ static struct video_device vpif_video_template = { .name = "vpif", .fops = &vpif_fops, .ioctl_ops = &vpif_ioctl_ops, - .tvnorms = VPIF_V4L2_STD, - .current_norm = V4L2_STD_625_50, - }; /*Configure the channels, buffer sizei, request irq */ @@ -1611,7 +1689,8 @@ static __init int vpif_probe(struct platform_device *pdev) { struct vpif_subdev_info *subdevdata; struct vpif_display_config *config; - int i, j = 0, k, q, m, err = 0; + int i, j = 0, k, err = 0; + int res_idx = 0; struct i2c_adapter *i2c_adap; struct common_obj *common; struct channel_obj *ch; @@ -1634,21 +1713,22 @@ static __init int vpif_probe(struct platform_device *pdev) return err; } - k = 0; - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { + while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { for (i = res->start; i <= res->end; i++) { if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Display", - (void *)(&vpif_obj.dev[k]->channel_id))) { + "VPIF_Display", (void *) + (&vpif_obj.dev[res_idx]->channel_id))) { err = -EBUSY; + for (j = 0; j < i; j++) + free_irq(j, (void *) + (&vpif_obj.dev[res_idx]->channel_id)); goto vpif_int_err; } } - k++; + res_idx++; } for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { - /* Get the pointer to the channel object */ ch = vpif_obj.dev[i]; @@ -1694,6 +1774,32 @@ static __init int vpif_probe(struct platform_device *pdev) } } + i2c_adap = i2c_get_adapter(1); + config = pdev->dev.platform_data; + subdev_count = config->subdev_count; + subdevdata = config->subdevinfo; + vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, + GFP_KERNEL); + if (vpif_obj.sd == NULL) { + vpif_err("unable to allocate memory for subdevice pointers\n"); + err = -ENOMEM; + goto vpif_sd_error; + } + + for (i = 0; i < subdev_count; i++) { + vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, + i2c_adap, + &subdevdata[i].board_info, + NULL); + if (!vpif_obj.sd[i]) { + vpif_err("Error registering v4l2 subdevice\n"); + goto probe_subdev_out; + } + + if (vpif_obj.sd[i]) + vpif_obj.sd[i]->grp_id = 1 << i; + } + for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { ch = vpif_obj.dev[j]; /* Initialize field of the channel objects */ @@ -1715,6 +1821,8 @@ static __init int vpif_probe(struct platform_device *pdev) } ch->initialized = 0; + if (subdev_count) + ch->sd = vpif_obj.sd[0]; ch->channel_id = j; if (j < 2) ch->common[VPIF_VIDEO_INDEX].numbuffers = @@ -1729,6 +1837,12 @@ static __init int vpif_probe(struct platform_device *pdev) ch->common[VPIF_VIDEO_INDEX].fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ch->video_dev->lock = &common->lock; + video_set_drvdata(ch->video_dev, ch); + + /* select output 0 */ + err = vpif_set_output(config, ch, 0); + if (err) + goto probe_out; /* register video device */ vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", @@ -1738,42 +1852,12 @@ static __init int vpif_probe(struct platform_device *pdev) VFL_TYPE_GRABBER, (j ? 3 : 2)); if (err < 0) goto probe_out; - - video_set_drvdata(ch->video_dev, ch); - } - - i2c_adap = i2c_get_adapter(1); - config = pdev->dev.platform_data; - subdev_count = config->subdev_count; - subdevdata = config->subdevinfo; - vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, - GFP_KERNEL); - if (vpif_obj.sd == NULL) { - vpif_err("unable to allocate memory for subdevice pointers\n"); - err = -ENOMEM; - goto probe_out; - } - - for (i = 0; i < subdev_count; i++) { - vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, - i2c_adap, - &subdevdata[i].board_info, - NULL); - if (!vpif_obj.sd[i]) { - vpif_err("Error registering v4l2 subdevice\n"); - goto probe_subdev_out; - } - - if (vpif_obj.sd[i]) - vpif_obj.sd[i]->grp_id = 1 << i; } v4l2_info(&vpif_obj.v4l2_dev, " VPIF display driver initialized\n"); return 0; -probe_subdev_out: - kfree(vpif_obj.sd); probe_out: for (k = 0; k < j; k++) { ch = vpif_obj.dev[k]; @@ -1781,14 +1865,21 @@ probe_out: video_device_release(ch->video_dev); ch->video_dev = NULL; } +probe_subdev_out: + kfree(vpif_obj.sd); +vpif_sd_error: + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { + ch = vpif_obj.dev[i]; + /* Note: does nothing if ch->video_dev == NULL */ + video_device_release(ch->video_dev); + } vpif_int_err: v4l2_device_unregister(&vpif_obj.v4l2_dev); vpif_err("VPIF IRQ request failed\n"); - for (q = k; k >= 0; k--) { - for (m = i; m >= res->start; m--) - free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id)); - res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1); - m = res->end; + for (i = 0; i < res_idx; i++) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + for (j = res->start; j <= res->end; j++) + free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); } return err; diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index f628ebcf3674..a5a18f74395c 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h @@ -62,13 +62,6 @@ struct video_obj { v4l2_std_id stdid; /* Currently selected or default * standard */ struct v4l2_dv_timings dv_timings; - u32 output_id; /* Current output id */ -}; - -struct vbi_obj { - int num_services; - struct vpif_vbi_params vbiparams; /* vpif parameters for the raw - * vbi data */ }; struct vpif_disp_buffer { @@ -131,12 +124,13 @@ struct channel_obj { * which is being displayed */ u8 initialized; /* flag to indicate whether * encoder is initialized */ + u32 output_idx; /* Current output index */ + struct v4l2_subdev *sd; /* Current output subdev(may be NULL) */ enum vpif_channel_id channel_id;/* Identifies channel */ struct vpif_params vpifparams; struct common_obj common[VPIF_NUMOBJECTS]; struct video_obj video; - struct vbi_obj vbi; }; /* File handle structure */ @@ -168,12 +162,4 @@ struct vpif_config_params { u8 min_numbuffers; }; -/* Struct which keeps track of the line numbers for the sliced vbi service */ -struct vpif_service_line { - u16 service_id; - u16 service_line[2]; - u16 enc_service_id; - u8 bytestowrite; -}; - #endif /* DAVINCIHD_DISPLAY_H */ |