aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <lg@denx.de>2009-02-26 15:34:28 -0500
committerDan Williams <dan.j.williams@intel.com>2009-02-26 16:00:58 -0500
commit6e1588cbd88590273300403648aef70e6bdaf5af (patch)
tree95d7a232f68d81e0190d05bd454b70d312077136
parent1febd91acff907152e61eb5ad0a82dd8d7db21c6 (diff)
i.MX31: framebuffer driver
This is a framebuffer driver for i.MX31 SoCs. It only supports synchronous displays, vertical panning supported, no overlay support. Signed-off-by: Guennadi Liakhovetski <lg@denx.de> Acked-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--arch/arm/plat-mxc/include/mach/mx3fb.h38
-rw-r--r--drivers/video/Kconfig12
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/mx3fb.c1555
4 files changed, 1606 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/include/mach/mx3fb.h b/arch/arm/plat-mxc/include/mach/mx3fb.h
new file mode 100644
index 000000000000..ac24c5c4bc83
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx3fb.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2008
3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#ifndef __ASM_ARCH_MX3FB_H__
11#define __ASM_ARCH_MX3FB_H__
12
13#include <linux/device.h>
14#include <linux/fb.h>
15
16/* Proprietary FB_SYNC_ flags */
17#define FB_SYNC_OE_ACT_HIGH 0x80000000
18#define FB_SYNC_CLK_INVERT 0x40000000
19#define FB_SYNC_DATA_INVERT 0x20000000
20#define FB_SYNC_CLK_IDLE_EN 0x10000000
21#define FB_SYNC_SHARP_MODE 0x08000000
22#define FB_SYNC_SWAP_RGB 0x04000000
23#define FB_SYNC_CLK_SEL_EN 0x02000000
24
25/**
26 * struct mx3fb_platform_data - mx3fb platform data
27 *
28 * @dma_dev: pointer to the dma-device, used for dma-slave connection
29 * @mode: pointer to a platform-provided per mxc_register_fb() videomode
30 */
31struct mx3fb_platform_data {
32 struct device *dma_dev;
33 const char *name;
34 const struct fb_videomode *mode;
35 int num_modes;
36};
37
38#endif
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6f3f3bff3832..5c5e3fe090ea 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2125,6 +2125,18 @@ config FB_PRE_INIT_FB
2125 Select this option if display contents should be inherited as set by 2125 Select this option if display contents should be inherited as set by
2126 the bootloader. 2126 the bootloader.
2127 2127
2128config FB_MX3
2129 tristate "MX3 Framebuffer support"
2130 depends on FB && MX3_IPU
2131 select FB_CFB_FILLRECT
2132 select FB_CFB_COPYAREA
2133 select FB_CFB_IMAGEBLIT
2134 default y
2135 help
2136 This is a framebuffer device for the i.MX31 LCD Controller. So
2137 far only synchronous displays are supported. If you plan to use
2138 an LCD display with your i.MX31 system, say Y here.
2139
2128source "drivers/video/omap/Kconfig" 2140source "drivers/video/omap/Kconfig"
2129 2141
2130source "drivers/video/backlight/Kconfig" 2142source "drivers/video/backlight/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index be2b657546ef..a5564a513a5e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -132,6 +132,7 @@ obj-$(CONFIG_FB_VGA16) += vga16fb.o
132obj-$(CONFIG_FB_OF) += offb.o 132obj-$(CONFIG_FB_OF) += offb.o
133obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o 133obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
134obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o 134obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
135obj-$(CONFIG_FB_MX3) += mx3fb.o
135 136
136# the test framebuffer is last 137# the test framebuffer is last
137obj-$(CONFIG_FB_VIRTUAL) += vfb.o 138obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
new file mode 100644
index 000000000000..3e8463562dee
--- /dev/null
+++ b/drivers/video/mx3fb.c
@@ -0,0 +1,1555 @@
1/*
2 * Copyright (C) 2008
3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
4 *
5 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/sched.h>
16#include <linux/errno.h>
17#include <linux/string.h>
18#include <linux/interrupt.h>
19#include <linux/slab.h>
20#include <linux/fb.h>
21#include <linux/delay.h>
22#include <linux/init.h>
23#include <linux/ioport.h>
24#include <linux/dma-mapping.h>
25#include <linux/dmaengine.h>
26#include <linux/console.h>
27#include <linux/clk.h>
28#include <linux/mutex.h>
29
30#include <mach/hardware.h>
31#include <mach/ipu.h>
32#include <mach/mx3fb.h>
33
34#include <asm/io.h>
35#include <asm/uaccess.h>
36
37#define MX3FB_NAME "mx3_sdc_fb"
38
39#define MX3FB_REG_OFFSET 0xB4
40
41/* SDC Registers */
42#define SDC_COM_CONF (0xB4 - MX3FB_REG_OFFSET)
43#define SDC_GW_CTRL (0xB8 - MX3FB_REG_OFFSET)
44#define SDC_FG_POS (0xBC - MX3FB_REG_OFFSET)
45#define SDC_BG_POS (0xC0 - MX3FB_REG_OFFSET)
46#define SDC_CUR_POS (0xC4 - MX3FB_REG_OFFSET)
47#define SDC_PWM_CTRL (0xC8 - MX3FB_REG_OFFSET)
48#define SDC_CUR_MAP (0xCC - MX3FB_REG_OFFSET)
49#define SDC_HOR_CONF (0xD0 - MX3FB_REG_OFFSET)
50#define SDC_VER_CONF (0xD4 - MX3FB_REG_OFFSET)
51#define SDC_SHARP_CONF_1 (0xD8 - MX3FB_REG_OFFSET)
52#define SDC_SHARP_CONF_2 (0xDC - MX3FB_REG_OFFSET)
53
54/* Register bits */
55#define SDC_COM_TFT_COLOR 0x00000001UL
56#define SDC_COM_FG_EN 0x00000010UL
57#define SDC_COM_GWSEL 0x00000020UL
58#define SDC_COM_GLB_A 0x00000040UL
59#define SDC_COM_KEY_COLOR_G 0x00000080UL
60#define SDC_COM_BG_EN 0x00000200UL
61#define SDC_COM_SHARP 0x00001000UL
62
63#define SDC_V_SYNC_WIDTH_L 0x00000001UL
64
65/* Display Interface registers */
66#define DI_DISP_IF_CONF (0x0124 - MX3FB_REG_OFFSET)
67#define DI_DISP_SIG_POL (0x0128 - MX3FB_REG_OFFSET)
68#define DI_SER_DISP1_CONF (0x012C - MX3FB_REG_OFFSET)
69#define DI_SER_DISP2_CONF (0x0130 - MX3FB_REG_OFFSET)
70#define DI_HSP_CLK_PER (0x0134 - MX3FB_REG_OFFSET)
71#define DI_DISP0_TIME_CONF_1 (0x0138 - MX3FB_REG_OFFSET)
72#define DI_DISP0_TIME_CONF_2 (0x013C - MX3FB_REG_OFFSET)
73#define DI_DISP0_TIME_CONF_3 (0x0140 - MX3FB_REG_OFFSET)
74#define DI_DISP1_TIME_CONF_1 (0x0144 - MX3FB_REG_OFFSET)
75#define DI_DISP1_TIME_CONF_2 (0x0148 - MX3FB_REG_OFFSET)
76#define DI_DISP1_TIME_CONF_3 (0x014C - MX3FB_REG_OFFSET)
77#define DI_DISP2_TIME_CONF_1 (0x0150 - MX3FB_REG_OFFSET)
78#define DI_DISP2_TIME_CONF_2 (0x0154 - MX3FB_REG_OFFSET)
79#define DI_DISP2_TIME_CONF_3 (0x0158 - MX3FB_REG_OFFSET)
80#define DI_DISP3_TIME_CONF (0x015C - MX3FB_REG_OFFSET)
81#define DI_DISP0_DB0_MAP (0x0160 - MX3FB_REG_OFFSET)
82#define DI_DISP0_DB1_MAP (0x0164 - MX3FB_REG_OFFSET)
83#define DI_DISP0_DB2_MAP (0x0168 - MX3FB_REG_OFFSET)
84#define DI_DISP0_CB0_MAP (0x016C - MX3FB_REG_OFFSET)
85#define DI_DISP0_CB1_MAP (0x0170 - MX3FB_REG_OFFSET)
86#define DI_DISP0_CB2_MAP (0x0174 - MX3FB_REG_OFFSET)
87#define DI_DISP1_DB0_MAP (0x0178 - MX3FB_REG_OFFSET)
88#define DI_DISP1_DB1_MAP (0x017C - MX3FB_REG_OFFSET)
89#define DI_DISP1_DB2_MAP (0x0180 - MX3FB_REG_OFFSET)
90#define DI_DISP1_CB0_MAP (0x0184 - MX3FB_REG_OFFSET)
91#define DI_DISP1_CB1_MAP (0x0188 - MX3FB_REG_OFFSET)
92#define DI_DISP1_CB2_MAP (0x018C - MX3FB_REG_OFFSET)
93#define DI_DISP2_DB0_MAP (0x0190 - MX3FB_REG_OFFSET)
94#define DI_DISP2_DB1_MAP (0x0194 - MX3FB_REG_OFFSET)
95#define DI_DISP2_DB2_MAP (0x0198 - MX3FB_REG_OFFSET)
96#define DI_DISP2_CB0_MAP (0x019C - MX3FB_REG_OFFSET)
97#define DI_DISP2_CB1_MAP (0x01A0 - MX3FB_REG_OFFSET)
98#define DI_DISP2_CB2_MAP (0x01A4 - MX3FB_REG_OFFSET)
99#define DI_DISP3_B0_MAP (0x01A8 - MX3FB_REG_OFFSET)
100#define DI_DISP3_B1_MAP (0x01AC - MX3FB_REG_OFFSET)
101#define DI_DISP3_B2_MAP (0x01B0 - MX3FB_REG_OFFSET)
102#define DI_DISP_ACC_CC (0x01B4 - MX3FB_REG_OFFSET)
103#define DI_DISP_LLA_CONF (0x01B8 - MX3FB_REG_OFFSET)
104#define DI_DISP_LLA_DATA (0x01BC - MX3FB_REG_OFFSET)
105
106/* DI_DISP_SIG_POL bits */
107#define DI_D3_VSYNC_POL_SHIFT 28
108#define DI_D3_HSYNC_POL_SHIFT 27
109#define DI_D3_DRDY_SHARP_POL_SHIFT 26
110#define DI_D3_CLK_POL_SHIFT 25
111#define DI_D3_DATA_POL_SHIFT 24
112
113/* DI_DISP_IF_CONF bits */
114#define DI_D3_CLK_IDLE_SHIFT 26
115#define DI_D3_CLK_SEL_SHIFT 25
116#define DI_D3_DATAMSK_SHIFT 24
117
118enum ipu_panel {
119 IPU_PANEL_SHARP_TFT,
120 IPU_PANEL_TFT,
121};
122
123struct ipu_di_signal_cfg {
124 unsigned datamask_en:1;
125 unsigned clksel_en:1;
126 unsigned clkidle_en:1;
127 unsigned data_pol:1; /* true = inverted */
128 unsigned clk_pol:1; /* true = rising edge */
129 unsigned enable_pol:1;
130 unsigned Hsync_pol:1; /* true = active high */
131 unsigned Vsync_pol:1;
132};
133
134static const struct fb_videomode mx3fb_modedb[] = {
135 {
136 /* 240x320 @ 60 Hz */
137 .name = "Sharp-QVGA",
138 .refresh = 60,
139 .xres = 240,
140 .yres = 320,
141 .pixclock = 185925,
142 .left_margin = 9,
143 .right_margin = 16,
144 .upper_margin = 7,
145 .lower_margin = 9,
146 .hsync_len = 1,
147 .vsync_len = 1,
148 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
149 FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT |
150 FB_SYNC_CLK_IDLE_EN,
151 .vmode = FB_VMODE_NONINTERLACED,
152 .flag = 0,
153 }, {
154 /* 240x33 @ 60 Hz */
155 .name = "Sharp-CLI",
156 .refresh = 60,
157 .xres = 240,
158 .yres = 33,
159 .pixclock = 185925,
160 .left_margin = 9,
161 .right_margin = 16,
162 .upper_margin = 7,
163 .lower_margin = 9 + 287,
164 .hsync_len = 1,
165 .vsync_len = 1,
166 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
167 FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT |
168 FB_SYNC_CLK_IDLE_EN,
169 .vmode = FB_VMODE_NONINTERLACED,
170 .flag = 0,
171 }, {
172 /* 640x480 @ 60 Hz */
173 .name = "NEC-VGA",
174 .refresh = 60,
175 .xres = 640,
176 .yres = 480,
177 .pixclock = 38255,
178 .left_margin = 144,
179 .right_margin = 0,
180 .upper_margin = 34,
181 .lower_margin = 40,
182 .hsync_len = 1,
183 .vsync_len = 1,
184 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
185 .vmode = FB_VMODE_NONINTERLACED,
186 .flag = 0,
187 }, {
188 /* NTSC TV output */
189 .name = "TV-NTSC",
190 .refresh = 60,
191 .xres = 640,
192 .yres = 480,
193 .pixclock = 37538,
194 .left_margin = 38,
195 .right_margin = 858 - 640 - 38 - 3,
196 .upper_margin = 36,
197 .lower_margin = 518 - 480 - 36 - 1,
198 .hsync_len = 3,
199 .vsync_len = 1,
200 .sync = 0,
201 .vmode = FB_VMODE_NONINTERLACED,
202 .flag = 0,
203 }, {
204 /* PAL TV output */
205 .name = "TV-PAL",
206 .refresh = 50,
207 .xres = 640,
208 .yres = 480,
209 .pixclock = 37538,
210 .left_margin = 38,
211 .right_margin = 960 - 640 - 38 - 32,
212 .upper_margin = 32,
213 .lower_margin = 555 - 480 - 32 - 3,
214 .hsync_len = 32,
215 .vsync_len = 3,
216 .sync = 0,
217 .vmode = FB_VMODE_NONINTERLACED,
218 .flag = 0,
219 }, {
220 /* TV output VGA mode, 640x480 @ 65 Hz */
221 .name = "TV-VGA",
222 .refresh = 60,
223 .xres = 640,
224 .yres = 480,
225 .pixclock = 40574,
226 .left_margin = 35,
227 .right_margin = 45,
228 .upper_margin = 9,
229 .lower_margin = 1,
230 .hsync_len = 46,
231 .vsync_len = 5,
232 .sync = 0,
233 .vmode = FB_VMODE_NONINTERLACED,
234 .flag = 0,
235 },
236};
237
238struct mx3fb_data {
239 struct fb_info *fbi;
240 int backlight_level;
241 void __iomem *reg_base;
242 spinlock_t lock;
243 struct device *dev;
244
245 uint32_t h_start_width;
246 uint32_t v_start_width;
247};
248
249struct dma_chan_request {
250 struct mx3fb_data *mx3fb;
251 enum ipu_channel id;
252};
253
254/* MX3 specific framebuffer information. */
255struct mx3fb_info {
256 int blank;
257 enum ipu_channel ipu_ch;
258 uint32_t cur_ipu_buf;
259
260 u32 pseudo_palette[16];
261
262 struct completion flip_cmpl;
263 struct mutex mutex; /* Protects fb-ops */
264 struct mx3fb_data *mx3fb;
265 struct idmac_channel *idmac_channel;
266 struct dma_async_tx_descriptor *txd;
267 dma_cookie_t cookie;
268 struct scatterlist sg[2];
269
270 u32 sync; /* preserve var->sync flags */
271};
272
273static void mx3fb_dma_done(void *);
274
275/* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */
276static const char *fb_mode;
277static unsigned long default_bpp = 16;
278
279static u32 mx3fb_read_reg(struct mx3fb_data *mx3fb, unsigned long reg)
280{
281 return __raw_readl(mx3fb->reg_base + reg);
282}
283
284static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long reg)
285{
286 __raw_writel(value, mx3fb->reg_base + reg);
287}
288
289static const uint32_t di_mappings[] = {
290 0x1600AAAA, 0x00E05555, 0x00070000, 3, /* RGB888 */
291 0x0005000F, 0x000B000F, 0x0011000F, 1, /* RGB666 */
292 0x0011000F, 0x000B000F, 0x0005000F, 1, /* BGR666 */
293 0x0004003F, 0x000A000F, 0x000F003F, 1 /* RGB565 */
294};
295
296static void sdc_fb_init(struct mx3fb_info *fbi)
297{
298 struct mx3fb_data *mx3fb = fbi->mx3fb;
299 uint32_t reg;
300
301 reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
302
303 mx3fb_write_reg(mx3fb, reg | SDC_COM_BG_EN, SDC_COM_CONF);
304}
305
306/* Returns enabled flag before uninit */
307static uint32_t sdc_fb_uninit(struct mx3fb_info *fbi)
308{
309 struct mx3fb_data *mx3fb = fbi->mx3fb;
310 uint32_t reg;
311
312 reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
313
314 mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF);
315
316 return reg & SDC_COM_BG_EN;
317}
318
319static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
320{
321 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
322 struct idmac_channel *ichan = mx3_fbi->idmac_channel;
323 struct dma_chan *dma_chan = &ichan->dma_chan;
324 unsigned long flags;
325 dma_cookie_t cookie;
326
327 dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
328 to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
329
330 /* This enables the channel */
331 if (mx3_fbi->cookie < 0) {
332 mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan,
333 &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
334 if (!mx3_fbi->txd) {
335 dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
336 dma_chan->chan_id);
337 return;
338 }
339
340 mx3_fbi->txd->callback_param = mx3_fbi->txd;
341 mx3_fbi->txd->callback = mx3fb_dma_done;
342
343 cookie = mx3_fbi->txd->tx_submit(mx3_fbi->txd);
344 dev_dbg(mx3fb->dev, "%d: Submit %p #%d [%c]\n", __LINE__,
345 mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+');
346 } else {
347 if (!mx3_fbi->txd || !mx3_fbi->txd->tx_submit) {
348 dev_err(mx3fb->dev, "Cannot enable channel %d\n",
349 dma_chan->chan_id);
350 return;
351 }
352
353 /* Just re-activate the same buffer */
354 dma_async_issue_pending(dma_chan);
355 cookie = mx3_fbi->cookie;
356 dev_dbg(mx3fb->dev, "%d: Re-submit %p #%d [%c]\n", __LINE__,
357 mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+');
358 }
359
360 if (cookie >= 0) {
361 spin_lock_irqsave(&mx3fb->lock, flags);
362 sdc_fb_init(mx3_fbi);
363 mx3_fbi->cookie = cookie;
364 spin_unlock_irqrestore(&mx3fb->lock, flags);
365 }
366
367 /*
368 * Attention! Without this msleep the channel keeps generating
369 * interrupts. Next sdc_set_brightness() is going to be called
370 * from mx3fb_blank().
371 */
372 msleep(2);
373}
374
375static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
376{
377 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
378 uint32_t enabled;
379 unsigned long flags;
380
381 spin_lock_irqsave(&mx3fb->lock, flags);
382
383 enabled = sdc_fb_uninit(mx3_fbi);
384
385 spin_unlock_irqrestore(&mx3fb->lock, flags);
386
387 mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan);
388 mx3_fbi->txd = NULL;
389 mx3_fbi->cookie = -EINVAL;
390}
391
392/**
393 * sdc_set_window_pos() - set window position of the respective plane.
394 * @mx3fb: mx3fb context.
395 * @channel: IPU DMAC channel ID.
396 * @x_pos: X coordinate relative to the top left corner to place window at.
397 * @y_pos: Y coordinate relative to the top left corner to place window at.
398 * @return: 0 on success or negative error code on failure.
399 */
400static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel,
401 int16_t x_pos, int16_t y_pos)
402{
403 x_pos += mx3fb->h_start_width;
404 y_pos += mx3fb->v_start_width;
405
406 if (channel != IDMAC_SDC_0)
407 return -EINVAL;
408
409 mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS);
410 return 0;
411}
412
413/**
414 * sdc_init_panel() - initialize a synchronous LCD panel.
415 * @mx3fb: mx3fb context.
416 * @panel: panel type.
417 * @pixel_clk: desired pixel clock frequency in Hz.
418 * @width: width of panel in pixels.
419 * @height: height of panel in pixels.
420 * @pixel_fmt: pixel format of buffer as FOURCC ASCII code.
421 * @h_start_width: number of pixel clocks between the HSYNC signal pulse
422 * and the start of valid data.
423 * @h_sync_width: width of the HSYNC signal in units of pixel clocks.
424 * @h_end_width: number of pixel clocks between the end of valid data
425 * and the HSYNC signal for next line.
426 * @v_start_width: number of lines between the VSYNC signal pulse and the
427 * start of valid data.
428 * @v_sync_width: width of the VSYNC signal in units of lines
429 * @v_end_width: number of lines between the end of valid data and the
430 * VSYNC signal for next frame.
431 * @sig: bitfield of signal polarities for LCD interface.
432 * @return: 0 on success or negative error code on failure.
433 */
434static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
435 uint32_t pixel_clk,
436 uint16_t width, uint16_t height,
437 enum pixel_fmt pixel_fmt,
438 uint16_t h_start_width, uint16_t h_sync_width,
439 uint16_t h_end_width, uint16_t v_start_width,
440 uint16_t v_sync_width, uint16_t v_end_width,
441 struct ipu_di_signal_cfg sig)
442{
443 unsigned long lock_flags;
444 uint32_t reg;
445 uint32_t old_conf;
446 uint32_t div;
447 struct clk *ipu_clk;
448
449 dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
450
451 if (v_sync_width == 0 || h_sync_width == 0)
452 return -EINVAL;
453
454 /* Init panel size and blanking periods */
455 reg = ((uint32_t) (h_sync_width - 1) << 26) |
456 ((uint32_t) (width + h_start_width + h_end_width - 1) << 16);
457 mx3fb_write_reg(mx3fb, reg, SDC_HOR_CONF);
458
459#ifdef DEBUG
460 printk(KERN_CONT " hor_conf %x,", reg);
461#endif
462
463 reg = ((uint32_t) (v_sync_width - 1) << 26) | SDC_V_SYNC_WIDTH_L |
464 ((uint32_t) (height + v_start_width + v_end_width - 1) << 16);
465 mx3fb_write_reg(mx3fb, reg, SDC_VER_CONF);
466
467#ifdef DEBUG
468 printk(KERN_CONT " ver_conf %x\n", reg);
469#endif
470
471 mx3fb->h_start_width = h_start_width;
472 mx3fb->v_start_width = v_start_width;
473
474 switch (panel) {
475 case IPU_PANEL_SHARP_TFT:
476 mx3fb_write_reg(mx3fb, 0x00FD0102L, SDC_SHARP_CONF_1);
477 mx3fb_write_reg(mx3fb, 0x00F500F4L, SDC_SHARP_CONF_2);
478 mx3fb_write_reg(mx3fb, SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF);
479 break;
480 case IPU_PANEL_TFT:
481 mx3fb_write_reg(mx3fb, SDC_COM_TFT_COLOR, SDC_COM_CONF);
482 break;
483 default:
484 return -EINVAL;
485 }
486
487 /* Init clocking */
488
489 /*
490 * Calculate divider: fractional part is 4 bits so simply multiple by
491 * 2^4 to get fractional part, as long as we stay under ~250MHz and on
492 * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
493 */
494 dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk);
495
496 ipu_clk = clk_get(mx3fb->dev, "ipu_clk");
497 div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
498 clk_put(ipu_clk);
499
500 if (div < 0x40) { /* Divider less than 4 */
501 dev_dbg(mx3fb->dev,
502 "InitPanel() - Pixel clock divider less than 4\n");
503 div = 0x40;
504 }
505
506 spin_lock_irqsave(&mx3fb->lock, lock_flags);
507
508 /*
509 * DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits
510 * fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing
511 * debug. DISP3_IF_CLK_UP_WR is 0
512 */
513 mx3fb_write_reg(mx3fb, (((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF);
514
515 /* DI settings */
516 old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF;
517 old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT |
518 sig.clksel_en << DI_D3_CLK_SEL_SHIFT |
519 sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT;
520 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF);
521
522 old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF;
523 old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT |
524 sig.clk_pol << DI_D3_CLK_POL_SHIFT |
525 sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT |
526 sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT |
527 sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
528 mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
529
530 switch (pixel_fmt) {
531 case IPU_PIX_FMT_RGB24:
532 mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP);
533 mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP);
534 mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP);
535 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
536 ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
537 break;
538 case IPU_PIX_FMT_RGB666:
539 mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP);
540 mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP);
541 mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP);
542 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
543 ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
544 break;
545 case IPU_PIX_FMT_BGR666:
546 mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP);
547 mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP);
548 mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP);
549 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
550 ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
551 break;
552 default:
553 mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP);
554 mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP);
555 mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP);
556 mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
557 ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
558 break;
559 }
560
561 spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
562
563 dev_dbg(mx3fb->dev, "DI_DISP_IF_CONF = 0x%08X\n",
564 mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF));
565 dev_dbg(mx3fb->dev, "DI_DISP_SIG_POL = 0x%08X\n",
566 mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL));
567 dev_dbg(mx3fb->dev, "DI_DISP3_TIME_CONF = 0x%08X\n",
568 mx3fb_read_reg(mx3fb, DI_DISP3_TIME_CONF));
569
570 return 0;
571}
572
573/**
574 * sdc_set_color_key() - set the transparent color key for SDC graphic plane.
575 * @mx3fb: mx3fb context.
576 * @channel: IPU DMAC channel ID.
577 * @enable: boolean to enable or disable color keyl.
578 * @color_key: 24-bit RGB color to use as transparent color key.
579 * @return: 0 on success or negative error code on failure.
580 */
581static int sdc_set_color_key(struct mx3fb_data *mx3fb, enum ipu_channel channel,
582 bool enable, uint32_t color_key)
583{
584 uint32_t reg, sdc_conf;
585 unsigned long lock_flags;
586
587 spin_lock_irqsave(&mx3fb->lock, lock_flags);
588
589 sdc_conf = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
590 if (channel == IDMAC_SDC_0)
591 sdc_conf &= ~SDC_COM_GWSEL;
592 else
593 sdc_conf |= SDC_COM_GWSEL;
594
595 if (enable) {
596 reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0xFF000000L;
597 mx3fb_write_reg(mx3fb, reg | (color_key & 0x00FFFFFFL),
598 SDC_GW_CTRL);
599
600 sdc_conf |= SDC_COM_KEY_COLOR_G;
601 } else {
602 sdc_conf &= ~SDC_COM_KEY_COLOR_G;
603 }
604 mx3fb_write_reg(mx3fb, sdc_conf, SDC_COM_CONF);
605
606 spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
607
608 return 0;
609}
610
611/**
612 * sdc_set_global_alpha() - set global alpha blending modes.
613 * @mx3fb: mx3fb context.
614 * @enable: boolean to enable or disable global alpha blending. If disabled,
615 * per pixel blending is used.
616 * @alpha: global alpha value.
617 * @return: 0 on success or negative error code on failure.
618 */
619static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t alpha)
620{
621 uint32_t reg;
622 unsigned long lock_flags;
623
624 spin_lock_irqsave(&mx3fb->lock, lock_flags);
625
626 if (enable) {
627 reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0x00FFFFFFL;
628 mx3fb_write_reg(mx3fb, reg | ((uint32_t) alpha << 24), SDC_GW_CTRL);
629
630 reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
631 mx3fb_write_reg(mx3fb, reg | SDC_COM_GLB_A, SDC_COM_CONF);
632 } else {
633 reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
634 mx3fb_write_reg(mx3fb, reg & ~SDC_COM_GLB_A, SDC_COM_CONF);
635 }
636
637 spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
638
639 return 0;
640}
641
642static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
643{
644 /* This might be board-specific */
645 mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
646 return;
647}
648
649static uint32_t bpp_to_pixfmt(int bpp)
650{
651 uint32_t pixfmt = 0;
652 switch (bpp) {
653 case 24:
654 pixfmt = IPU_PIX_FMT_BGR24;
655 break;
656 case 32:
657 pixfmt = IPU_PIX_FMT_BGR32;
658 break;
659 case 16:
660 pixfmt = IPU_PIX_FMT_RGB565;
661 break;
662 }
663 return pixfmt;
664}
665
666static int mx3fb_blank(int blank, struct fb_info *fbi);
667static int mx3fb_map_video_memory(struct fb_info *fbi);
668static int mx3fb_unmap_video_memory(struct fb_info *fbi);
669
670/**
671 * mx3fb_set_fix() - set fixed framebuffer parameters from variable settings.
672 * @info: framebuffer information pointer
673 * @return: 0 on success or negative error code on failure.
674 */
675static int mx3fb_set_fix(struct fb_info *fbi)
676{
677 struct fb_fix_screeninfo *fix = &fbi->fix;
678 struct fb_var_screeninfo *var = &fbi->var;
679
680 strncpy(fix->id, "DISP3 BG", 8);
681
682 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
683
684 fix->type = FB_TYPE_PACKED_PIXELS;
685 fix->accel = FB_ACCEL_NONE;
686 fix->visual = FB_VISUAL_TRUECOLOR;
687 fix->xpanstep = 1;
688 fix->ypanstep = 1;
689
690 return 0;
691}
692
693static void mx3fb_dma_done(void *arg)
694{
695 struct idmac_tx_desc *tx_desc = to_tx_desc(arg);
696 struct dma_chan *chan = tx_desc->txd.chan;
697 struct idmac_channel *ichannel = to_idmac_chan(chan);
698 struct mx3fb_data *mx3fb = ichannel->client;
699 struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
700
701 dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq);
702
703 /* We only need one interrupt, it will be re-enabled as needed */
704 disable_irq(ichannel->eof_irq);
705
706 complete(&mx3_fbi->flip_cmpl);
707}
708
709/**
710 * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
711 * @fbi: framebuffer information pointer.
712 * @return: 0 on success or negative error code on failure.
713 */
714static int mx3fb_set_par(struct fb_info *fbi)
715{
716 u32 mem_len;
717 struct ipu_di_signal_cfg sig_cfg;
718 enum ipu_panel mode = IPU_PANEL_TFT;
719 struct mx3fb_info *mx3_fbi = fbi->par;
720 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
721 struct idmac_channel *ichan = mx3_fbi->idmac_channel;
722 struct idmac_video_param *video = &ichan->params.video;
723 struct scatterlist *sg = mx3_fbi->sg;
724 size_t screen_size;
725
726 dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
727
728 mutex_lock(&mx3_fbi->mutex);
729
730 /* Total cleanup */
731 if (mx3_fbi->txd)
732 sdc_disable_channel(mx3_fbi);
733
734 mx3fb_set_fix(fbi);
735
736 mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
737 if (mem_len > fbi->fix.smem_len) {
738 if (fbi->fix.smem_start)
739 mx3fb_unmap_video_memory(fbi);
740
741 fbi->fix.smem_len = mem_len;
742 if (mx3fb_map_video_memory(fbi) < 0) {
743 mutex_unlock(&mx3_fbi->mutex);
744 return -ENOMEM;
745 }
746 }
747
748 screen_size = fbi->fix.line_length * fbi->var.yres;
749
750 sg_init_table(&sg[0], 1);
751 sg_init_table(&sg[1], 1);
752
753 sg_dma_address(&sg[0]) = fbi->fix.smem_start;
754 sg_set_page(&sg[0], virt_to_page(fbi->screen_base),
755 fbi->fix.smem_len,
756 offset_in_page(fbi->screen_base));
757
758 if (mx3_fbi->ipu_ch == IDMAC_SDC_0) {
759 memset(&sig_cfg, 0, sizeof(sig_cfg));
760 if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
761 sig_cfg.Hsync_pol = true;
762 if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
763 sig_cfg.Vsync_pol = true;
764 if (fbi->var.sync & FB_SYNC_CLK_INVERT)
765 sig_cfg.clk_pol = true;
766 if (fbi->var.sync & FB_SYNC_DATA_INVERT)
767 sig_cfg.data_pol = true;
768 if (fbi->var.sync & FB_SYNC_OE_ACT_HIGH)
769 sig_cfg.enable_pol = true;
770 if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
771 sig_cfg.clkidle_en = true;
772 if (fbi->var.sync & FB_SYNC_CLK_SEL_EN)
773 sig_cfg.clksel_en = true;
774 if (fbi->var.sync & FB_SYNC_SHARP_MODE)
775 mode = IPU_PANEL_SHARP_TFT;
776
777 dev_dbg(fbi->device, "pixclock = %ul Hz\n",
778 (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
779
780 if (sdc_init_panel(mx3fb, mode,
781 (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
782 fbi->var.xres, fbi->var.yres,
783 (fbi->var.sync & FB_SYNC_SWAP_RGB) ?
784 IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,
785 fbi->var.left_margin,
786 fbi->var.hsync_len,
787 fbi->var.right_margin +
788 fbi->var.hsync_len,
789 fbi->var.upper_margin,
790 fbi->var.vsync_len,
791 fbi->var.lower_margin +
792 fbi->var.vsync_len, sig_cfg) != 0) {
793 mutex_unlock(&mx3_fbi->mutex);
794 dev_err(fbi->device,
795 "mx3fb: Error initializing panel.\n");
796 return -EINVAL;
797 }
798 }
799
800 sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0);
801
802 mx3_fbi->cur_ipu_buf = 0;
803
804 video->out_pixel_fmt = bpp_to_pixfmt(fbi->var.bits_per_pixel);
805 video->out_width = fbi->var.xres;
806 video->out_height = fbi->var.yres;
807 video->out_stride = fbi->var.xres_virtual;
808
809 if (mx3_fbi->blank == FB_BLANK_UNBLANK)
810 sdc_enable_channel(mx3_fbi);
811
812 mutex_unlock(&mx3_fbi->mutex);
813
814 return 0;
815}
816
817/**
818 * mx3fb_check_var() - check and adjust framebuffer variable parameters.
819 * @var: framebuffer variable parameters
820 * @fbi: framebuffer information pointer
821 */
822static int mx3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
823{
824 struct mx3fb_info *mx3_fbi = fbi->par;
825 u32 vtotal;
826 u32 htotal;
827
828 dev_dbg(fbi->device, "%s\n", __func__);
829
830 if (var->xres_virtual < var->xres)
831 var->xres_virtual = var->xres;
832 if (var->yres_virtual < var->yres)
833 var->yres_virtual = var->yres;
834
835 if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
836 (var->bits_per_pixel != 16))
837 var->bits_per_pixel = default_bpp;
838
839 switch (var->bits_per_pixel) {
840 case 16:
841 var->red.length = 5;
842 var->red.offset = 11;
843 var->red.msb_right = 0;
844
845 var->green.length = 6;
846 var->green.offset = 5;
847 var->green.msb_right = 0;
848
849 var->blue.length = 5;
850 var->blue.offset = 0;
851 var->blue.msb_right = 0;
852
853 var->transp.length = 0;
854 var->transp.offset = 0;
855 var->transp.msb_right = 0;
856 break;
857 case 24:
858 var->red.length = 8;
859 var->red.offset = 16;
860 var->red.msb_right = 0;
861
862 var->green.length = 8;
863 var->green.offset = 8;
864 var->green.msb_right = 0;
865
866 var->blue.length = 8;
867 var->blue.offset = 0;
868 var->blue.msb_right = 0;
869
870 var->transp.length = 0;
871 var->transp.offset = 0;
872 var->transp.msb_right = 0;
873 break;
874 case 32:
875 var->red.length = 8;
876 var->red.offset = 16;
877 var->red.msb_right = 0;
878
879 var->green.length = 8;
880 var->green.offset = 8;
881 var->green.msb_right = 0;
882
883 var->blue.length = 8;
884 var->blue.offset = 0;
885 var->blue.msb_right = 0;
886
887 var->transp.length = 8;
888 var->transp.offset = 24;
889 var->transp.msb_right = 0;
890 break;
891 }
892
893 if (var->pixclock < 1000) {
894 htotal = var->xres + var->right_margin + var->hsync_len +
895 var->left_margin;
896 vtotal = var->yres + var->lower_margin + var->vsync_len +
897 var->upper_margin;
898 var->pixclock = (vtotal * htotal * 6UL) / 100UL;
899 var->pixclock = KHZ2PICOS(var->pixclock);
900 dev_dbg(fbi->device, "pixclock set for 60Hz refresh = %u ps\n",
901 var->pixclock);
902 }
903
904 var->height = -1;
905 var->width = -1;
906 var->grayscale = 0;
907
908 /* Preserve sync flags */
909 var->sync |= mx3_fbi->sync;
910 mx3_fbi->sync |= var->sync;
911
912 return 0;
913}
914
915static u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf)
916{
917 chan &= 0xffff;
918 chan >>= 16 - bf->length;
919 return chan << bf->offset;
920}
921
922static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
923 unsigned int green, unsigned int blue,
924 unsigned int trans, struct fb_info *fbi)
925{
926 struct mx3fb_info *mx3_fbi = fbi->par;
927 u32 val;
928 int ret = 1;
929
930 dev_dbg(fbi->device, "%s\n", __func__);
931
932 mutex_lock(&mx3_fbi->mutex);
933 /*
934 * If greyscale is true, then we convert the RGB value
935 * to greyscale no matter what visual we are using.
936 */
937 if (fbi->var.grayscale)
938 red = green = blue = (19595 * red + 38470 * green +
939 7471 * blue) >> 16;
940 switch (fbi->fix.visual) {
941 case FB_VISUAL_TRUECOLOR:
942 /*
943 * 16-bit True Colour. We encode the RGB value
944 * according to the RGB bitfield information.
945 */
946 if (regno < 16) {
947 u32 *pal = fbi->pseudo_palette;
948
949 val = chan_to_field(red, &fbi->var.red);
950 val |= chan_to_field(green, &fbi->var.green);
951 val |= chan_to_field(blue, &fbi->var.blue);
952
953 pal[regno] = val;
954
955 ret = 0;
956 }
957 break;
958
959 case FB_VISUAL_STATIC_PSEUDOCOLOR:
960 case FB_VISUAL_PSEUDOCOLOR:
961 break;
962 }
963 mutex_unlock(&mx3_fbi->mutex);
964
965 return ret;
966}
967
968/**
969 * mx3fb_blank() - blank the display.
970 */
971static int mx3fb_blank(int blank, struct fb_info *fbi)
972{
973 struct mx3fb_info *mx3_fbi = fbi->par;
974 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
975
976 dev_dbg(fbi->device, "%s\n", __func__);
977
978 dev_dbg(fbi->device, "blank = %d\n", blank);
979
980 if (mx3_fbi->blank == blank)
981 return 0;
982
983 mutex_lock(&mx3_fbi->mutex);
984 mx3_fbi->blank = blank;
985
986 switch (blank) {
987 case FB_BLANK_POWERDOWN:
988 case FB_BLANK_VSYNC_SUSPEND:
989 case FB_BLANK_HSYNC_SUSPEND:
990 case FB_BLANK_NORMAL:
991 sdc_disable_channel(mx3_fbi);
992 sdc_set_brightness(mx3fb, 0);
993 break;
994 case FB_BLANK_UNBLANK:
995 sdc_enable_channel(mx3_fbi);
996 sdc_set_brightness(mx3fb, mx3fb->backlight_level);
997 break;
998 }
999 mutex_unlock(&mx3_fbi->mutex);
1000
1001 return 0;
1002}
1003
1004/**
1005 * mx3fb_pan_display() - pan or wrap the display
1006 * @var: variable screen buffer information.
1007 * @info: framebuffer information pointer.
1008 *
1009 * We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1010 */
1011static int mx3fb_pan_display(struct fb_var_screeninfo *var,
1012 struct fb_info *fbi)
1013{
1014 struct mx3fb_info *mx3_fbi = fbi->par;
1015 u32 y_bottom;
1016 unsigned long base;
1017 off_t offset;
1018 dma_cookie_t cookie;
1019 struct scatterlist *sg = mx3_fbi->sg;
1020 struct dma_chan *dma_chan = &mx3_fbi->idmac_channel->dma_chan;
1021 struct dma_async_tx_descriptor *txd;
1022 int ret;
1023
1024 dev_dbg(fbi->device, "%s [%c]\n", __func__,
1025 list_empty(&mx3_fbi->idmac_channel->queue) ? '-' : '+');
1026
1027 if (var->xoffset > 0) {
1028 dev_dbg(fbi->device, "x panning not supported\n");
1029 return -EINVAL;
1030 }
1031
1032 if (fbi->var.xoffset == var->xoffset &&
1033 fbi->var.yoffset == var->yoffset)
1034 return 0; /* No change, do nothing */
1035
1036 y_bottom = var->yoffset;
1037
1038 if (!(var->vmode & FB_VMODE_YWRAP))
1039 y_bottom += var->yres;
1040
1041 if (y_bottom > fbi->var.yres_virtual)
1042 return -EINVAL;
1043
1044 mutex_lock(&mx3_fbi->mutex);
1045
1046 offset = (var->yoffset * var->xres_virtual + var->xoffset) *
1047 (var->bits_per_pixel / 8);
1048 base = fbi->fix.smem_start + offset;
1049
1050 dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",
1051 mx3_fbi->cur_ipu_buf, base);
1052
1053 /*
1054 * We enable the End of Frame interrupt, which will free a tx-descriptor,
1055 * which we will need for the next device_prep_slave_sg(). The
1056 * IRQ-handler will disable the IRQ again.
1057 */
1058 init_completion(&mx3_fbi->flip_cmpl);
1059 enable_irq(mx3_fbi->idmac_channel->eof_irq);
1060
1061 ret = wait_for_completion_timeout(&mx3_fbi->flip_cmpl, HZ / 10);
1062 if (ret <= 0) {
1063 mutex_unlock(&mx3_fbi->mutex);
1064 dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ?
1065 "user interrupt" : "timeout");
1066 return ret ? : -ETIMEDOUT;
1067 }
1068
1069 mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf;
1070
1071 sg_dma_address(&sg[mx3_fbi->cur_ipu_buf]) = base;
1072 sg_set_page(&sg[mx3_fbi->cur_ipu_buf],
1073 virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len,
1074 offset_in_page(fbi->screen_base + offset));
1075
1076 txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
1077 mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
1078 if (!txd) {
1079 dev_err(fbi->device,
1080 "Error preparing a DMA transaction descriptor.\n");
1081 mutex_unlock(&mx3_fbi->mutex);
1082 return -EIO;
1083 }
1084
1085 txd->callback_param = txd;
1086 txd->callback = mx3fb_dma_done;
1087
1088 /*
1089 * Emulate original mx3fb behaviour: each new call to idmac_tx_submit()
1090 * should switch to another buffer
1091 */
1092 cookie = txd->tx_submit(txd);
1093 dev_dbg(fbi->device, "%d: Submit %p #%d\n", __LINE__, txd, cookie);
1094 if (cookie < 0) {
1095 dev_err(fbi->device,
1096 "Error updating SDC buf %d to address=0x%08lX\n",
1097 mx3_fbi->cur_ipu_buf, base);
1098 mutex_unlock(&mx3_fbi->mutex);
1099 return -EIO;
1100 }
1101
1102 if (mx3_fbi->txd)
1103 async_tx_ack(mx3_fbi->txd);
1104 mx3_fbi->txd = txd;
1105
1106 fbi->var.xoffset = var->xoffset;
1107 fbi->var.yoffset = var->yoffset;
1108
1109 if (var->vmode & FB_VMODE_YWRAP)
1110 fbi->var.vmode |= FB_VMODE_YWRAP;
1111 else
1112 fbi->var.vmode &= ~FB_VMODE_YWRAP;
1113
1114 mutex_unlock(&mx3_fbi->mutex);
1115
1116 dev_dbg(fbi->device, "Update complete\n");
1117
1118 return 0;
1119}
1120
1121/*
1122 * This structure contains the pointers to the control functions that are
1123 * invoked by the core framebuffer driver to perform operations like
1124 * blitting, rectangle filling, copy regions and cursor definition.
1125 */
1126static struct fb_ops mx3fb_ops = {
1127 .owner = THIS_MODULE,
1128 .fb_set_par = mx3fb_set_par,
1129 .fb_check_var = mx3fb_check_var,
1130 .fb_setcolreg = mx3fb_setcolreg,
1131 .fb_pan_display = mx3fb_pan_display,
1132 .fb_fillrect = cfb_fillrect,
1133 .fb_copyarea = cfb_copyarea,
1134 .fb_imageblit = cfb_imageblit,
1135 .fb_blank = mx3fb_blank,
1136};
1137
1138#ifdef CONFIG_PM
1139/*
1140 * Power management hooks. Note that we won't be called from IRQ context,
1141 * unlike the blank functions above, so we may sleep.
1142 */
1143
1144/*
1145 * Suspends the framebuffer and blanks the screen. Power management support
1146 */
1147static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
1148{
1149 struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
1150 struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
1151
1152 acquire_console_sem();
1153 fb_set_suspend(drv_data->fbi, 1);
1154 release_console_sem();
1155
1156 if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
1157 sdc_disable_channel(mx3_fbi);
1158 sdc_set_brightness(mx3fb, 0);
1159
1160 }
1161 return 0;
1162}
1163
1164/*
1165 * Resumes the framebuffer and unblanks the screen. Power management support
1166 */
1167static int mx3fb_resume(struct platform_device *pdev)
1168{
1169 struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
1170 struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
1171
1172 if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
1173 sdc_enable_channel(mx3_fbi);
1174 sdc_set_brightness(mx3fb, drv_data->backlight_level);
1175 }
1176
1177 acquire_console_sem();
1178 fb_set_suspend(drv_data->fbi, 0);
1179 release_console_sem();
1180
1181 return 0;
1182}
1183#else
1184#define mx3fb_suspend NULL
1185#define mx3fb_resume NULL
1186#endif
1187
1188/*
1189 * Main framebuffer functions
1190 */
1191
1192/**
1193 * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
1194 * @fbi: framebuffer information pointer
1195 * @return: Error code indicating success or failure
1196 *
1197 * This buffer is remapped into a non-cached, non-buffered, memory region to
1198 * allow palette and pixel writes to occur without flushing the cache. Once this
1199 * area is remapped, all virtual memory access to the video memory should occur
1200 * at the new region.
1201 */
1202static int mx3fb_map_video_memory(struct fb_info *fbi)
1203{
1204 int retval = 0;
1205 dma_addr_t addr;
1206
1207 fbi->screen_base = dma_alloc_writecombine(fbi->device,
1208 fbi->fix.smem_len,
1209 &addr, GFP_DMA);
1210
1211 if (!fbi->screen_base) {
1212 dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
1213 fbi->fix.smem_len);
1214 retval = -EBUSY;
1215 goto err0;
1216 }
1217
1218 fbi->fix.smem_start = addr;
1219
1220 dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
1221 (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
1222
1223 fbi->screen_size = fbi->fix.smem_len;
1224
1225 /* Clear the screen */
1226 memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
1227
1228 return 0;
1229
1230err0:
1231 fbi->fix.smem_len = 0;
1232 fbi->fix.smem_start = 0;
1233 fbi->screen_base = NULL;
1234 return retval;
1235}
1236
1237/**
1238 * mx3fb_unmap_video_memory() - de-allocate frame buffer memory.
1239 * @fbi: framebuffer information pointer
1240 * @return: error code indicating success or failure
1241 */
1242static int mx3fb_unmap_video_memory(struct fb_info *fbi)
1243{
1244 dma_free_writecombine(fbi->device, fbi->fix.smem_len,
1245 fbi->screen_base, fbi->fix.smem_start);
1246
1247 fbi->screen_base = 0;
1248 fbi->fix.smem_start = 0;
1249 fbi->fix.smem_len = 0;
1250 return 0;
1251}
1252
1253/**
1254 * mx3fb_init_fbinfo() - initialize framebuffer information object.
1255 * @return: initialized framebuffer structure.
1256 */
1257static struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops)
1258{
1259 struct fb_info *fbi;
1260 struct mx3fb_info *mx3fbi;
1261 int ret;
1262
1263 /* Allocate sufficient memory for the fb structure */
1264 fbi = framebuffer_alloc(sizeof(struct mx3fb_info), dev);
1265 if (!fbi)
1266 return NULL;
1267
1268 mx3fbi = fbi->par;
1269 mx3fbi->cookie = -EINVAL;
1270 mx3fbi->cur_ipu_buf = 0;
1271
1272 fbi->var.activate = FB_ACTIVATE_NOW;
1273
1274 fbi->fbops = ops;
1275 fbi->flags = FBINFO_FLAG_DEFAULT;
1276 fbi->pseudo_palette = mx3fbi->pseudo_palette;
1277
1278 mutex_init(&mx3fbi->mutex);
1279
1280 /* Allocate colormap */
1281 ret = fb_alloc_cmap(&fbi->cmap, 16, 0);
1282 if (ret < 0) {
1283 framebuffer_release(fbi);
1284 return NULL;
1285 }
1286
1287 return fbi;
1288}
1289
1290static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
1291{
1292 struct device *dev = mx3fb->dev;
1293 struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data;
1294 const char *name = mx3fb_pdata->name;
1295 unsigned int irq;
1296 struct fb_info *fbi;
1297 struct mx3fb_info *mx3fbi;
1298 const struct fb_videomode *mode;
1299 int ret, num_modes;
1300
1301 ichan->client = mx3fb;
1302 irq = ichan->eof_irq;
1303
1304 if (ichan->dma_chan.chan_id != IDMAC_SDC_0)
1305 return -EINVAL;
1306
1307 fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops);
1308 if (!fbi)
1309 return -ENOMEM;
1310
1311 if (!fb_mode)
1312 fb_mode = name;
1313
1314 if (!fb_mode) {
1315 ret = -EINVAL;
1316 goto emode;
1317 }
1318
1319 if (mx3fb_pdata->mode && mx3fb_pdata->num_modes) {
1320 mode = mx3fb_pdata->mode;
1321 num_modes = mx3fb_pdata->num_modes;
1322 } else {
1323 mode = mx3fb_modedb;
1324 num_modes = ARRAY_SIZE(mx3fb_modedb);
1325 }
1326
1327 if (!fb_find_mode(&fbi->var, fbi, fb_mode, mode,
1328 num_modes, NULL, default_bpp)) {
1329 ret = -EBUSY;
1330 goto emode;
1331 }
1332
1333 fb_videomode_to_modelist(mode, num_modes, &fbi->modelist);
1334
1335 /* Default Y virtual size is 2x panel size */
1336 fbi->var.yres_virtual = fbi->var.yres * 2;
1337
1338 mx3fb->fbi = fbi;
1339
1340 /* set Display Interface clock period */
1341 mx3fb_write_reg(mx3fb, 0x00100010L, DI_HSP_CLK_PER);
1342 /* Might need to trigger HSP clock change - see 44.3.3.8.5 */
1343
1344 sdc_set_brightness(mx3fb, 255);
1345 sdc_set_global_alpha(mx3fb, true, 0xFF);
1346 sdc_set_color_key(mx3fb, IDMAC_SDC_0, false, 0);
1347
1348 mx3fbi = fbi->par;
1349 mx3fbi->idmac_channel = ichan;
1350 mx3fbi->ipu_ch = ichan->dma_chan.chan_id;
1351 mx3fbi->mx3fb = mx3fb;
1352 mx3fbi->blank = FB_BLANK_NORMAL;
1353
1354 init_completion(&mx3fbi->flip_cmpl);
1355 disable_irq(ichan->eof_irq);
1356 dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
1357 ret = mx3fb_set_par(fbi);
1358 if (ret < 0)
1359 goto esetpar;
1360
1361 mx3fb_blank(FB_BLANK_UNBLANK, fbi);
1362
1363 dev_info(dev, "mx3fb: fb registered, using mode %s\n", fb_mode);
1364
1365 ret = register_framebuffer(fbi);
1366 if (ret < 0)
1367 goto erfb;
1368
1369 return 0;
1370
1371erfb:
1372esetpar:
1373emode:
1374 fb_dealloc_cmap(&fbi->cmap);
1375 framebuffer_release(fbi);
1376
1377 return ret;
1378}
1379
1380static bool chan_filter(struct dma_chan *chan, void *arg)
1381{
1382 struct dma_chan_request *rq = arg;
1383 struct device *dev;
1384 struct mx3fb_platform_data *mx3fb_pdata;
1385
1386 if (!rq)
1387 return false;
1388
1389 dev = rq->mx3fb->dev;
1390 mx3fb_pdata = dev->platform_data;
1391
1392 return rq->id == chan->chan_id &&
1393 mx3fb_pdata->dma_dev == chan->device->dev;
1394}
1395
1396static void release_fbi(struct fb_info *fbi)
1397{
1398 mx3fb_unmap_video_memory(fbi);
1399
1400 fb_dealloc_cmap(&fbi->cmap);
1401
1402 unregister_framebuffer(fbi);
1403 framebuffer_release(fbi);
1404}
1405
1406static int mx3fb_probe(struct platform_device *pdev)
1407{
1408 struct device *dev = &pdev->dev;
1409 int ret;
1410 struct resource *sdc_reg;
1411 struct mx3fb_data *mx3fb;
1412 dma_cap_mask_t mask;
1413 struct dma_chan *chan;
1414 struct dma_chan_request rq;
1415
1416 /*
1417 * Display Interface (DI) and Synchronous Display Controller (SDC)
1418 * registers
1419 */
1420 sdc_reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1421 if (!sdc_reg)
1422 return -EINVAL;
1423
1424 mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL);
1425 if (!mx3fb)
1426 return -ENOMEM;
1427
1428 spin_lock_init(&mx3fb->lock);
1429
1430 mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg));
1431 if (!mx3fb->reg_base) {
1432 ret = -ENOMEM;
1433 goto eremap;
1434 }
1435
1436 pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end,
1437 mx3fb->reg_base);
1438
1439 /* IDMAC interface */
1440 dmaengine_get();
1441
1442 mx3fb->dev = dev;
1443 platform_set_drvdata(pdev, mx3fb);
1444
1445 rq.mx3fb = mx3fb;
1446
1447 dma_cap_zero(mask);
1448 dma_cap_set(DMA_SLAVE, mask);
1449 dma_cap_set(DMA_PRIVATE, mask);
1450 rq.id = IDMAC_SDC_0;
1451 chan = dma_request_channel(mask, chan_filter, &rq);
1452 if (!chan) {
1453 ret = -EBUSY;
1454 goto ersdc0;
1455 }
1456
1457 ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
1458 if (ret < 0)
1459 goto eisdc0;
1460
1461 mx3fb->backlight_level = 255;
1462
1463 return 0;
1464
1465eisdc0:
1466 dma_release_channel(chan);
1467ersdc0:
1468 dmaengine_put();
1469 iounmap(mx3fb->reg_base);
1470eremap:
1471 kfree(mx3fb);
1472 dev_err(dev, "mx3fb: failed to register fb\n");
1473 return ret;
1474}
1475
1476static int mx3fb_remove(struct platform_device *dev)
1477{
1478 struct mx3fb_data *mx3fb = platform_get_drvdata(dev);
1479 struct fb_info *fbi = mx3fb->fbi;
1480 struct mx3fb_info *mx3_fbi = fbi->par;
1481 struct dma_chan *chan;
1482
1483 chan = &mx3_fbi->idmac_channel->dma_chan;
1484 release_fbi(fbi);
1485
1486 dma_release_channel(chan);
1487 dmaengine_put();
1488
1489 iounmap(mx3fb->reg_base);
1490 kfree(mx3fb);
1491 return 0;
1492}
1493
1494static struct platform_driver mx3fb_driver = {
1495 .driver = {
1496 .name = MX3FB_NAME,
1497 },
1498 .probe = mx3fb_probe,
1499 .remove = mx3fb_remove,
1500 .suspend = mx3fb_suspend,
1501 .resume = mx3fb_resume,
1502};
1503
1504/*
1505 * Parse user specified options (`video=mx3fb:')
1506 * example:
1507 * video=mx3fb:bpp=16
1508 */
1509static int mx3fb_setup(void)
1510{
1511#ifndef MODULE
1512 char *opt, *options = NULL;
1513
1514 if (fb_get_options("mx3fb", &options))
1515 return -ENODEV;
1516
1517 if (!options || !*options)
1518 return 0;
1519
1520 while ((opt = strsep(&options, ",")) != NULL) {
1521 if (!*opt)
1522 continue;
1523 if (!strncmp(opt, "bpp=", 4))
1524 default_bpp = simple_strtoul(opt + 4, NULL, 0);
1525 else
1526 fb_mode = opt;
1527 }
1528#endif
1529
1530 return 0;
1531}
1532
1533static int __init mx3fb_init(void)
1534{
1535 int ret = mx3fb_setup();
1536
1537 if (ret < 0)
1538 return ret;
1539
1540 ret = platform_driver_register(&mx3fb_driver);
1541 return ret;
1542}
1543
1544static void __exit mx3fb_exit(void)
1545{
1546 platform_driver_unregister(&mx3fb_driver);
1547}
1548
1549module_init(mx3fb_init);
1550module_exit(mx3fb_exit);
1551
1552MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1553MODULE_DESCRIPTION("MX3 framebuffer driver");
1554MODULE_ALIAS("platform:" MX3FB_NAME);
1555MODULE_LICENSE("GPL v2");