diff options
-rw-r--r-- | drivers/media/video/mxc/capture/ipu_csi_enc.c | 32 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/ipu_prp_enc.c | 32 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c | 30 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c | 32 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/ipu_still.c | 4 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mxc_v4l2_capture.c | 36 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mxc_v4l2_capture.h | 4 | ||||
-rw-r--r-- | drivers/mxc/ipu/ipu_common.c | 13 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_common.c | 83 | ||||
-rw-r--r-- | include/linux/ipu.h | 3 |
10 files changed, 245 insertions, 24 deletions
diff --git a/drivers/media/video/mxc/capture/ipu_csi_enc.c b/drivers/media/video/mxc/capture/ipu_csi_enc.c index fb3d0d7d5ec6..5818707a2458 100644 --- a/drivers/media/video/mxc/capture/ipu_csi_enc.c +++ b/drivers/media/video/mxc/capture/ipu_csi_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -205,6 +205,32 @@ static int csi_enc_disabling_tasks(void *private) } /*! + * Enable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int csi_enc_enable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_enable_csi(cam->csi); +} + +/*! + * Disable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int csi_enc_disable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_disable_csi(cam->csi); +} + +/*! * function to select CSI ENC as the working path * * @param private struct cam_data * mxc capture instance @@ -220,6 +246,8 @@ int csi_enc_select(void *private) cam->enc_update_eba = csi_enc_eba_update; cam->enc_enable = csi_enc_enabling_tasks; cam->enc_disable = csi_enc_disabling_tasks; + cam->enc_enable_csi = csi_enc_enable_csi; + cam->enc_disable_csi = csi_enc_disable_csi; } else { err = -EIO; } @@ -243,6 +271,8 @@ int csi_enc_deselect(void *private) cam->enc_update_eba = NULL; cam->enc_enable = NULL; cam->enc_disable = NULL; + cam->enc_enable_csi = NULL; + cam->enc_disable_csi = NULL; } return err; diff --git a/drivers/media/video/mxc/capture/ipu_prp_enc.c b/drivers/media/video/mxc/capture/ipu_prp_enc.c index 79eb8a615ee8..4b5426cb887d 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_enc.c +++ b/drivers/media/video/mxc/capture/ipu_prp_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -367,6 +367,32 @@ static int prp_enc_disabling_tasks(void *private) } /*! + * Enable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int prp_enc_enable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_enable_csi(cam->csi); +} + +/*! + * Disable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int prp_enc_disable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_disable_csi(cam->csi); +} + +/*! * function to select PRP-ENC as the working path * * @param private struct cam_data * mxc capture instance @@ -382,6 +408,8 @@ int prp_enc_select(void *private) cam->enc_update_eba = prp_enc_eba_update; cam->enc_enable = prp_enc_enabling_tasks; cam->enc_disable = prp_enc_disabling_tasks; + cam->enc_enable_csi = prp_enc_enable_csi; + cam->enc_disable_csi = prp_enc_disable_csi; } else { err = -EIO; } @@ -407,6 +435,8 @@ int prp_enc_deselect(void *private) cam->enc_update_eba = NULL; cam->enc_enable = NULL; cam->enc_disable = NULL; + cam->enc_enable_csi = NULL; + cam->enc_disable_csi = NULL; if (cam->rot_enc_bufs_vaddr[0]) { dma_free_coherent(0, cam->rot_enc_buf_size[0], cam->rot_enc_bufs_vaddr[0], diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c index 9994012a3176..882bacf923b1 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c +++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c @@ -365,6 +365,32 @@ static int prpvf_stop(void *private) } /*! + * Enable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int prp_vf_enable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_enable_csi(cam->csi); +} + +/*! + * Disable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int prp_vf_disable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_disable_csi(cam->csi); +} + +/*! * function to select PRP-VF as the working path * * @param private cam_data * mxc v4l2 main structure @@ -379,6 +405,8 @@ int prp_vf_sdc_select(void *private) cam = (cam_data *) private; cam->vf_start_sdc = prpvf_start; cam->vf_stop_sdc = prpvf_stop; + cam->vf_enable_csi = prp_vf_enable_csi; + cam->vf_disable_csi = prp_vf_disable_csi; cam->overlay_active = false; } else err = -EIO; @@ -403,6 +431,8 @@ int prp_vf_sdc_deselect(void *private) cam = (cam_data *) private; cam->vf_start_sdc = NULL; cam->vf_stop_sdc = NULL; + cam->vf_enable_csi = NULL; + cam->vf_disable_csi = NULL; } return err; } diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c index 4035c7664022..7f0984c42950 100644 --- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c +++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -344,6 +344,32 @@ static int prpvf_stop(void *private) } /*! + * Enable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int prp_vf_enable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_enable_csi(cam->csi); +} + +/*! + * Disable csi + * @param private struct cam_data * mxc capture instance + * + * @return status + */ +static int prp_vf_disable_csi(void *private) +{ + cam_data *cam = (cam_data *) private; + + return ipu_disable_csi(cam->csi); +} + +/*! * function to select PRP-VF as the working path * * @param private cam_data * mxc v4l2 main structure @@ -357,6 +383,8 @@ int prp_vf_sdc_select_bg(void *private) if (cam) { cam->vf_start_sdc = prpvf_start; cam->vf_stop_sdc = prpvf_stop; + cam->vf_enable_csi = prp_vf_enable_csi; + cam->vf_disable_csi = prp_vf_disable_csi; cam->overlay_active = false; } @@ -379,6 +407,8 @@ int prp_vf_sdc_deselect_bg(void *private) if (cam) { cam->vf_start_sdc = NULL; cam->vf_stop_sdc = NULL; + cam->vf_enable_csi = NULL; + cam->vf_disable_csi = NULL; } return err; } diff --git a/drivers/media/video/mxc/capture/ipu_still.c b/drivers/media/video/mxc/capture/ipu_still.c index c95e5244b85d..348bf2b9b564 100644 --- a/drivers/media/video/mxc/capture/ipu_still.c +++ b/drivers/media/video/mxc/capture/ipu_still.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -154,6 +154,7 @@ static int prp_still_start(void *private) ipu_select_buffer(CSI_MEM, IPU_OUTPUT_BUFFER, 0); ipu_enable_channel(CSI_MEM); + ipu_enable_csi(cam->csi); #endif return err; @@ -177,6 +178,7 @@ static int prp_still_stop(void *private) ipu_free_irq(IPU_IRQ_CSI0_OUT_EOF, cam); #endif + ipu_disable_csi(cam->csi); ipu_disable_channel(CSI_MEM, true); ipu_uninit_channel(CSI_MEM); ipu_csi_enable_mclk_if(CSI_MCLK_RAW, cam->csi, false, false); diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c index 62c190dd05c9..dd78b15aed4c 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -163,6 +163,8 @@ static video_fmt_idx video_index = TV_NOT_LOCKED; static int mxc_v4l2_master_attach(struct v4l2_int_device *slave); static void mxc_v4l2_master_detach(struct v4l2_int_device *slave); static u8 camera_power(cam_data *cam, bool cameraOn); +static int start_preview(cam_data *cam); +static int stop_preview(cam_data *cam); /*! Information about this driver. */ static struct v4l2_int_master mxc_v4l2_master = { @@ -345,6 +347,9 @@ static int mxc_streamon(cam_data *cam) cam->capture_pid = current->pid; + if (cam->overlay_on == true) + stop_preview(cam); + if (cam->enc_enable) { err = cam->enc_enable(cam); if (err != 0) { @@ -371,6 +376,15 @@ static int mxc_streamon(cam_data *cam) return -EINVAL; } + if (cam->overlay_on == true) + start_preview(cam); + + if (cam->enc_enable_csi) { + err = cam->enc_enable_csi(cam); + if (err != 0) + return err; + } + cam->capture_on = true; return err; @@ -392,9 +406,14 @@ static int mxc_streamoff(cam_data *cam) if (cam->capture_on == false) return 0; - if (cam->enc_disable) { - err = cam->enc_disable(cam); + if (cam->enc_disable_csi) { + err = cam->enc_disable_csi(cam); + if (err != 0) + return err; } + if (cam->enc_disable) + err = cam->enc_disable(cam); + mxc_free_frames(cam); mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER; cam->capture_on = false; @@ -531,6 +550,11 @@ static int start_preview(cam_data *cam) return err; err = cam->vf_start_sdc(cam); + if (err != 0) + return err; + + if (cam->vf_enable_csi) + err = cam->vf_enable_csi(cam); } #endif @@ -581,6 +605,12 @@ static int stop_preview(cam_data *cam) #endif #if defined(CONFIG_MXC_IPU_PRP_VF_SDC) || defined(CONFIG_MXC_IPU_PRP_VF_SDC_MODULE) + if (cam->vf_disable_csi) { + err = cam->vf_disable_csi(cam); + if (err != 0) + return err; + } + if (cam->output == 0 || cam->output == 2) { if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) err = prp_vf_sdc_deselect(cam); diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h index f12be977dedd..e5fd2e82b7a6 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h @@ -168,11 +168,15 @@ typedef struct _cam_data { int (*enc_update_eba) (dma_addr_t eba, int *bufferNum); int (*enc_enable) (void *private); int (*enc_disable) (void *private); + int (*enc_enable_csi) (void *private); + int (*enc_disable_csi) (void *private); void (*enc_callback) (u32 mask, void *dev); int (*vf_start_adc) (void *private); int (*vf_stop_adc) (void *private); int (*vf_start_sdc) (void *private); int (*vf_stop_sdc) (void *private); + int (*vf_enable_csi) (void *private); + int (*vf_disable_csi) (void *private); int (*csi_start) (void *private); int (*csi_stop) (void *private); diff --git a/drivers/mxc/ipu/ipu_common.c b/drivers/mxc/ipu/ipu_common.c index c748a3304967..43ba100b5c5d 100644 --- a/drivers/mxc/ipu/ipu_common.c +++ b/drivers/mxc/ipu/ipu_common.c @@ -1332,6 +1332,17 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) return 0; } +int32_t ipu_enable_csi(uint32_t csi) +{ + return 0; +} + + +int32_t ipu_disable_csi(uint32_t csi) +{ + return 0; +} + static irqreturn_t ipu_irq_handler(int irq, void *desc) { @@ -1915,6 +1926,8 @@ EXPORT_SYMBOL(ipu_select_buffer); EXPORT_SYMBOL(ipu_link_channels); EXPORT_SYMBOL(ipu_enable_channel); EXPORT_SYMBOL(ipu_disable_channel); +EXPORT_SYMBOL(ipu_enable_csi); +EXPORT_SYMBOL(ipu_disable_csi); EXPORT_SYMBOL(ipu_enable_irq); EXPORT_SYMBOL(ipu_disable_irq); EXPORT_SYMBOL(ipu_clear_irq); diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index f53a047a186a..0cb367bf38c6 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -513,7 +513,6 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params) } ipu_smfc_use_count++; - ipu_csi_use_count[params->csi_mem.csi]++; g_ipu_csi_channel[params->csi_mem.csi] = channel; /*SMFC setting*/ @@ -543,7 +542,6 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params) using_ic_dirct_ch = CSI_PRP_ENC_MEM; ipu_ic_use_count++; - ipu_csi_use_count[params->csi_prp_enc_mem.csi]++; g_ipu_csi_channel[params->csi_prp_enc_mem.csi] = channel; /*Without SMFC, CSI only support parallel data source*/ @@ -577,7 +575,6 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params) using_ic_dirct_ch = CSI_PRP_VF_MEM; ipu_ic_use_count++; - ipu_csi_use_count[params->csi_prp_vf_mem.csi]++; g_ipu_csi_channel[params->csi_prp_vf_mem.csi] = channel; /*Without SMFC, CSI only support parallel data source*/ @@ -758,10 +755,6 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params) } if (ipu_smfc_use_count == 1) ipu_conf |= IPU_CONF_SMFC_EN; - if (ipu_csi_use_count[0] == 1) - ipu_conf |= IPU_CONF_CSI0_EN; - if (ipu_csi_use_count[1] == 1) - ipu_conf |= IPU_CONF_CSI1_EN; __raw_writel(ipu_conf, IPU_CONF); @@ -823,10 +816,8 @@ void ipu_uninit_channel(ipu_channel_t channel) ipu_smfc_use_count--; if (g_ipu_csi_channel[0] == channel) { g_ipu_csi_channel[0] = CHAN_NONE; - ipu_csi_use_count[0]--; } else if (g_ipu_csi_channel[1] == channel) { g_ipu_csi_channel[1] = CHAN_NONE; - ipu_csi_use_count[1]--; } break; case CSI_PRP_ENC_MEM: @@ -836,10 +827,8 @@ void ipu_uninit_channel(ipu_channel_t channel) _ipu_ic_uninit_prpenc(); if (g_ipu_csi_channel[0] == channel) { g_ipu_csi_channel[0] = CHAN_NONE; - ipu_csi_use_count[0]--; } else if (g_ipu_csi_channel[1] == channel) { g_ipu_csi_channel[1] = CHAN_NONE; - ipu_csi_use_count[1]--; } break; case CSI_PRP_VF_MEM: @@ -849,10 +838,8 @@ void ipu_uninit_channel(ipu_channel_t channel) _ipu_ic_uninit_prpvf(); if (g_ipu_csi_channel[0] == channel) { g_ipu_csi_channel[0] = CHAN_NONE; - ipu_csi_use_count[0]--; } else if (g_ipu_csi_channel[1] == channel) { g_ipu_csi_channel[1] = CHAN_NONE; - ipu_csi_use_count[1]--; } break; case MEM_PRP_VF_MEM: @@ -954,10 +941,6 @@ void ipu_uninit_channel(ipu_channel_t channel) } if (ipu_smfc_use_count == 0) ipu_conf &= ~IPU_CONF_SMFC_EN; - if (ipu_csi_use_count[0] == 0) - ipu_conf &= ~IPU_CONF_CSI0_EN; - if (ipu_csi_use_count[1] == 0) - ipu_conf &= ~IPU_CONF_CSI1_EN; __raw_writel(ipu_conf, IPU_CONF); @@ -1947,6 +1930,72 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) } EXPORT_SYMBOL(ipu_disable_channel); +/*! + * This function enables CSI. + * + * @param csi csi num 0 or 1 + * + * @return This function returns 0 on success or negative error code on + * fail. + */ +int32_t ipu_enable_csi(uint32_t csi) +{ + uint32_t reg; + unsigned long lock_flags; + + if (csi > 1) { + dev_err(g_ipu_dev, "Wrong csi num_%d\n", csi); + return -EINVAL; + } + + spin_lock_irqsave(&ipu_lock, lock_flags); + ipu_csi_use_count[csi]++; + + if (ipu_csi_use_count[csi] == 1) { + reg = __raw_readl(IPU_CONF); + if (csi == 0) + __raw_writel(reg | IPU_CONF_CSI0_EN, IPU_CONF); + else + __raw_writel(reg | IPU_CONF_CSI1_EN, IPU_CONF); + } + spin_unlock_irqrestore(&ipu_lock, lock_flags); + return 0; +} +EXPORT_SYMBOL(ipu_enable_csi); + +/*! + * This function disables CSI. + * + * @param csi csi num 0 or 1 + * + * @return This function returns 0 on success or negative error code on + * fail. + */ +int32_t ipu_disable_csi(uint32_t csi) +{ + uint32_t reg; + unsigned long lock_flags; + + if (csi > 1) { + dev_err(g_ipu_dev, "Wrong csi num_%d\n", csi); + return -EINVAL; + } + + spin_lock_irqsave(&ipu_lock, lock_flags); + ipu_csi_use_count[csi]--; + + if (ipu_csi_use_count[csi] == 0) { + reg = __raw_readl(IPU_CONF); + if (csi == 0) + __raw_writel(reg & ~IPU_CONF_CSI0_EN, IPU_CONF); + else + __raw_writel(reg & ~IPU_CONF_CSI1_EN, IPU_CONF); + } + spin_unlock_irqrestore(&ipu_lock, lock_flags); + return 0; +} +EXPORT_SYMBOL(ipu_disable_csi); + static irqreturn_t ipu_irq_handler(int irq, void *desc) { int i; diff --git a/include/linux/ipu.h b/include/linux/ipu.h index fdb50eb89842..5a03856b1ac3 100644 --- a/include/linux/ipu.h +++ b/include/linux/ipu.h @@ -902,6 +902,9 @@ int32_t ipu_enable_channel(ipu_channel_t channel); int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop); int32_t ipu_swap_channel(ipu_channel_t from_ch, ipu_channel_t to_ch); +int32_t ipu_enable_csi(uint32_t csi); +int32_t ipu_disable_csi(uint32_t csi); + int ipu_lowpwr_display_enable(void); int ipu_lowpwr_display_disable(void); |