ipu->ic_use_count++;
ipu->csi_channel[params->csi_prp_enc_mem.csi] = channel;
- /*Without SMFC, CSI only support parallel data source*/
- ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- params->csi_prp_enc_mem.csi));
+ if (params->csi_prp_enc_mem.mipi_en) {
+ ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_enc_mem.csi));
+ _ipu_csi_set_mipi_di(ipu,
+ params->csi_prp_enc_mem.mipi_vc,
+ params->csi_prp_enc_mem.mipi_id,
+ params->csi_prp_enc_mem.csi);
+ } else
+ ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_enc_mem.csi));
/*CSI0/1 feed into IC*/
ipu_conf &= ~IPU_CONF_IC_INPUT;
ipu->ic_use_count++;
ipu->csi_channel[params->csi_prp_vf_mem.csi] = channel;
- /*Without SMFC, CSI only support parallel data source*/
- ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
- params->csi_prp_vf_mem.csi));
+ if (params->csi_prp_vf_mem.mipi_en) {
+ ipu_conf |= (1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_vf_mem.csi));
+ _ipu_csi_set_mipi_di(ipu,
+ params->csi_prp_vf_mem.mipi_vc,
+ params->csi_prp_vf_mem.mipi_id,
+ params->csi_prp_vf_mem.csi);
+ } else
+ ipu_conf &= ~(1 << (IPU_CONF_CSI0_DATA_SOURCE_OFFSET +
+ params->csi_prp_vf_mem.csi));
/*CSI0/1 feed into IC*/
ipu_conf &= ~IPU_CONF_IC_INPUT;
*/
#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/console.h>
#include <linux/io.h>
#include <linux/bitops.h>
-#include <linux/ipu.h>
-#include <linux/mxcfb.h>
-#include <linux/regulator/consumer.h>
-#include <linux/backlight.h>
-#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/fsl_devices.h>
+#include <mach/devices-common.h>
#include <mach/hardware.h>
#include <mach/clock.h>
#include <mach/mipi_csi2.h>
static struct mipi_csi2_info *gmipi_csi2;
+void _mipi_csi2_lock(struct mipi_csi2_info *info)
+{
+ if (!in_irq() && !in_softirq())
+ mutex_lock(&info->mutex_lock);
+}
+
+void _mipi_csi2_unlock(struct mipi_csi2_info *info)
+{
+ if (!in_irq() && !in_softirq())
+ mutex_unlock(&info->mutex_lock);
+}
+
static inline void mipi_csi2_write(struct mipi_csi2_info *info, unsigned value, unsigned offset)
{
writel(value, info->mipi_csi2_base + offset);
return readl(info->mipi_csi2_base + offset);
}
+/*!
+ * This function is called to enable the mipi csi2 interface.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns setted value
+ */
+bool mipi_csi2_enable(struct mipi_csi2_info *info)
+{
+ bool status;
+
+ _mipi_csi2_lock(info);
+
+ if (!info->mipi_en) {
+ info->mipi_en = true;
+ clk_enable(info->dphy_clk);
+ } else
+ mipi_dbg("mipi csi2 already enabled!\n");
+
+ status = info->mipi_en;
+
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_enable);
+
+/*!
+ * This function is called to disable the mipi csi2 interface.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns setted value
+ */
+bool mipi_csi2_disable(struct mipi_csi2_info *info)
+{
+ bool status;
+
+ _mipi_csi2_lock(info);
+
+ if (info->mipi_en) {
+ info->mipi_en = false;
+ clk_disable(info->dphy_clk);
+ } else
+ mipi_dbg("mipi csi2 already disabled!\n");
+
+ status = info->mipi_en;
+
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_disable);
+
+/*!
+ * This function is called to get mipi csi2 disable/enable status.
+ *
+ * @param info mipi csi2 hander
+ * @return Returns mipi csi2 status
+ */
+bool mipi_csi2_get_status(struct mipi_csi2_info *info)
+{
+ bool status;
+
+ _mipi_csi2_lock(info);
+ status = info->mipi_en;
+ _mipi_csi2_unlock(info);
+
+ return status;
+}
+EXPORT_SYMBOL(mipi_csi2_get_status);
+
/*!
* This function is called to set mipi lanes.
*
*/
unsigned int mipi_csi2_set_lanes(struct mipi_csi2_info *info)
{
+ unsigned int lanes;
+
+ _mipi_csi2_lock(info);
mipi_csi2_write(info, info->lanes - 1, CSI2_N_LANES);
+ lanes = mipi_csi2_read(info, CSI2_N_LANES);
+ _mipi_csi2_unlock(info);
- return mipi_csi2_read(info, CSI2_N_LANES);
+ return lanes;
}
EXPORT_SYMBOL(mipi_csi2_set_lanes);
* @return Returns setted value
*/
unsigned int mipi_csi2_set_datatype(struct mipi_csi2_info *info,
- unsigned int datatype)
+ unsigned int datatype)
{
+ unsigned int dtype;
+
+ _mipi_csi2_lock(info);
info->datatype = datatype;
+ dtype = info->datatype;
+ _mipi_csi2_unlock(info);
- return info->datatype;
+ return dtype;
}
EXPORT_SYMBOL(mipi_csi2_set_datatype);
*/
unsigned int mipi_csi2_get_datatype(struct mipi_csi2_info *info)
{
- return info->datatype;
+ unsigned int dtype;
+
+ _mipi_csi2_lock(info);
+ dtype = info->datatype;
+ _mipi_csi2_unlock(info);
+
+ return dtype;
}
EXPORT_SYMBOL(mipi_csi2_get_datatype);
*/
unsigned int mipi_csi2_dphy_status(struct mipi_csi2_info *info)
{
- return mipi_csi2_read(info, CSI2_PHY_STATE);
+ unsigned int status;
+
+ _mipi_csi2_lock(info);
+ status = mipi_csi2_read(info, CSI2_PHY_STATE);
+ _mipi_csi2_unlock(info);
+
+ return status;
}
EXPORT_SYMBOL(mipi_csi2_dphy_status);
*/
unsigned int mipi_csi2_get_error1(struct mipi_csi2_info *info)
{
- return mipi_csi2_read(info, CSI2_ERR1);
+ unsigned int err1;
+
+ _mipi_csi2_lock(info);
+ err1 = mipi_csi2_read(info, CSI2_ERR1);
+ _mipi_csi2_unlock(info);
+
+ return err1;
}
EXPORT_SYMBOL(mipi_csi2_get_error1);
*/
unsigned int mipi_csi2_get_error2(struct mipi_csi2_info *info)
{
- return mipi_csi2_read(info, CSI2_ERR2);
+ unsigned int err2;
+
+ _mipi_csi2_lock(info);
+ err2 = mipi_csi2_read(info, CSI2_ERR2);
+ _mipi_csi2_unlock(info);
+
+ return err2;
}
EXPORT_SYMBOL(mipi_csi2_get_error2);
*/
int mipi_csi2_reset(struct mipi_csi2_info *info)
{
+ _mipi_csi2_lock(info);
+
mipi_csi2_write(info, 0x0, CSI2_PHY_SHUTDOWNZ);
mipi_csi2_write(info, 0x0, CSI2_DPHY_RSTZ);
mipi_csi2_write(info, 0x0, CSI2_RESETN);
mipi_csi2_write(info, 0xffffffff, CSI2_DPHY_RSTZ);
mipi_csi2_write(info, 0xffffffff, CSI2_RESETN);
+ _mipi_csi2_unlock(info);
+
return 0;
}
EXPORT_SYMBOL(mipi_csi2_reset);
*/
int mipi_csi2_get_bind_ipu(struct mipi_csi2_info *info)
{
- return info->ipu_id;
+ int ipu_id;
+
+ _mipi_csi2_lock(info);
+ ipu_id = info->ipu_id;
+ _mipi_csi2_unlock(info);
+
+ return ipu_id;
}
EXPORT_SYMBOL(mipi_csi2_get_bind_ipu);
*/
unsigned int mipi_csi2_get_bind_csi(struct mipi_csi2_info *info)
{
- return info->csi_id;
+ unsigned int csi_id;
+
+ _mipi_csi2_lock(info);
+ csi_id = info->csi_id;
+ _mipi_csi2_unlock(info);
+
+ return csi_id;
}
EXPORT_SYMBOL(mipi_csi2_get_bind_csi);
*/
unsigned int mipi_csi2_get_virtual_channel(struct mipi_csi2_info *info)
{
- return info->v_channel;
+ unsigned int v_channel;
+
+ _mipi_csi2_lock(info);
+ v_channel = info->v_channel;
+ _mipi_csi2_unlock(info);
+
+ return v_channel;
}
EXPORT_SYMBOL(mipi_csi2_get_virtual_channel);
goto alloc_failed;
}
+ /* initialize mutex */
+ mutex_init(&gmipi_csi2->mutex_lock);
+
/* get mipi csi2 informaiton */
gmipi_csi2->pdev = pdev;
+ gmipi_csi2->mipi_en = false;
gmipi_csi2->ipu_id = plat_data->ipu_id;
gmipi_csi2->csi_id = plat_data->csi_id;
gmipi_csi2->v_channel = plat_data->v_channel;
/* get mipi csi2 dphy version */
mipi_csi2_dphy_ver = mipi_csi2_read(gmipi_csi2, CSI2_VERSION);
+ clk_disable(gmipi_csi2->dphy_clk);
+
platform_set_drvdata(pdev, gmipi_csi2);
dev_info(&pdev->dev, "i.MX MIPI CSI2 driver probed\n");
iounmap(gmipi_csi2->mipi_csi2_base);
/* disable mipi dphy clk */
- clk_disable(gmipi_csi2->dphy_clk);
clk_put(gmipi_csi2->dphy_clk);
clk_put(gmipi_csi2->pixel_clk);
platform_driver_unregister(&mipi_csi2_driver);
}
-module_init(mipi_csi2_init);
+subsys_initcall(mipi_csi2_init);
module_exit(mipi_csi2_cleanup);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");