mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Juergen Beisert <jbe@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 07/12] Adapt the existing imx-ipu fb driver to support runtime videomode selection
Date: Tue, 26 Oct 2010 13:31:43 +0200	[thread overview]
Message-ID: <1288092708-5187-8-git-send-email-jbe@pengutronix.de> (raw)
In-Reply-To: <1288092708-5187-1-git-send-email-jbe@pengutronix.de>

Adapt the API to the new framebuffer videomode selection at runtime. If the new
feature is not used, there is no visible change at runtime for platforms using
this driver.

NOTE: Due to the lack of hardware, this is compile time tested only.

This is patch 5 of 7 to keep the repository bisectable.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
 arch/arm/boards/freescale-mx35-3-stack/3stack.c |    2 +-
 arch/arm/boards/pcm043/pcm043.c                 |    2 +-
 arch/arm/mach-imx/include/mach/imx-ipu-fb.h     |   12 +-
 drivers/video/imx-ipu-fb.c                      |  216 +++++++++++++----------
 4 files changed, 124 insertions(+), 108 deletions(-)

diff --git a/arch/arm/boards/freescale-mx35-3-stack/3stack.c b/arch/arm/boards/freescale-mx35-3-stack/3stack.c
index d6699cd..fb40f50 100644
--- a/arch/arm/boards/freescale-mx35-3-stack/3stack.c
+++ b/arch/arm/boards/freescale-mx35-3-stack/3stack.c
@@ -139,7 +139,7 @@ static struct fb_videomode CTP_CLAA070LC0ACW = {
 	.lower_margin	= 10,	/* whole frame should have 500 lines */
 	.hsync_len	= 1,	/* note: DE only display */
 	.vsync_len	= 1,	/* note: DE only display */
-	.sync		= FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
+	.sync		= FB_SYNC_CLK_IDLE_EN | FB_SYNC_DE_HIGH_ACT,
 	.vmode		= FB_VMODE_NONINTERLACED,
 	.flag		= 0,
 };
diff --git a/arch/arm/boards/pcm043/pcm043.c b/arch/arm/boards/pcm043/pcm043.c
index 5932f95..7e63cc5 100644
--- a/arch/arm/boards/pcm043/pcm043.c
+++ b/arch/arm/boards/pcm043/pcm043.c
@@ -124,7 +124,7 @@ static struct fb_videomode pcm043_fb_mode = {
 	.lower_margin	= 40,
 	.hsync_len	= 96,
 	.vsync_len	= 1,
-	.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+	.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_DE_HIGH_ACT,
 	.vmode		= FB_VMODE_NONINTERLACED,
 	.flag		= 0,
 };
diff --git a/arch/arm/mach-imx/include/mach/imx-ipu-fb.h b/arch/arm/mach-imx/include/mach/imx-ipu-fb.h
index 8e1cc87..ce95243 100644
--- a/arch/arm/mach-imx/include/mach/imx-ipu-fb.h
+++ b/arch/arm/mach-imx/include/mach/imx-ipu-fb.h
@@ -12,20 +12,12 @@
 
 #include <fb.h>
 
