Merge branch 'topic/ipu-destaging' of git://git.pengutronix.de/git/pza/linux into drm-next

Destage IPUv3

* 'topic/ipu-destaging' of git://git.pengutronix.de/git/pza/linux:
  gpu: ipu-v3: Register the CSI modules
  gpu: ipu-v3: Add CSI and SMFC module enable wrappers
  gpu: ipu-v3: Add ipu_idmac_get_current_buffer function
  gpu: ipu-v3: Add SMFC code
  gpu: ipu-v3: Move i.MX IPUv3 core driver out of staging
This commit is contained in:
Dave Airlie 2014-06-11 10:13:58 +10:00
commit c1a6e9fe82
18 changed files with 215 additions and 28 deletions

View file

@ -1,2 +1,3 @@
obj-y += drm/ vga/ obj-y += drm/ vga/
obj-$(CONFIG_TEGRA_HOST1X) += host1x/ obj-$(CONFIG_TEGRA_HOST1X) += host1x/
obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/

View file

@ -0,0 +1,7 @@
config IMX_IPUV3_CORE
tristate "IPUv3 core support"
depends on SOC_IMX5 || SOC_IMX6Q || SOC_IMX6SL || ARCH_MULTIPLATFORM
depends on RESET_CONTROLLER
help
Choose this if you have a i.MX5/6 system and want to use the Image
Processing Unit. This option only enables IPU base support.

View file

@ -1,3 +1,3 @@
obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += imx-ipu-v3.o obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o ipu-smfc.o

View file

@ -31,7 +31,7 @@
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include "imx-ipu-v3.h" #include <video/imx-ipu-v3.h>
#include "ipu-prv.h" #include "ipu-prv.h"
static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset) static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
@ -661,6 +661,39 @@ int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
} }
EXPORT_SYMBOL_GPL(ipu_module_disable); EXPORT_SYMBOL_GPL(ipu_module_disable);
int ipu_csi_enable(struct ipu_soc *ipu, int csi)
{
return ipu_module_enable(ipu, csi ? IPU_CONF_CSI1_EN : IPU_CONF_CSI0_EN);
}
EXPORT_SYMBOL_GPL(ipu_csi_enable);
int ipu_csi_disable(struct ipu_soc *ipu, int csi)
{
return ipu_module_disable(ipu, csi ? IPU_CONF_CSI1_EN : IPU_CONF_CSI0_EN);
}
EXPORT_SYMBOL_GPL(ipu_csi_disable);
int ipu_smfc_enable(struct ipu_soc *ipu)
{
return ipu_module_enable(ipu, IPU_CONF_SMFC_EN);
}
EXPORT_SYMBOL_GPL(ipu_smfc_enable);
int ipu_smfc_disable(struct ipu_soc *ipu)
{
return ipu_module_disable(ipu, IPU_CONF_SMFC_EN);
}
EXPORT_SYMBOL_GPL(ipu_smfc_disable);
int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
{
struct ipu_soc *ipu = channel->ipu;
unsigned int chno = channel->num;
return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
}
EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num) void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
{ {
struct ipu_soc *ipu = channel->ipu; struct ipu_soc *ipu = channel->ipu;
@ -874,8 +907,17 @@ static int ipu_submodules_init(struct ipu_soc *ipu,
goto err_dp; goto err_dp;
} }
ret = ipu_smfc_init(ipu, dev, ipu_base +
devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
if (ret) {
unit = "smfc";
goto err_smfc;
}
return 0; return 0;
err_smfc:
ipu_dp_exit(ipu);
err_dp: err_dp:
ipu_dmfc_exit(ipu); ipu_dmfc_exit(ipu);
err_dmfc: err_dmfc:
@ -947,6 +989,7 @@ EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
static void ipu_submodules_exit(struct ipu_soc *ipu) static void ipu_submodules_exit(struct ipu_soc *ipu)
{ {
ipu_smfc_exit(ipu);
ipu_dp_exit(ipu); ipu_dp_exit(ipu);
ipu_dmfc_exit(ipu); ipu_dmfc_exit(ipu);
ipu_dc_exit(ipu); ipu_dc_exit(ipu);
@ -971,6 +1014,7 @@ static void platform_device_unregister_children(struct platform_device *pdev)
struct ipu_platform_reg { struct ipu_platform_reg {
struct ipu_client_platformdata pdata; struct ipu_client_platformdata pdata;
const char *name; const char *name;
int reg_offset;
}; };
static const struct ipu_platform_reg client_reg[] = { static const struct ipu_platform_reg client_reg[] = {
@ -992,13 +1036,29 @@ static const struct ipu_platform_reg client_reg[] = {
.dma[1] = -EINVAL, .dma[1] = -EINVAL,
}, },
.name = "imx-ipuv3-crtc", .name = "imx-ipuv3-crtc",
}, {
.pdata = {
.csi = 0,
.dma[0] = IPUV3_CHANNEL_CSI0,
.dma[1] = -EINVAL,
},
.reg_offset = IPU_CM_CSI0_REG_OFS,
.name = "imx-ipuv3-camera",
}, {
.pdata = {
.csi = 1,
.dma[0] = IPUV3_CHANNEL_CSI1,
.dma[1] = -EINVAL,
},
.reg_offset = IPU_CM_CSI1_REG_OFS,
.name = "imx-ipuv3-camera",
}, },
}; };
static DEFINE_MUTEX(ipu_client_id_mutex); static DEFINE_MUTEX(ipu_client_id_mutex);
static int ipu_client_id; static int ipu_client_id;
static int ipu_add_client_devices(struct ipu_soc *ipu) static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
{ {
struct device *dev = ipu->dev; struct device *dev = ipu->dev;
unsigned i; unsigned i;
@ -1012,9 +1072,19 @@ static int ipu_add_client_devices(struct ipu_soc *ipu)
for (i = 0; i < ARRAY_SIZE(client_reg); i++) { for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
const struct ipu_platform_reg *reg = &client_reg[i]; const struct ipu_platform_reg *reg = &client_reg[i];
struct platform_device *pdev; struct platform_device *pdev;
struct resource res;
pdev = platform_device_register_data(dev, reg->name, if (reg->reg_offset) {
id++, &reg->pdata, sizeof(reg->pdata)); memset(&res, 0, sizeof(res));
res.flags = IORESOURCE_MEM;
res.start = ipu_base + ipu->devtype->cm_ofs + reg->reg_offset;
res.end = res.start + PAGE_SIZE - 1;
pdev = platform_device_register_resndata(dev, reg->name,
id++, &res, 1, &reg->pdata, sizeof(reg->pdata));
} else {
pdev = platform_device_register_data(dev, reg->name,
id++, &reg->pdata, sizeof(reg->pdata));
}
if (IS_ERR(pdev)) if (IS_ERR(pdev))
goto err_register; goto err_register;
@ -1210,7 +1280,7 @@ static int ipu_probe(struct platform_device *pdev)
if (ret) if (ret)
goto failed_submodules_init; goto failed_submodules_init;
ret = ipu_add_client_devices(ipu); ret = ipu_add_client_devices(ipu, ipu_base);
if (ret) { if (ret) {
dev_err(&pdev->dev, "adding client devices failed with %d\n", dev_err(&pdev->dev, "adding client devices failed with %d\n",
ret); ret);

View file

@ -20,8 +20,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include "../imx-drm.h" #include <video/imx-ipu-v3.h>
#include "imx-ipu-v3.h"
#include "ipu-prv.h" #include "ipu-prv.h"
#define DC_MAP_CONF_PTR(n) (0x108 + ((n) & ~0x1) * 2) #define DC_MAP_CONF_PTR(n) (0x108 + ((n) & ~0x1) * 2)

View file

@ -20,7 +20,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "imx-ipu-v3.h" #include <video/imx-ipu-v3.h>
#include "ipu-prv.h" #include "ipu-prv.h"
struct ipu_di { struct ipu_di {

View file

@ -17,7 +17,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/io.h> #include <linux/io.h>
#include "imx-ipu-v3.h" #include <video/imx-ipu-v3.h>
#include "ipu-prv.h" #include "ipu-prv.h"
#define DMFC_RD_CHAN 0x0000 #define DMFC_RD_CHAN 0x0000

View file

@ -19,7 +19,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/err.h> #include <linux/err.h>
#include "imx-ipu-v3.h" #include <video/imx-ipu-v3.h>
#include "ipu-prv.h" #include "ipu-prv.h"
#define DP_SYNC 0 #define DP_SYNC 0

View file

@ -22,7 +22,7 @@ struct ipu_soc;
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "imx-ipu-v3.h" #include <video/imx-ipu-v3.h>
#define IPUV3_CHANNEL_CSI0 0 #define IPUV3_CHANNEL_CSI0 0
#define IPUV3_CHANNEL_CSI1 1 #define IPUV3_CHANNEL_CSI1 1
@ -151,6 +151,8 @@ struct ipuv3_channel {
struct ipu_dc_priv; struct ipu_dc_priv;
struct ipu_dmfc_priv; struct ipu_dmfc_priv;
struct ipu_di; struct ipu_di;
struct ipu_smfc_priv;
struct ipu_devtype; struct ipu_devtype;
struct ipu_soc { struct ipu_soc {
@ -178,6 +180,7 @@ struct ipu_soc {
struct ipu_dp_priv *dp_priv; struct ipu_dp_priv *dp_priv;
struct ipu_dmfc_priv *dmfc_priv; struct ipu_dmfc_priv *dmfc_priv;
struct ipu_di *di_priv[2]; struct ipu_di *di_priv[2];
struct ipu_smfc_priv *smfc_priv;
}; };
void ipu_srm_dp_sync_update(struct ipu_soc *ipu); void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
@ -203,4 +206,7 @@ void ipu_dc_exit(struct ipu_soc *ipu);
int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
void ipu_cpmem_exit(struct ipu_soc *ipu); void ipu_cpmem_exit(struct ipu_soc *ipu);
int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
void ipu_smfc_exit(struct ipu_soc *ipu);
#endif /* __IPU_PRV_H__ */ #endif /* __IPU_PRV_H__ */

View file

@ -0,0 +1,97 @@
/*
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#define DEBUG
#include <linux/export.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <video/imx-ipu-v3.h>
#include "ipu-prv.h"
struct ipu_smfc_priv {
void __iomem *base;
spinlock_t lock;
};
/*SMFC Registers */
#define SMFC_MAP 0x0000
#define SMFC_WMC 0x0004
#define SMFC_BS 0x0008
int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize)
{
struct ipu_smfc_priv *smfc = ipu->smfc_priv;
unsigned long flags;
u32 val, shift;
spin_lock_irqsave(&smfc->lock, flags);
shift = channel * 4;
val = readl(smfc->base + SMFC_BS);
val &= ~(0xf << shift);
val |= burstsize << shift;
writel(val, smfc->base + SMFC_BS);
spin_unlock_irqrestore(&smfc->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id)
{
struct ipu_smfc_priv *smfc = ipu->smfc_priv;
unsigned long flags;
u32 val, shift;
spin_lock_irqsave(&smfc->lock, flags);
shift = channel * 3;
val = readl(smfc->base + SMFC_MAP);
val &= ~(0x7 << shift);
val |= ((csi_id << 2) | mipi_id) << shift;
writel(val, smfc->base + SMFC_MAP);
spin_unlock_irqrestore(&smfc->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
unsigned long base)
{
struct ipu_smfc_priv *smfc;
smfc = devm_kzalloc(dev, sizeof(*smfc), GFP_KERNEL);
if (!smfc)
return -ENOMEM;
ipu->smfc_priv = smfc;
spin_lock_init(&smfc->lock);
smfc->base = devm_ioremap(dev, base, PAGE_SIZE);
if (!smfc->base)
return -ENOMEM;
pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, smfc->base);
return 0;
}
void ipu_smfc_exit(struct ipu_soc *ipu)
{
}

View file

@ -39,19 +39,10 @@ config DRM_IMX_LDB
Choose this to enable the internal LVDS Display Bridge (LDB) Choose this to enable the internal LVDS Display Bridge (LDB)
found on i.MX53 and i.MX6 processors. found on i.MX53 and i.MX6 processors.
config DRM_IMX_IPUV3_CORE
tristate "IPUv3 core support"
depends on DRM_IMX
depends on RESET_CONTROLLER
help
Choose this if you have a i.MX5/6 system and want
to use the IPU. This option only enables IPU base
support.
config DRM_IMX_IPUV3 config DRM_IMX_IPUV3
tristate "DRM Support for i.MX IPUv3" tristate "DRM Support for i.MX IPUv3"
depends on DRM_IMX depends on DRM_IMX
depends on DRM_IMX_IPUV3_CORE depends on IMX_IPUV3_CORE
help help
Choose this if you have a i.MX5 or i.MX6 processor. Choose this if you have a i.MX5 or i.MX6 processor.

View file

@ -6,7 +6,6 @@ obj-$(CONFIG_DRM_IMX) += imxdrm.o
obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o
obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o

View file

@ -27,8 +27,8 @@
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h> #include <drm/drm_encoder_slave.h>
#include <video/imx-ipu-v3.h>
#include "ipu-v3/imx-ipu-v3.h"
#include "imx-hdmi.h" #include "imx-hdmi.h"
#include "imx-drm.h" #include "imx-drm.h"

View file

@ -30,8 +30,8 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <video/imx-ipu-v3.h>
#include "ipu-v3/imx-ipu-v3.h"
#include "imx-drm.h" #include "imx-drm.h"
#define TVE_COM_CONF_REG 0x00 #define TVE_COM_CONF_REG 0x00

View file

@ -30,7 +30,7 @@
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include "ipu-v3/imx-ipu-v3.h" #include <video/imx-ipu-v3.h>
#include "imx-drm.h" #include "imx-drm.h"
#include "ipuv3-plane.h" #include "ipuv3-plane.h"

View file

@ -17,7 +17,7 @@
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include "ipu-v3/imx-ipu-v3.h" #include "video/imx-ipu-v3.h"
#include "ipuv3-plane.h" #include "ipuv3-plane.h"
#define to_ipu_plane(x) container_of(x, struct ipu_plane, base) #define to_ipu_plane(x) container_of(x, struct ipu_plane, base)

View file

@ -20,6 +20,7 @@ source "drivers/char/agp/Kconfig"
source "drivers/gpu/vga/Kconfig" source "drivers/gpu/vga/Kconfig"
source "drivers/gpu/host1x/Kconfig" source "drivers/gpu/host1x/Kconfig"
source "drivers/gpu/ipu-v3/Kconfig"
menu "Direct Rendering Manager" menu "Direct Rendering Manager"
source "drivers/gpu/drm/Kconfig" source "drivers/gpu/drm/Kconfig"

View file

@ -103,6 +103,7 @@ int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
bool doublebuffer); bool doublebuffer);
int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel);
void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num); void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
/* /*
@ -160,6 +161,20 @@ int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha, int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
bool bg_chan); bool bg_chan);
/*
* IPU CMOS Sensor Interface (csi) functions
*/
int ipu_csi_enable(struct ipu_soc *ipu, int csi);
int ipu_csi_disable(struct ipu_soc *ipu, int csi);
/*
* IPU Sensor Multiple FIFO Controller (SMFC) functions
*/
int ipu_smfc_enable(struct ipu_soc *ipu);
int ipu_smfc_disable(struct ipu_soc *ipu);
int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id);
int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize);
#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size)) #define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
#define IPU_FIELD_UBO IPU_CPMEM_WORD(0, 46, 22) #define IPU_FIELD_UBO IPU_CPMEM_WORD(0, 46, 22)
@ -316,6 +331,7 @@ static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p,
}; };
struct ipu_client_platformdata { struct ipu_client_platformdata {
int csi;
int di; int di;
int dc; int dc;
int dp; int dp;