-/* Proprietary FB_SYNC_ flags */
-#define FB_SYNC_OE_ACT_HIGH	0x80000000
-#define FB_SYNC_CLK_INVERT	0x40000000
-#define FB_SYNC_DATA_INVERT	0x20000000
-#define FB_SYNC_CLK_IDLE_EN	0x10000000
-#define FB_SYNC_SHARP_MODE	0x08000000
-#define FB_SYNC_SWAP_RGB	0x04000000
-#define FB_SYNC_CLK_SEL_EN	0x02000000
-
 /*
- * struct mx3fb_platform_data - mx3fb platform data
+ * struct imx_ipu_fb_platform_data - imx-ipu-fb's platform data
  */
 struct imx_ipu_fb_platform_data {
 	struct fb_videomode	*mode;
+	unsigned mode_cnt;	/**< number of entries in 'mode' */
 	unsigned char		bpp;
 	void __iomem		*framebuffer;
 	/** hook to enable backlight and stuff */
diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c
index c38082d..45399cb 100644
--- a/drivers/video/imx-ipu-fb.c
+++ b/drivers/video/imx-ipu-fb.c
@@ -34,12 +34,12 @@
 #include <mach/clock.h>
 
 struct ipu_fb_info {
+	struct  fb_host		fb_host;	/**< myself */
 	void __iomem		*regs;
 
 	void			(*enable)(int enable);
 
-	struct fb_info		info;
-	struct device_d		*dev;
+	const struct fb_videomode *mode;	/**< requested videomodue */
 };
 
 /* IPU DMA Controller channel definitions. */
@@ -413,29 +413,30 @@ static inline void reg_write(struct ipu_fb_info *fbi, u32 value,
 	writel(value, fbi->regs + reg);
 }
 
+#define fb_info_to_imxfb_info(x) ((struct ipu_fb_info*)((x)->host))
+
 /*
  * sdc_init_panel() - initialize a synchronous LCD panel.
- * @width:		width of panel in pixels.
- * @height:		height of panel in pixels.
- * @pixel_fmt:		pixel format of buffer as FOURCC ASCII code.
+ * @param info The framebuffer to work on
+ * @param pixel_fmt pixel format of buffer as FOURCC ASCII code.
  * @return:		0 on success or negative error code on failure.
  */
-static int sdc_init_panel(struct fb_info *info, enum pixel_fmt pixel_fmt)
+static int sdc_init_panel(struct fb_info *fb_info, enum pixel_fmt pixel_fmt)
 {
-	struct ipu_fb_info *fbi = info->priv;
-	struct fb_videomode *mode = info->mode;
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
+	const struct fb_videomode *mode = fbi->mode;
 	u32 reg, old_conf, div;
 	enum ipu_panel panel = IPU_PANEL_TFT;
 	unsigned long pixel_clk;
 
 	/* Init panel size and blanking periods */
 	reg = ((mode->hsync_len - 1) << 26) |
-		((info->xres + mode->left_margin + mode->right_margin +
+		((mode->xres + mode->left_margin + mode->right_margin +
 		  mode->hsync_len - 1) << 16);
 	reg_write(fbi, reg, SDC_HOR_CONF);
 
 	reg = ((mode->vsync_len - 1) << 26) | SDC_V_SYNC_WIDTH_L |
-		((info->yres + mode->upper_margin + mode->lower_margin +
+		((mode->yres + mode->upper_margin + mode->lower_margin +
 		  mode->vsync_len - 1) << 16);
 	reg_write(fbi, reg, SDC_VER_CONF);
 
@@ -448,7 +449,7 @@ static int sdc_init_panel(struct fb_info *info, enum pixel_fmt pixel_fmt)
 		old_conf |= DI_D3_CLK_POL;
 	if (mode->sync & FB_SYNC_DATA_INVERT)
 		old_conf |= DI_D3_DATA_POL;
-	if (mode->sync & FB_SYNC_OE_ACT_HIGH)
+	if (mode->sync & FB_SYNC_DE_HIGH_ACT)
 		old_conf |= DI_D3_DRDY_SHARP_POL;
 	reg_write(fbi, old_conf, DI_DISP_SIG_POL);
 
@@ -483,12 +484,12 @@ static int sdc_init_panel(struct fb_info *info, enum pixel_fmt pixel_fmt)
 	div = imx_get_lcdclk() * 16 / pixel_clk;
 
 	if (div < 0x40) {	/* Divider less than 4 */
-		dev_dbg(&info->dev,
+		dev_dbg(fbi->fb_host.hw_dev,
 			"InitPanel() - Pixel clock divider less than 4\n");
 		div = 0x40;
 	}
 
-	dev_dbg(&info->dev, "pixel clk = %u, divider %u.%u\n",
+	dev_dbg(fbi->fb_host.hw_dev, "pixel clk = %u, divider %u.%u\n",
 		pixel_clk, div >> 4, (div & 7) * 125);
 
 	/*
@@ -588,19 +589,20 @@ static u32 dma_param_addr(enum ipu_channel channel)
 	return 0x10000 | (channel << 4);
 }
 
-static void ipu_init_channel_buffer(struct ipu_fb_info *fbi,
+static void ipu_init_channel_buffer(struct fb_info *fb_info,
 		enum ipu_channel channel, void *fbmem)
 {
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
 	union chan_param_mem params = {};
 	u32 reg;
 	u32 stride_bytes;
 
-	stride_bytes = fbi->info.xres * ((fbi->info.bits_per_pixel + 7) / 8);
+	stride_bytes = fbi->mode->xres * ((fb_info->bits_per_pixel + 7) / 8);
 	stride_bytes = (stride_bytes + 3) & ~3;
 
 	/* Build parameter memory data for DMA channel */
-	ipu_ch_param_set_size(&params, bpp_to_pixfmt(fbi->info.bits_per_pixel),
-			      fbi->info.xres, fbi->info.yres, stride_bytes);
+	ipu_ch_param_set_size(&params, bpp_to_pixfmt(fb_info->bits_per_pixel),
+			      fbi->mode->xres, fbi->mode->yres, stride_bytes);
 	ipu_ch_param_set_buffer(&params, fbmem, NULL);
 	params.pp.bam = 0;
 	/* Some channels (rotation) have restriction on burst length */
@@ -622,9 +624,10 @@ static void ipu_init_channel_buffer(struct ipu_fb_info *fbi,
 	reg_write(fbi, reg, IPU_CHA_DB_MODE_SEL);
 }
 
-static void ipu_channel_set_priority(struct ipu_fb_info *fbi,
+static void ipu_channel_set_priority(struct fb_info *fb_info,
 		enum ipu_channel channel, int prio)
 {
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
 	u32 reg;
 
 	reg = reg_read(fbi, IDMAC_CHA_PRI);
@@ -639,11 +642,13 @@ static void ipu_channel_set_priority(struct ipu_fb_info *fbi,
 
 /*
  * ipu_enable_channel() - enable an IPU channel.
+ * @param fb_info The framebuffer to work on
  * @channel:	channel ID.
  * @return:	0 on success or negative error code on failure.
  */
-static int ipu_enable_channel(struct ipu_fb_info *fbi, enum ipu_channel channel)
+static int ipu_enable_channel(struct fb_info *fb_info, enum ipu_channel channel)
 {
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
 	u32 reg;
 
 	/* Reset to buffer 0 */
@@ -651,7 +656,7 @@ static int ipu_enable_channel(struct ipu_fb_info *fbi, enum ipu_channel channel)
 
 	switch (channel) {
 	case IDMAC_SDC_0:
-		ipu_channel_set_priority(fbi, channel, 1);
+		ipu_channel_set_priority(fb_info, channel, 1);
 		break;
 	default:
 		break;
@@ -663,9 +668,10 @@ static int ipu_enable_channel(struct ipu_fb_info *fbi, enum ipu_channel channel)
 	return 0;
 }
 
-static int ipu_update_channel_buffer(struct ipu_fb_info *fbi,
+static int ipu_update_channel_buffer(struct fb_info *fb_info,
 		enum ipu_channel channel, void *buf)
 {
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
 	u32 reg;
 
 	reg = reg_read(fbi, IPU_CHA_BUF0_RDY);
@@ -679,16 +685,17 @@ static int ipu_update_channel_buffer(struct ipu_fb_info *fbi,
 	return 0;
 }
 
-static int idmac_tx_submit(struct ipu_fb_info *fbi, enum ipu_channel channel,
+static int idmac_tx_submit(struct fb_info *fb_info, enum ipu_channel channel,
 		void *buf)
 {
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
 	int ret;
 
-	ipu_init_channel_buffer(fbi, channel, buf);
+	ipu_init_channel_buffer(fb_info, channel, buf);
 
 
 	/* ipu_idmac.c::ipu_submit_channel_buffers() */
-	ret = ipu_update_channel_buffer(fbi, channel, buf);
+	ret = ipu_update_channel_buffer(fb_info, channel, buf);
 	if (ret < 0)
 		return ret;
 
@@ -697,16 +704,17 @@ static int idmac_tx_submit(struct ipu_fb_info *fbi, enum ipu_channel channel,
 	reg_write(fbi, 1UL << channel, IPU_CHA_BUF0_RDY);
 
 
-	ret = ipu_enable_channel(fbi, channel);
+	ret = ipu_enable_channel(fb_info, channel);
 	return ret;
 }
 
-static void sdc_enable_channel(struct ipu_fb_info *fbi, void *fbmem)
+static void sdc_enable_channel(struct fb_info *fb_info, void *fbmem)
 {
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
 	int ret;
 	u32 reg;
 
-	ret = idmac_tx_submit(fbi, IDMAC_SDC_0, fbmem);
+	ret = idmac_tx_submit(fb_info, IDMAC_SDC_0, fbmem);
 
 	/* mx3fb.c::sdc_fb_init() */
 	if (ret >= 0) {
@@ -722,11 +730,74 @@ static void sdc_enable_channel(struct ipu_fb_info *fbi, void *fbmem)
 	mdelay(2);
 }
 
+static void imxfb_init_info(struct fb_info *fb_info, const struct fb_videomode *mode)
+{
+	struct imx_ipu_fb_rgb *rgb;
+
+	fb_info->xres = mode->xres;
+	fb_info->yres = mode->yres;
+
+	switch (fb_info->bits_per_pixel) {
+	case 32:
+		rgb = &def_rgb_32;
+		break;
+	case 24:
+		rgb = &def_rgb_24;
+		break;
+	case 16:
+	default:
+		rgb = &def_rgb_16;
+		break;
+	}
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	fb_info->red    = rgb->red;
+	fb_info->green  = rgb->green;
+	fb_info->blue   = rgb->blue;
+	fb_info->transp = rgb->transp;
+}
+
+static int ipu_fb_initialize_mode(struct fb_info *fb_info, const struct fb_videomode *mode)
+{
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
+	unsigned size;
+
+	/*
+	 * we need at least this amount of memory for the framebuffer
+	 */
+	size = mode->xres * mode->yres * (fb_info->bits_per_pixel >> 3);
+	if (fb_info->fb_dev->size != 0) {
+		if (size > fb_info->fb_dev->size) {
+			pr_err("Cannot initialize video mode '%s': Its too large. "
+				"Required bytes are %u, available only %u\n",
+				mode->name, size, fb_info->fb_dev->size);
+			return -EINVAL;
+		}
+	} else
+		fb_info->fb_dev->size = size;
+
+	/*
+	 * if no framebuffer memory was specified yet, allocate one,
+	 * and allocate more memory, on user request
+	 */
+	if (fb_info->fb_dev->map_base == 0U /* FIXME should be 'NULL'*/)
+		fb_info->fb_dev->map_base = (unsigned long)xzalloc(fb_info->fb_dev->size);
+
+	fbi->mode = mode;
+
+	imxfb_init_info(fb_info, mode);
+
+	return 0;
+}
+
 /* References in this function refer to respective Linux kernel sources */
-static void ipu_fb_enable(struct fb_info *info)
+static void ipu_fb_enable(struct fb_info *fb_info)
 {
-	struct ipu_fb_info *fbi = info->priv;
-	struct fb_videomode *mode = info->mode;
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(fb_info);
+	const struct fb_videomode *mode = fbi->mode;
 	u32 reg;
 
 	/* pcm037.c::mxc_board_init() */
@@ -779,12 +850,12 @@ static void ipu_fb_enable(struct fb_info *info)
 		~(SDC_COM_GWSEL | SDC_COM_KEY_COLOR_G);
 	reg_write(fbi, reg, SDC_COM_CONF);
 
-	sdc_init_panel(info, IPU_PIX_FMT_RGB666);
+	sdc_init_panel(fb_info, IPU_PIX_FMT_RGB666);
 
 	reg_write(fbi, (mode->left_margin << 16) | mode->upper_margin,
 			SDC_BG_POS);
 
-	sdc_enable_channel(fbi, info->screen_base);
+	sdc_enable_channel(fb_info, (void*)fb_info->fb_dev->map_base);
 
 	/*
 	 * Linux driver calls sdc_set_brightness() here again,
@@ -796,7 +867,7 @@ static void ipu_fb_enable(struct fb_info *info)
 
 static void ipu_fb_disable(struct fb_info *info)
 {
-	struct ipu_fb_info *fbi = info->priv;
+	struct ipu_fb_info *fbi = fb_info_to_imxfb_info(info);
 	u32 reg;
 
 	if (fbi->enable)
@@ -807,85 +878,38 @@ static void ipu_fb_disable(struct fb_info *info)
 	reg_write(fbi, reg, SDC_COM_CONF);
 }
 
-static struct fb_ops imxfb_ops = {
-	.fb_enable = ipu_fb_enable,
-	.fb_disable = ipu_fb_disable,
-};
-
-static void imxfb_init_info(struct fb_info *info, struct fb_videomode *mode,
-		int bpp)
-{
-	struct imx_ipu_fb_rgb *rgb;
-
-	info->mode = mode;
-	info->xres = mode->xres;
-	info->yres = mode->yres;
-	info->bits_per_pixel = bpp;
-
-	switch (info->bits_per_pixel) {
-	case 32:
-		rgb = &def_rgb_32;
-		break;
-	case 24:
-		rgb = &def_rgb_24;
-		break;
-	case 16:
-	default:
-		rgb = &def_rgb_16;
-		break;
-	}
-
-	/*
-	 * Copy the RGB parameters for this display
-	 * from the machine specific parameters.
-	 */
-	info->red    = rgb->red;
-	info->green  = rgb->green;
-	info->blue   = rgb->blue;
-	info->transp = rgb->transp;
-}
-
 static int imxfb_probe(struct device_d *dev)
 {
 	struct ipu_fb_info *fbi;
-	struct fb_info *info;
+	struct device_d *fb_dev;
 	const struct imx_ipu_fb_platform_data *pdata = dev->platform_data;
-	int ret;
 
 	if (!pdata)
 		return -ENODEV;
 
 	fbi = xzalloc(sizeof(*fbi));
-	info = &fbi->info;
+
+	/* add runtime hardware info */
+	fbi->fb_host.hw_dev = dev;
+	fbi->fb_host.fb_mode = ipu_fb_initialize_mode;
+	fbi->fb_host.fb_enable = ipu_fb_enable;
+	fbi->fb_host.fb_disable = ipu_fb_disable;
+	fbi->fb_host.fb_setcolreg = NULL;
 
 	fbi->regs = (void *)dev->map_base;
-	fbi->dev = dev;
-	info->priv = fbi;
-	info->fbops = &imxfb_ops;
-	fbi->enable = pdata->enable;
 
-	imxfb_init_info(info, pdata->mode, pdata->bpp);
+	/* add runtime video info */
+	fbi->fb_host.mode = pdata->mode;
+	/* to be backward compatible */
+	fbi->fb_host.mode_cnt = pdata->mode_cnt == 0 ? 1 : pdata->mode_cnt;
+	fbi->fb_host.bits_per_pixel = pdata->bpp;
 
 	dev_info(dev, "i.MX Framebuffer driver\n");
 
-	/*
-	 * Use a given frambuffer or reserve some
-	 * memory for screen usage
-	 */
-	fbi->info.screen_base = pdata->framebuffer;
-	if (fbi->info.screen_base == NULL) {
-		fbi->info.screen_base = malloc(info->xres * info->yres *
-					       (info->bits_per_pixel >> 3));
-		if (!fbi->info.screen_base)
-			return -ENOMEM;
-	}
-
-	sdc_enable_channel(fbi, info->screen_base);
-
-	ret = register_framebuffer(&fbi->info);
-	if (ret < 0) {
+	fb_dev = register_framebuffer(&fbi->fb_host, pdata->framebuffer, 0);
+	if (fb_dev == NULL) {
 		dev_err(dev, "failed to register framebuffer\n");
-		return ret;
+		return -EINVAL;
 	}
 
 	return 0;
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2010-10-26 11:32 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-26 11:31 [PATCHv2] Add dynamic video initialization to barebox Juergen Beisert
2010-10-26 11:31 ` [PATCH 01/12] Separate framebuffer platformdata and the videomode Juergen Beisert
2010-10-26 11:31 ` [PATCH 02/12] Add more flags for sync control Juergen Beisert
2010-10-26 11:31 ` [PATCH 03/12] Bring in dynamic videomode selection at runtime Juergen Beisert
2010-11-01 13:47   ` Sascha Hauer
2010-11-15 10:04     ` Juergen Beisert
2010-11-17  8:27       ` Sascha Hauer
2010-11-01 14:16   ` Sascha Hauer
2010-11-15 10:08     ` Juergen Beisert
2010-10-26 11:31 ` [PATCH 04/12] Remove the old videomode functions Juergen Beisert
2010-10-26 11:31 ` [PATCH 05/12] Add verbose framebuffer device info Juergen Beisert
2010-10-26 11:31 ` [PATCH 06/12] Adapt the existing imx fb driver to support runtime videomode selection Juergen Beisert
2010-10-26 11:31 ` Juergen Beisert [this message]
2010-10-26 11:31 ` [PATCH 08/12] Add a video driver for S3C2440 bases platforms Juergen Beisert
2010-11-01 14:41   ` Sascha Hauer
2010-11-15 11:35     ` Juergen Beisert
2010-11-17  8:36       ` Sascha Hauer
2010-10-26 11:31 ` [PATCH 09/12] STM378x: Add video driver for this platform Juergen Beisert
2010-10-26 11:31 ` [PATCH 10/12] Remove variable size restrictions Juergen Beisert
2010-10-26 11:31 ` [PATCH 11/12] Add doxygen documentation to the framebfuffer code Juergen Beisert
2010-10-26 11:31 ` [PATCH 12/12] Provide more driver specific data in a videomode Juergen Beisert
2010-11-01 13:19 ` [PATCHv2] Add dynamic video initialization to barebox Sascha Hauer
2010-11-01 13:29   ` Eric Bénard
2010-11-01 14:18     ` Sascha Hauer
2010-11-15  9:57   ` Juergen Beisert
2010-11-15 10:25     ` Belisko Marek
2010-11-17  8:44       ` Sascha Hauer
2010-11-18  8:18         ` Belisko Marek
2010-11-18 10:09           ` Sascha Hauer
2010-11-17  8:43     ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1288092708-5187-8-git-send-email-jbe@pengutronix.de \
    --to=jbe@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox