Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
3879f5d6
Commit
3879f5d6
authored
Mar 16, 2009
by
Russell King
Committed by
Russell King
Mar 16, 2009
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'imx-fb-fix' of
git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx
into devel
Conflicts: drivers/video/mx3fb.c
parents
607b067e
6e1588cb
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1174 additions
and
1174 deletions
+1174
-1174
arch/arm/plat-mxc/include/mach/mx3fb.h
arch/arm/plat-mxc/include/mach/mx3fb.h
+13
-13
drivers/video/Kconfig
drivers/video/Kconfig
+10
-10
drivers/video/Makefile
drivers/video/Makefile
+1
-1
drivers/video/mx3fb.c
drivers/video/mx3fb.c
+1150
-1150
No files found.
arch/arm/plat-mxc/include/mach/mx3fb.h
View file @
3879f5d6
...
@@ -14,25 +14,25 @@
...
@@ -14,25 +14,25 @@
#include <linux/fb.h>
#include <linux/fb.h>
/* Proprietary FB_SYNC_ flags */
/* Proprietary FB_SYNC_ flags */
#define FB_SYNC_OE_ACT_HIGH
0x80000000
#define FB_SYNC_OE_ACT_HIGH
0x80000000
#define FB_SYNC_CLK_INVERT
0x40000000
#define FB_SYNC_CLK_INVERT
0x40000000
#define FB_SYNC_DATA_INVERT
0x20000000
#define FB_SYNC_DATA_INVERT
0x20000000
#define FB_SYNC_CLK_IDLE_EN
0x10000000
#define FB_SYNC_CLK_IDLE_EN
0x10000000
#define FB_SYNC_SHARP_MODE
0x08000000
#define FB_SYNC_SHARP_MODE
0x08000000
#define FB_SYNC_SWAP_RGB
0x04000000
#define FB_SYNC_SWAP_RGB
0x04000000
#define FB_SYNC_CLK_SEL_EN
0x02000000
#define FB_SYNC_CLK_SEL_EN
0x02000000
/**
/**
* struct mx3fb_platform_data - mx3fb platform data
* struct mx3fb_platform_data - mx3fb platform data
*
*
* @dma_dev:
pointer to the dma-device, used for dma-slave connection
* @dma_dev:
pointer to the dma-device, used for dma-slave connection
* @mode:
pointer to a platform-provided per mxc_register_fb() videomode
* @mode:
pointer to a platform-provided per mxc_register_fb() videomode
*/
*/
struct
mx3fb_platform_data
{
struct
mx3fb_platform_data
{
struct
device
*
dma_dev
;
struct
device
*
dma_dev
;
const
char
*
name
;
const
char
*
name
;
const
struct
fb_videomode
*
mode
;
const
struct
fb_videomode
*
mode
;
int
num_modes
;
int
num_modes
;
};
};
#endif
#endif
drivers/video/Kconfig
View file @
3879f5d6
...
@@ -2120,16 +2120,16 @@ config FB_PRE_INIT_FB
...
@@ -2120,16 +2120,16 @@ config FB_PRE_INIT_FB
the bootloader.
the bootloader.
config FB_MX3
config FB_MX3
tristate "MX3 Framebuffer support"
tristate "MX3 Framebuffer support"
depends on FB && MX3_IPU
depends on FB && MX3_IPU
select FB_CFB_FILLRECT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_CFB_IMAGEBLIT
default y
default y
help
help
This is a framebuffer device for the i.MX31 LCD Controller. So
This is a framebuffer device for the i.MX31 LCD Controller. So
far only synchronous displays are supported. If you plan to use
far only synchronous displays are supported. If you plan to use
an LCD display with your i.MX31 system, say Y here.
an LCD display with your i.MX31 system, say Y here.
config FB_BROADSHEET
config FB_BROADSHEET
tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
...
...
drivers/video/Makefile
View file @
3879f5d6
...
@@ -133,7 +133,7 @@ obj-$(CONFIG_FB_VGA16) += vga16fb.o
...
@@ -133,7 +133,7 @@ obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF)
+=
offb.o
obj-$(CONFIG_FB_OF)
+=
offb.o
obj-$(CONFIG_FB_BF54X_LQ043)
+=
bf54x-lq043fb.o
obj-$(CONFIG_FB_BF54X_LQ043)
+=
bf54x-lq043fb.o
obj-$(CONFIG_FB_BFIN_T350MCQB)
+=
bfin-t350mcqb-fb.o
obj-$(CONFIG_FB_BFIN_T350MCQB)
+=
bfin-t350mcqb-fb.o
obj-$(CONFIG_FB_MX3)
+=
mx3fb.o
obj-$(CONFIG_FB_MX3)
+=
mx3fb.o
# the test framebuffer is last
# the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL)
+=
vfb.o
obj-$(CONFIG_FB_VIRTUAL)
+=
vfb.o
...
...
drivers/video/mx3fb.c
View file @
3879f5d6
...
@@ -34,240 +34,240 @@
...
@@ -34,240 +34,240 @@
#include <asm/io.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#define MX3FB_NAME
"mx3_sdc_fb"
#define MX3FB_NAME
"mx3_sdc_fb"
#define MX3FB_REG_OFFSET
0xB4
#define MX3FB_REG_OFFSET
0xB4
/* SDC Registers */
/* SDC Registers */
#define SDC_COM_CONF
(0xB4 - MX3FB_REG_OFFSET)
#define SDC_COM_CONF
(0xB4 - MX3FB_REG_OFFSET)
#define SDC_GW_CTRL
(0xB8 - MX3FB_REG_OFFSET)
#define SDC_GW_CTRL
(0xB8 - MX3FB_REG_OFFSET)
#define SDC_FG_POS
(0xBC - MX3FB_REG_OFFSET)
#define SDC_FG_POS
(0xBC - MX3FB_REG_OFFSET)
#define SDC_BG_POS
(0xC0 - MX3FB_REG_OFFSET)
#define SDC_BG_POS
(0xC0 - MX3FB_REG_OFFSET)
#define SDC_CUR_POS
(0xC4 - MX3FB_REG_OFFSET)
#define SDC_CUR_POS
(0xC4 - MX3FB_REG_OFFSET)
#define SDC_PWM_CTRL
(0xC8 - MX3FB_REG_OFFSET)
#define SDC_PWM_CTRL
(0xC8 - MX3FB_REG_OFFSET)
#define SDC_CUR_MAP
(0xCC - MX3FB_REG_OFFSET)
#define SDC_CUR_MAP
(0xCC - MX3FB_REG_OFFSET)
#define SDC_HOR_CONF
(0xD0 - MX3FB_REG_OFFSET)
#define SDC_HOR_CONF
(0xD0 - MX3FB_REG_OFFSET)
#define SDC_VER_CONF
(0xD4 - MX3FB_REG_OFFSET)
#define SDC_VER_CONF
(0xD4 - MX3FB_REG_OFFSET)
#define SDC_SHARP_CONF_1
(0xD8 - MX3FB_REG_OFFSET)
#define SDC_SHARP_CONF_1
(0xD8 - MX3FB_REG_OFFSET)
#define SDC_SHARP_CONF_2
(0xDC - MX3FB_REG_OFFSET)
#define SDC_SHARP_CONF_2
(0xDC - MX3FB_REG_OFFSET)
/* Register bits */
/* Register bits */
#define SDC_COM_TFT_COLOR
0x00000001UL
#define SDC_COM_TFT_COLOR
0x00000001UL
#define SDC_COM_FG_EN
0x00000010UL
#define SDC_COM_FG_EN
0x00000010UL
#define SDC_COM_GWSEL
0x00000020UL
#define SDC_COM_GWSEL
0x00000020UL
#define SDC_COM_GLB_A
0x00000040UL
#define SDC_COM_GLB_A
0x00000040UL
#define SDC_COM_KEY_COLOR_G
0x00000080UL
#define SDC_COM_KEY_COLOR_G
0x00000080UL
#define SDC_COM_BG_EN
0x00000200UL
#define SDC_COM_BG_EN
0x00000200UL
#define SDC_COM_SHARP
0x00001000UL
#define SDC_COM_SHARP
0x00001000UL
#define SDC_V_SYNC_WIDTH_L
0x00000001UL
#define SDC_V_SYNC_WIDTH_L
0x00000001UL
/* Display Interface registers */
/* Display Interface registers */
#define DI_DISP_IF_CONF
(0x0124 - MX3FB_REG_OFFSET)
#define DI_DISP_IF_CONF
(0x0124 - MX3FB_REG_OFFSET)
#define DI_DISP_SIG_POL
(0x0128 - MX3FB_REG_OFFSET)
#define DI_DISP_SIG_POL
(0x0128 - MX3FB_REG_OFFSET)
#define DI_SER_DISP1_CONF
(0x012C - MX3FB_REG_OFFSET)
#define DI_SER_DISP1_CONF
(0x012C - MX3FB_REG_OFFSET)
#define DI_SER_DISP2_CONF
(0x0130 - MX3FB_REG_OFFSET)
#define DI_SER_DISP2_CONF
(0x0130 - MX3FB_REG_OFFSET)
#define DI_HSP_CLK_PER
(0x0134 - MX3FB_REG_OFFSET)
#define DI_HSP_CLK_PER
(0x0134 - MX3FB_REG_OFFSET)
#define DI_DISP0_TIME_CONF_1
(0x0138 - MX3FB_REG_OFFSET)
#define DI_DISP0_TIME_CONF_1
(0x0138 - MX3FB_REG_OFFSET)
#define DI_DISP0_TIME_CONF_2
(0x013C - MX3FB_REG_OFFSET)
#define DI_DISP0_TIME_CONF_2
(0x013C - MX3FB_REG_OFFSET)
#define DI_DISP0_TIME_CONF_3
(0x0140 - MX3FB_REG_OFFSET)
#define DI_DISP0_TIME_CONF_3
(0x0140 - MX3FB_REG_OFFSET)
#define DI_DISP1_TIME_CONF_1
(0x0144 - MX3FB_REG_OFFSET)
#define DI_DISP1_TIME_CONF_1
(0x0144 - MX3FB_REG_OFFSET)
#define DI_DISP1_TIME_CONF_2
(0x0148 - MX3FB_REG_OFFSET)
#define DI_DISP1_TIME_CONF_2
(0x0148 - MX3FB_REG_OFFSET)
#define DI_DISP1_TIME_CONF_3
(0x014C - MX3FB_REG_OFFSET)
#define DI_DISP1_TIME_CONF_3
(0x014C - MX3FB_REG_OFFSET)
#define DI_DISP2_TIME_CONF_1
(0x0150 - MX3FB_REG_OFFSET)
#define DI_DISP2_TIME_CONF_1
(0x0150 - MX3FB_REG_OFFSET)
#define DI_DISP2_TIME_CONF_2
(0x0154 - MX3FB_REG_OFFSET)
#define DI_DISP2_TIME_CONF_2
(0x0154 - MX3FB_REG_OFFSET)
#define DI_DISP2_TIME_CONF_3
(0x0158 - MX3FB_REG_OFFSET)
#define DI_DISP2_TIME_CONF_3
(0x0158 - MX3FB_REG_OFFSET)
#define DI_DISP3_TIME_CONF
(0x015C - MX3FB_REG_OFFSET)
#define DI_DISP3_TIME_CONF
(0x015C - MX3FB_REG_OFFSET)
#define DI_DISP0_DB0_MAP
(0x0160 - MX3FB_REG_OFFSET)
#define DI_DISP0_DB0_MAP
(0x0160 - MX3FB_REG_OFFSET)
#define DI_DISP0_DB1_MAP
(0x0164 - MX3FB_REG_OFFSET)
#define DI_DISP0_DB1_MAP
(0x0164 - MX3FB_REG_OFFSET)
#define DI_DISP0_DB2_MAP
(0x0168 - MX3FB_REG_OFFSET)
#define DI_DISP0_DB2_MAP
(0x0168 - MX3FB_REG_OFFSET)
#define DI_DISP0_CB0_MAP
(0x016C - MX3FB_REG_OFFSET)
#define DI_DISP0_CB0_MAP
(0x016C - MX3FB_REG_OFFSET)
#define DI_DISP0_CB1_MAP
(0x0170 - MX3FB_REG_OFFSET)
#define DI_DISP0_CB1_MAP
(0x0170 - MX3FB_REG_OFFSET)
#define DI_DISP0_CB2_MAP
(0x0174 - MX3FB_REG_OFFSET)
#define DI_DISP0_CB2_MAP
(0x0174 - MX3FB_REG_OFFSET)
#define DI_DISP1_DB0_MAP
(0x0178 - MX3FB_REG_OFFSET)
#define DI_DISP1_DB0_MAP
(0x0178 - MX3FB_REG_OFFSET)
#define DI_DISP1_DB1_MAP
(0x017C - MX3FB_REG_OFFSET)
#define DI_DISP1_DB1_MAP
(0x017C - MX3FB_REG_OFFSET)
#define DI_DISP1_DB2_MAP
(0x0180 - MX3FB_REG_OFFSET)
#define DI_DISP1_DB2_MAP
(0x0180 - MX3FB_REG_OFFSET)
#define DI_DISP1_CB0_MAP
(0x0184 - MX3FB_REG_OFFSET)
#define DI_DISP1_CB0_MAP
(0x0184 - MX3FB_REG_OFFSET)
#define DI_DISP1_CB1_MAP
(0x0188 - MX3FB_REG_OFFSET)
#define DI_DISP1_CB1_MAP
(0x0188 - MX3FB_REG_OFFSET)
#define DI_DISP1_CB2_MAP
(0x018C - MX3FB_REG_OFFSET)
#define DI_DISP1_CB2_MAP
(0x018C - MX3FB_REG_OFFSET)
#define DI_DISP2_DB0_MAP
(0x0190 - MX3FB_REG_OFFSET)
#define DI_DISP2_DB0_MAP
(0x0190 - MX3FB_REG_OFFSET)
#define DI_DISP2_DB1_MAP
(0x0194 - MX3FB_REG_OFFSET)
#define DI_DISP2_DB1_MAP
(0x0194 - MX3FB_REG_OFFSET)
#define DI_DISP2_DB2_MAP
(0x0198 - MX3FB_REG_OFFSET)
#define DI_DISP2_DB2_MAP
(0x0198 - MX3FB_REG_OFFSET)
#define DI_DISP2_CB0_MAP
(0x019C - MX3FB_REG_OFFSET)
#define DI_DISP2_CB0_MAP
(0x019C - MX3FB_REG_OFFSET)
#define DI_DISP2_CB1_MAP
(0x01A0 - MX3FB_REG_OFFSET)
#define DI_DISP2_CB1_MAP
(0x01A0 - MX3FB_REG_OFFSET)
#define DI_DISP2_CB2_MAP
(0x01A4 - MX3FB_REG_OFFSET)
#define DI_DISP2_CB2_MAP
(0x01A4 - MX3FB_REG_OFFSET)
#define DI_DISP3_B0_MAP
(0x01A8 - MX3FB_REG_OFFSET)
#define DI_DISP3_B0_MAP
(0x01A8 - MX3FB_REG_OFFSET)
#define DI_DISP3_B1_MAP
(0x01AC - MX3FB_REG_OFFSET)
#define DI_DISP3_B1_MAP
(0x01AC - MX3FB_REG_OFFSET)
#define DI_DISP3_B2_MAP
(0x01B0 - MX3FB_REG_OFFSET)
#define DI_DISP3_B2_MAP
(0x01B0 - MX3FB_REG_OFFSET)
#define DI_DISP_ACC_CC
(0x01B4 - MX3FB_REG_OFFSET)
#define DI_DISP_ACC_CC
(0x01B4 - MX3FB_REG_OFFSET)
#define DI_DISP_LLA_CONF
(0x01B8 - MX3FB_REG_OFFSET)
#define DI_DISP_LLA_CONF
(0x01B8 - MX3FB_REG_OFFSET)
#define DI_DISP_LLA_DATA
(0x01BC - MX3FB_REG_OFFSET)
#define DI_DISP_LLA_DATA
(0x01BC - MX3FB_REG_OFFSET)
/* DI_DISP_SIG_POL bits */
/* DI_DISP_SIG_POL bits */
#define DI_D3_VSYNC_POL_SHIFT
28
#define DI_D3_VSYNC_POL_SHIFT
28
#define DI_D3_HSYNC_POL_SHIFT
27
#define DI_D3_HSYNC_POL_SHIFT
27
#define DI_D3_DRDY_SHARP_POL_SHIFT
26
#define DI_D3_DRDY_SHARP_POL_SHIFT
26
#define DI_D3_CLK_POL_SHIFT
25
#define DI_D3_CLK_POL_SHIFT
25
#define DI_D3_DATA_POL_SHIFT
24
#define DI_D3_DATA_POL_SHIFT
24
/* DI_DISP_IF_CONF bits */
/* DI_DISP_IF_CONF bits */
#define DI_D3_CLK_IDLE_SHIFT
26
#define DI_D3_CLK_IDLE_SHIFT
26
#define DI_D3_CLK_SEL_SHIFT
25
#define DI_D3_CLK_SEL_SHIFT
25
#define DI_D3_DATAMSK_SHIFT
24
#define DI_D3_DATAMSK_SHIFT
24
enum
ipu_panel
{
enum
ipu_panel
{
IPU_PANEL_SHARP_TFT
,
IPU_PANEL_SHARP_TFT
,
IPU_PANEL_TFT
,
IPU_PANEL_TFT
,
};
};
struct
ipu_di_signal_cfg
{
struct
ipu_di_signal_cfg
{
unsigned
datamask_en
:
1
;
unsigned
datamask_en
:
1
;
unsigned
clksel_en
:
1
;
unsigned
clksel_en
:
1
;
unsigned
clkidle_en
:
1
;
unsigned
clkidle_en
:
1
;
unsigned
data_pol
:
1
;
/* true = inverted */
unsigned
data_pol
:
1
;
/* true = inverted */
unsigned
clk_pol
:
1
;
/* true = rising edge */
unsigned
clk_pol
:
1
;
/* true = rising edge */
unsigned
enable_pol
:
1
;
unsigned
enable_pol
:
1
;
unsigned
Hsync_pol
:
1
;
/* true = active high */
unsigned
Hsync_pol
:
1
;
/* true = active high */
unsigned
Vsync_pol
:
1
;
unsigned
Vsync_pol
:
1
;
};
};
static
const
struct
fb_videomode
mx3fb_modedb
[]
=
{
static
const
struct
fb_videomode
mx3fb_modedb
[]
=
{
{
{
/* 240x320 @ 60 Hz */
/* 240x320 @ 60 Hz */
.
name
=
"Sharp-QVGA"
,
.
name
=
"Sharp-QVGA"
,
.
refresh
=
60
,
.
refresh
=
60
,
.
xres
=
240
,
.
xres
=
240
,
.
yres
=
320
,
.
yres
=
320
,
.
pixclock
=
185925
,
.
pixclock
=
185925
,
.
left_margin
=
9
,
.
left_margin
=
9
,
.
right_margin
=
16
,
.
right_margin
=
16
,
.
upper_margin
=
7
,
.
upper_margin
=
7
,
.
lower_margin
=
9
,
.
lower_margin
=
9
,
.
hsync_len
=
1
,
.
hsync_len
=
1
,
.
vsync_len
=
1
,
.
vsync_len
=
1
,
.
sync
=
FB_SYNC_HOR_HIGH_ACT
|
FB_SYNC_SHARP_MODE
|
.
sync
=
FB_SYNC_HOR_HIGH_ACT
|
FB_SYNC_SHARP_MODE
|
FB_SYNC_CLK_INVERT
|
FB_SYNC_DATA_INVERT
|
FB_SYNC_CLK_INVERT
|
FB_SYNC_DATA_INVERT
|
FB_SYNC_CLK_IDLE_EN
,
FB_SYNC_CLK_IDLE_EN
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
flag
=
0
,
.
flag
=
0
,
},
{
},
{
/* 240x33 @ 60 Hz */
/* 240x33 @ 60 Hz */
.
name
=
"Sharp-CLI"
,
.
name
=
"Sharp-CLI"
,
.
refresh
=
60
,
.
refresh
=
60
,
.
xres
=
240
,
.
xres
=
240
,
.
yres
=
33
,
.
yres
=
33
,
.
pixclock
=
185925
,
.
pixclock
=
185925
,
.
left_margin
=
9
,
.
left_margin
=
9
,
.
right_margin
=
16
,
.
right_margin
=
16
,
.
upper_margin
=
7
,
.
upper_margin
=
7
,
.
lower_margin
=
9
+
287
,
.
lower_margin
=
9
+
287
,
.
hsync_len
=
1
,
.
hsync_len
=
1
,
.
vsync_len
=
1
,
.
vsync_len
=
1
,
.
sync
=
FB_SYNC_HOR_HIGH_ACT
|
FB_SYNC_SHARP_MODE
|
.
sync
=
FB_SYNC_HOR_HIGH_ACT
|
FB_SYNC_SHARP_MODE
|
FB_SYNC_CLK_INVERT
|
FB_SYNC_DATA_INVERT
|
FB_SYNC_CLK_INVERT
|
FB_SYNC_DATA_INVERT
|
FB_SYNC_CLK_IDLE_EN
,
FB_SYNC_CLK_IDLE_EN
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
flag
=
0
,
.
flag
=
0
,
},
{
},
{
/* 640x480 @ 60 Hz */
/* 640x480 @ 60 Hz */
.
name
=
"NEC-VGA"
,
.
name
=
"NEC-VGA"
,
.
refresh
=
60
,
.
refresh
=
60
,
.
xres
=
640
,
.
xres
=
640
,
.
yres
=
480
,
.
yres
=
480
,
.
pixclock
=
38255
,
.
pixclock
=
38255
,
.
left_margin
=
144
,
.
left_margin
=
144
,
.
right_margin
=
0
,
.
right_margin
=
0
,
.
upper_margin
=
34
,
.
upper_margin
=
34
,
.
lower_margin
=
40
,
.
lower_margin
=
40
,
.
hsync_len
=
1
,
.
hsync_len
=
1
,
.
vsync_len
=
1
,
.
vsync_len
=
1
,
.
sync
=
FB_SYNC_VERT_HIGH_ACT
|
FB_SYNC_OE_ACT_HIGH
,
.
sync
=
FB_SYNC_VERT_HIGH_ACT
|
FB_SYNC_OE_ACT_HIGH
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
flag
=
0
,
.
flag
=
0
,
},
{
},
{
/* NTSC TV output */
/* NTSC TV output */
.
name
=
"TV-NTSC"
,
.
name
=
"TV-NTSC"
,
.
refresh
=
60
,
.
refresh
=
60
,
.
xres
=
640
,
.
xres
=
640
,
.
yres
=
480
,
.
yres
=
480
,
.
pixclock
=
37538
,
.
pixclock
=
37538
,
.
left_margin
=
38
,
.
left_margin
=
38
,
.
right_margin
=
858
-
640
-
38
-
3
,
.
right_margin
=
858
-
640
-
38
-
3
,
.
upper_margin
=
36
,
.
upper_margin
=
36
,
.
lower_margin
=
518
-
480
-
36
-
1
,
.
lower_margin
=
518
-
480
-
36
-
1
,
.
hsync_len
=
3
,
.
hsync_len
=
3
,
.
vsync_len
=
1
,
.
vsync_len
=
1
,
.
sync
=
0
,
.
sync
=
0
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
flag
=
0
,
.
flag
=
0
,
},
{
},
{
/* PAL TV output */
/* PAL TV output */
.
name
=
"TV-PAL"
,
.
name
=
"TV-PAL"
,
.
refresh
=
50
,
.
refresh
=
50
,
.
xres
=
640
,
.
xres
=
640
,
.
yres
=
480
,
.
yres
=
480
,
.
pixclock
=
37538
,
.
pixclock
=
37538
,
.
left_margin
=
38
,
.
left_margin
=
38
,
.
right_margin
=
960
-
640
-
38
-
32
,
.
right_margin
=
960
-
640
-
38
-
32
,
.
upper_margin
=
32
,
.
upper_margin
=
32
,
.
lower_margin
=
555
-
480
-
32
-
3
,
.
lower_margin
=
555
-
480
-
32
-
3
,
.
hsync_len
=
32
,
.
hsync_len
=
32
,
.
vsync_len
=
3
,
.
vsync_len
=
3
,
.
sync
=
0
,
.
sync
=
0
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
flag
=
0
,
.
flag
=
0
,
},
{
},
{
/* TV output VGA mode, 640x480 @ 65 Hz */
/* TV output VGA mode, 640x480 @ 65 Hz */
.
name
=
"TV-VGA"
,
.
name
=
"TV-VGA"
,
.
refresh
=
60
,
.
refresh
=
60
,
.
xres
=
640
,
.
xres
=
640
,
.
yres
=
480
,
.
yres
=
480
,
.
pixclock
=
40574
,
.
pixclock
=
40574
,
.
left_margin
=
35
,
.
left_margin
=
35
,
.
right_margin
=
45
,
.
right_margin
=
45
,
.
upper_margin
=
9
,
.
upper_margin
=
9
,
.
lower_margin
=
1
,
.
lower_margin
=
1
,
.
hsync_len
=
46
,
.
hsync_len
=
46
,
.
vsync_len
=
5
,
.
vsync_len
=
5
,
.
sync
=
0
,
.
sync
=
0
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
vmode
=
FB_VMODE_NONINTERLACED
,
.
flag
=
0
,
.
flag
=
0
,
},
},
};
};
struct
mx3fb_data
{
struct
mx3fb_data
{
struct
fb_info
*
fbi
;
struct
fb_info
*
fbi
;
int
backlight_level
;
int
backlight_level
;
void
__iomem
*
reg_base
;
void
__iomem
*
reg_base
;
spinlock_t
lock
;
spinlock_t
lock
;
struct
device
*
dev
;
struct
device
*
dev
;
uint32_t
h_start_width
;
uint32_t
h_start_width
;
uint32_t
v_start_width
;
uint32_t
v_start_width
;
};
};
struct
dma_chan_request
{
struct
dma_chan_request
{
struct
mx3fb_data
*
mx3fb
;
struct
mx3fb_data
*
mx3fb
;
enum
ipu_channel
id
;
enum
ipu_channel
id
;
};
};
/* MX3 specific framebuffer information. */
/* MX3 specific framebuffer information. */
struct
mx3fb_info
{
struct
mx3fb_info
{
int
blank
;
int
blank
;
enum
ipu_channel
ipu_ch
;
enum
ipu_channel
ipu_ch
;
uint32_t
cur_ipu_buf
;
uint32_t
cur_ipu_buf
;
u32
pseudo_palette
[
16
];
u32
pseudo_palette
[
16
];
struct
completion
flip_cmpl
;
struct
completion
flip_cmpl
;
struct
mutex
mutex
;
/* Protects fb-ops */
struct
mutex
mutex
;
/* Protects fb-ops */
struct
mx3fb_data
*
mx3fb
;
struct
mx3fb_data
*
mx3fb
;
struct
idmac_channel
*
idmac_channel
;
struct
idmac_channel
*
idmac_channel
;
struct
dma_async_tx_descriptor
*
txd
;
struct
dma_async_tx_descriptor
*
txd
;
dma_cookie_t
cookie
;
dma_cookie_t
cookie
;
struct
scatterlist
sg
[
2
];
struct
scatterlist
sg
[
2
];
u32
sync
;
/* preserve var->sync flags */
u32
sync
;
/* preserve var->sync flags */
};
};
static
void
mx3fb_dma_done
(
void
*
);
static
void
mx3fb_dma_done
(
void
*
);
...
@@ -278,389 +278,389 @@ static unsigned long default_bpp = 16;
...
@@ -278,389 +278,389 @@ static unsigned long default_bpp = 16;
static
u32
mx3fb_read_reg
(
struct
mx3fb_data
*
mx3fb
,
unsigned
long
reg
)
static
u32
mx3fb_read_reg
(
struct
mx3fb_data
*
mx3fb
,
unsigned
long
reg
)
{
{
return
__raw_readl
(
mx3fb
->
reg_base
+
reg
);
return
__raw_readl
(
mx3fb
->
reg_base
+
reg
);
}
}
static
void
mx3fb_write_reg
(
struct
mx3fb_data
*
mx3fb
,
u32
value
,
unsigned
long
reg
)
static
void
mx3fb_write_reg
(
struct
mx3fb_data
*
mx3fb
,
u32
value
,
unsigned
long
reg
)
{
{
__raw_writel
(
value
,
mx3fb
->
reg_base
+
reg
);
__raw_writel
(
value
,
mx3fb
->
reg_base
+
reg
);
}
}
static
const
uint32_t
di_mappings
[]
=
{
static
const
uint32_t
di_mappings
[]
=
{
0x1600AAAA
,
0x00E05555
,
0x00070000
,
3
,
/* RGB888 */
0x1600AAAA
,
0x00E05555
,
0x00070000
,
3
,
/* RGB888 */
0x0005000F
,
0x000B000F
,
0x0011000F
,
1
,
/* RGB666 */
0x0005000F
,
0x000B000F
,
0x0011000F
,
1
,
/* RGB666 */
0x0011000F
,
0x000B000F
,
0x0005000F
,
1
,
/* BGR666 */
0x0011000F
,
0x000B000F
,
0x0005000F
,
1
,
/* BGR666 */
0x0004003F
,
0x000A000F
,
0x000F003F
,
1
/* RGB565 */
0x0004003F
,
0x000A000F
,
0x000F003F
,
1
/* RGB565 */
};
};
static
void
sdc_fb_init
(
struct
mx3fb_info
*
fbi
)
static
void
sdc_fb_init
(
struct
mx3fb_info
*
fbi
)
{
{
struct
mx3fb_data
*
mx3fb
=
fbi
->
mx3fb
;
struct
mx3fb_data
*
mx3fb
=
fbi
->
mx3fb
;
uint32_t
reg
;
uint32_t
reg
;
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
|
SDC_COM_BG_EN
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
|
SDC_COM_BG_EN
,
SDC_COM_CONF
);
}
}
/* Returns enabled flag before uninit */
/* Returns enabled flag before uninit */
static
uint32_t
sdc_fb_uninit
(
struct
mx3fb_info
*
fbi
)
static
uint32_t
sdc_fb_uninit
(
struct
mx3fb_info
*
fbi
)
{
{
struct
mx3fb_data
*
mx3fb
=
fbi
->
mx3fb
;
struct
mx3fb_data
*
mx3fb
=
fbi
->
mx3fb
;
uint32_t
reg
;
uint32_t
reg
;
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
&
~
SDC_COM_BG_EN
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
&
~
SDC_COM_BG_EN
,
SDC_COM_CONF
);
return
reg
&
SDC_COM_BG_EN
;
return
reg
&
SDC_COM_BG_EN
;
}
}
static
void
sdc_enable_channel
(
struct
mx3fb_info
*
mx3_fbi
)
static
void
sdc_enable_channel
(
struct
mx3fb_info
*
mx3_fbi
)
{
{
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
struct
idmac_channel
*
ichan
=
mx3_fbi
->
idmac_channel
;
struct
idmac_channel
*
ichan
=
mx3_fbi
->
idmac_channel
;
struct
dma_chan
*
dma_chan
=
&
ichan
->
dma_chan
;
struct
dma_chan
*
dma_chan
=
&
ichan
->
dma_chan
;
unsigned
long
flags
;
unsigned
long
flags
;
dma_cookie_t
cookie
;
dma_cookie_t
cookie
;
dev_dbg
(
mx3fb
->
dev
,
"mx3fbi %p, desc %p, sg %p
\n
"
,
mx3_fbi
,
dev_dbg
(
mx3fb
->
dev
,
"mx3fbi %p, desc %p, sg %p
\n
"
,
mx3_fbi
,
to_tx_desc
(
mx3_fbi
->
txd
),
to_tx_desc
(
mx3_fbi
->
txd
)
->
sg
);
to_tx_desc
(
mx3_fbi
->
txd
),
to_tx_desc
(
mx3_fbi
->
txd
)
->
sg
);
/* This enables the channel */
/* This enables the channel */
if
(
mx3_fbi
->
cookie
<
0
)
{
if
(
mx3_fbi
->
cookie
<
0
)
{
mx3_fbi
->
txd
=
dma_chan
->
device
->
device_prep_slave_sg
(
dma_chan
,
mx3_fbi
->
txd
=
dma_chan
->
device
->
device_prep_slave_sg
(
dma_chan
,
&
mx3_fbi
->
sg
[
0
],
1
,
DMA_TO_DEVICE
,
DMA_PREP_INTERRUPT
);
&
mx3_fbi
->
sg
[
0
],
1
,
DMA_TO_DEVICE
,
DMA_PREP_INTERRUPT
);
if
(
!
mx3_fbi
->
txd
)
{
if
(
!
mx3_fbi
->
txd
)
{
dev_err
(
mx3fb
->
dev
,
"Cannot allocate descriptor on %d
\n
"
,
dev_err
(
mx3fb
->
dev
,
"Cannot allocate descriptor on %d
\n
"
,
dma_chan
->
chan_id
);
dma_chan
->
chan_id
);
return
;
return
;
}
}
mx3_fbi
->
txd
->
callback_param
=
mx3_fbi
->
txd
;
mx3_fbi
->
txd
->
callback_param
=
mx3_fbi
->
txd
;
mx3_fbi
->
txd
->
callback
=
mx3fb_dma_done
;
mx3_fbi
->
txd
->
callback
=
mx3fb_dma_done
;
cookie
=
mx3_fbi
->
txd
->
tx_submit
(
mx3_fbi
->
txd
);
cookie
=
mx3_fbi
->
txd
->
tx_submit
(
mx3_fbi
->
txd
);
dev_dbg
(
mx3fb
->
dev
,
"%d: Submit %p #%d [%c]
\n
"
,
__LINE__
,
dev_dbg
(
mx3fb
->
dev
,
"%d: Submit %p #%d [%c]
\n
"
,
__LINE__
,
mx3_fbi
->
txd
,
cookie
,
list_empty
(
&
ichan
->
queue
)
?
'-'
:
'+'
);
mx3_fbi
->
txd
,
cookie
,
list_empty
(
&
ichan
->
queue
)
?
'-'
:
'+'
);
}
else
{
}
else
{
if
(
!
mx3_fbi
->
txd
||
!
mx3_fbi
->
txd
->
tx_submit
)
{
if
(
!
mx3_fbi
->
txd
||
!
mx3_fbi
->
txd
->
tx_submit
)
{
dev_err
(
mx3fb
->
dev
,
"Cannot enable channel %d
\n
"
,
dev_err
(
mx3fb
->
dev
,
"Cannot enable channel %d
\n
"
,
dma_chan
->
chan_id
);
dma_chan
->
chan_id
);
return
;
return
;
}
}
/* Just re-activate the same buffer */
/* Just re-activate the same buffer */
dma_async_issue_pending
(
dma_chan
);
dma_async_issue_pending
(
dma_chan
);
cookie
=
mx3_fbi
->
cookie
;
cookie
=
mx3_fbi
->
cookie
;
dev_dbg
(
mx3fb
->
dev
,
"%d: Re-submit %p #%d [%c]
\n
"
,
__LINE__
,
dev_dbg
(
mx3fb
->
dev
,
"%d: Re-submit %p #%d [%c]
\n
"
,
__LINE__
,
mx3_fbi
->
txd
,
cookie
,
list_empty
(
&
ichan
->
queue
)
?
'-'
:
'+'
);
mx3_fbi
->
txd
,
cookie
,
list_empty
(
&
ichan
->
queue
)
?
'-'
:
'+'
);
}
}
if
(
cookie
>=
0
)
{
if
(
cookie
>=
0
)
{
spin_lock_irqsave
(
&
mx3fb
->
lock
,
flags
);
spin_lock_irqsave
(
&
mx3fb
->
lock
,
flags
);
sdc_fb_init
(
mx3_fbi
);
sdc_fb_init
(
mx3_fbi
);
mx3_fbi
->
cookie
=
cookie
;
mx3_fbi
->
cookie
=
cookie
;
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
flags
);
}
}
/*
/*
* Attention! Without this msleep the channel keeps generating
* Attention! Without this msleep the channel keeps generating
* interrupts. Next sdc_set_brightness() is going to be called
* interrupts. Next sdc_set_brightness() is going to be called
* from mx3fb_blank().
* from mx3fb_blank().
*/
*/
msleep
(
2
);
msleep
(
2
);
}
}
static
void
sdc_disable_channel
(
struct
mx3fb_info
*
mx3_fbi
)
static
void
sdc_disable_channel
(
struct
mx3fb_info
*
mx3_fbi
)
{
{
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
uint32_t
enabled
;
uint32_t
enabled
;
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
mx3fb
->
lock
,
flags
);
spin_lock_irqsave
(
&
mx3fb
->
lock
,
flags
);
enabled
=
sdc_fb_uninit
(
mx3_fbi
);
enabled
=
sdc_fb_uninit
(
mx3_fbi
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
flags
);
mx3_fbi
->
txd
->
chan
->
device
->
device_terminate_all
(
mx3_fbi
->
txd
->
chan
);
mx3_fbi
->
txd
->
chan
->
device
->
device_terminate_all
(
mx3_fbi
->
txd
->
chan
);
mx3_fbi
->
txd
=
NULL
;
mx3_fbi
->
txd
=
NULL
;
mx3_fbi
->
cookie
=
-
EINVAL
;
mx3_fbi
->
cookie
=
-
EINVAL
;
}
}
/**
/**
* sdc_set_window_pos() - set window position of the respective plane.
* sdc_set_window_pos() - set window position of the respective plane.
* @mx3fb:
mx3fb context.
* @mx3fb:
mx3fb context.
* @channel:
IPU DMAC channel ID.
* @channel:
IPU DMAC channel ID.
* @x_pos:
X coordinate relative to the top left corner to place window at.
* @x_pos:
X coordinate relative to the top left corner to place window at.
* @y_pos:
Y coordinate relative to the top left corner to place window at.
* @y_pos:
Y coordinate relative to the top left corner to place window at.
* @return:
0 on success or negative error code on failure.
* @return:
0 on success or negative error code on failure.
*/
*/
static
int
sdc_set_window_pos
(
struct
mx3fb_data
*
mx3fb
,
enum
ipu_channel
channel
,
static
int
sdc_set_window_pos
(
struct
mx3fb_data
*
mx3fb
,
enum
ipu_channel
channel
,
int16_t
x_pos
,
int16_t
y_pos
)
int16_t
x_pos
,
int16_t
y_pos
)
{
{
x_pos
+=
mx3fb
->
h_start_width
;
x_pos
+=
mx3fb
->
h_start_width
;
y_pos
+=
mx3fb
->
v_start_width
;
y_pos
+=
mx3fb
->
v_start_width
;
if
(
channel
!=
IDMAC_SDC_0
)
if
(
channel
!=
IDMAC_SDC_0
)
return
-
EINVAL
;
return
-
EINVAL
;
mx3fb_write_reg
(
mx3fb
,
(
x_pos
<<
16
)
|
y_pos
,
SDC_BG_POS
);
mx3fb_write_reg
(
mx3fb
,
(
x_pos
<<
16
)
|
y_pos
,
SDC_BG_POS
);
return
0
;
return
0
;
}
}
/**
/**
* sdc_init_panel() - initialize a synchronous LCD panel.
* sdc_init_panel() - initialize a synchronous LCD panel.
* @mx3fb:
mx3fb context.
* @mx3fb:
mx3fb context.
* @panel:
panel type.
* @panel:
panel type.
* @pixel_clk:
desired pixel clock frequency in Hz.
* @pixel_clk:
desired pixel clock frequency in Hz.
* @width:
width of panel in pixels.
* @width:
width of panel in pixels.
* @height:
height of panel in pixels.
* @height:
height of panel in pixels.
* @pixel_fmt:
pixel format of buffer as FOURCC ASCII code.
* @pixel_fmt:
pixel format of buffer as FOURCC ASCII code.
* @h_start_width:
number of pixel clocks between the HSYNC signal pulse
* @h_start_width:
number of pixel clocks between the HSYNC signal pulse
*
and the start of valid data.
*
and the start of valid data.
* @h_sync_width:
width of the HSYNC signal in units of pixel clocks.
* @h_sync_width:
width of the HSYNC signal in units of pixel clocks.
* @h_end_width:
number of pixel clocks between the end of valid data
* @h_end_width:
number of pixel clocks between the end of valid data
*
and the HSYNC signal for next line.
*
and the HSYNC signal for next line.
* @v_start_width:
number of lines between the VSYNC signal pulse and the
* @v_start_width:
number of lines between the VSYNC signal pulse and the
*
start of valid data.
*
start of valid data.
* @v_sync_width:
width of the VSYNC signal in units of lines
* @v_sync_width:
width of the VSYNC signal in units of lines
* @v_end_width:
number of lines between the end of valid data and the
* @v_end_width:
number of lines between the end of valid data and the
*
VSYNC signal for next frame.
*
VSYNC signal for next frame.
* @sig:
bitfield of signal polarities for LCD interface.
* @sig:
bitfield of signal polarities for LCD interface.
* @return:
0 on success or negative error code on failure.
* @return:
0 on success or negative error code on failure.
*/
*/
static
int
sdc_init_panel
(
struct
mx3fb_data
*
mx3fb
,
enum
ipu_panel
panel
,
static
int
sdc_init_panel
(
struct
mx3fb_data
*
mx3fb
,
enum
ipu_panel
panel
,
uint32_t
pixel_clk
,
uint32_t
pixel_clk
,
uint16_t
width
,
uint16_t
height
,
uint16_t
width
,
uint16_t
height
,
enum
pixel_fmt
pixel_fmt
,
enum
pixel_fmt
pixel_fmt
,
uint16_t
h_start_width
,
uint16_t
h_sync_width
,
uint16_t
h_start_width
,
uint16_t
h_sync_width
,
uint16_t
h_end_width
,
uint16_t
v_start_width
,
uint16_t
h_end_width
,
uint16_t
v_start_width
,
uint16_t
v_sync_width
,
uint16_t
v_end_width
,
uint16_t
v_sync_width
,
uint16_t
v_end_width
,
struct
ipu_di_signal_cfg
sig
)
struct
ipu_di_signal_cfg
sig
)
{
{
unsigned
long
lock_flags
;
unsigned
long
lock_flags
;
uint32_t
reg
;
uint32_t
reg
;
uint32_t
old_conf
;
uint32_t
old_conf
;
uint32_t
div
;
uint32_t
div
;
struct
clk
*
ipu_clk
;
struct
clk
*
ipu_clk
;
dev_dbg
(
mx3fb
->
dev
,
"panel size = %d x %d"
,
width
,
height
);
dev_dbg
(
mx3fb
->
dev
,
"panel size = %d x %d"
,
width
,
height
);
if
(
v_sync_width
==
0
||
h_sync_width
==
0
)
if
(
v_sync_width
==
0
||
h_sync_width
==
0
)
return
-
EINVAL
;
return
-
EINVAL
;
/* Init panel size and blanking periods */
/* Init panel size and blanking periods */
reg
=
((
uint32_t
)
(
h_sync_width
-
1
)
<<
26
)
|
reg
=
((
uint32_t
)
(
h_sync_width
-
1
)
<<
26
)
|
((
uint32_t
)
(
width
+
h_start_width
+
h_end_width
-
1
)
<<
16
);
((
uint32_t
)
(
width
+
h_start_width
+
h_end_width
-
1
)
<<
16
);
mx3fb_write_reg
(
mx3fb
,
reg
,
SDC_HOR_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
,
SDC_HOR_CONF
);
#ifdef DEBUG
#ifdef DEBUG
printk
(
KERN_CONT
" hor_conf %x,"
,
reg
);
printk
(
KERN_CONT
" hor_conf %x,"
,
reg
);
#endif
#endif
reg
=
((
uint32_t
)
(
v_sync_width
-
1
)
<<
26
)
|
SDC_V_SYNC_WIDTH_L
|
reg
=
((
uint32_t
)
(
v_sync_width
-
1
)
<<
26
)
|
SDC_V_SYNC_WIDTH_L
|
((
uint32_t
)
(
height
+
v_start_width
+
v_end_width
-
1
)
<<
16
);
((
uint32_t
)
(
height
+
v_start_width
+
v_end_width
-
1
)
<<
16
);
mx3fb_write_reg
(
mx3fb
,
reg
,
SDC_VER_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
,
SDC_VER_CONF
);
#ifdef DEBUG
#ifdef DEBUG
printk
(
KERN_CONT
" ver_conf %x
\n
"
,
reg
);
printk
(
KERN_CONT
" ver_conf %x
\n
"
,
reg
);
#endif
#endif
mx3fb
->
h_start_width
=
h_start_width
;
mx3fb
->
h_start_width
=
h_start_width
;
mx3fb
->
v_start_width
=
v_start_width
;
mx3fb
->
v_start_width
=
v_start_width
;
switch
(
panel
)
{
switch
(
panel
)
{
case
IPU_PANEL_SHARP_TFT
:
case
IPU_PANEL_SHARP_TFT
:
mx3fb_write_reg
(
mx3fb
,
0x00FD0102L
,
SDC_SHARP_CONF_1
);
mx3fb_write_reg
(
mx3fb
,
0x00FD0102L
,
SDC_SHARP_CONF_1
);
mx3fb_write_reg
(
mx3fb
,
0x00F500F4L
,
SDC_SHARP_CONF_2
);
mx3fb_write_reg
(
mx3fb
,
0x00F500F4L
,
SDC_SHARP_CONF_2
);
mx3fb_write_reg
(
mx3fb
,
SDC_COM_SHARP
|
SDC_COM_TFT_COLOR
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
SDC_COM_SHARP
|
SDC_COM_TFT_COLOR
,
SDC_COM_CONF
);
break
;
break
;
case
IPU_PANEL_TFT
:
case
IPU_PANEL_TFT
:
mx3fb_write_reg
(
mx3fb
,
SDC_COM_TFT_COLOR
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
SDC_COM_TFT_COLOR
,
SDC_COM_CONF
);
break
;
break
;
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* Init clocking */
/* Init clocking */
/*
/*
* Calculate divider: fractional part is 4 bits so simply multiple by
* Calculate divider: fractional part is 4 bits so simply multiple by
* 2
4 to get fractional part, as long as we stay under ~250MHz and on
* 2^
4 to get fractional part, as long as we stay under ~250MHz and on
* i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
* i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
*/
*/
dev_dbg
(
mx3fb
->
dev
,
"pixel clk = %d
\n
"
,
pixel_clk
);
dev_dbg
(
mx3fb
->
dev
,
"pixel clk = %d
\n
"
,
pixel_clk
);
ipu_clk
=
clk_get
(
mx3fb
->
dev
,
NULL
);
ipu_clk
=
clk_get
(
mx3fb
->
dev
,
NULL
);
div
=
clk_get_rate
(
ipu_clk
)
*
16
/
pixel_clk
;
div
=
clk_get_rate
(
ipu_clk
)
*
16
/
pixel_clk
;
clk_put
(
ipu_clk
);
clk_put
(
ipu_clk
);
if
(
div
<
0x40
)
{
/* Divider less than 4 */
if
(
div
<
0x40
)
{
/* Divider less than 4 */
dev_dbg
(
mx3fb
->
dev
,
dev_dbg
(
mx3fb
->
dev
,
"InitPanel() - Pixel clock divider less than 4
\n
"
);
"InitPanel() - Pixel clock divider less than 4
\n
"
);
div
=
0x40
;
div
=
0x40
;
}
}
spin_lock_irqsave
(
&
mx3fb
->
lock
,
lock_flags
);
spin_lock_irqsave
(
&
mx3fb
->
lock
,
lock_flags
);
/*
/*
* DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits
* DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits
* fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing
* fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing
* debug. DISP3_IF_CLK_UP_WR is 0
* debug. DISP3_IF_CLK_UP_WR is 0
*/
*/
mx3fb_write_reg
(
mx3fb
,
(((
div
/
8
)
-
1
)
<<
22
)
|
div
,
DI_DISP3_TIME_CONF
);
mx3fb_write_reg
(
mx3fb
,
(((
div
/
8
)
-
1
)
<<
22
)
|
div
,
DI_DISP3_TIME_CONF
);
/* DI settings */
/* DI settings */
old_conf
=
mx3fb_read_reg
(
mx3fb
,
DI_DISP_IF_CONF
)
&
0x78FFFFFF
;
old_conf
=
mx3fb_read_reg
(
mx3fb
,
DI_DISP_IF_CONF
)
&
0x78FFFFFF
;
old_conf
|=
sig
.
datamask_en
<<
DI_D3_DATAMSK_SHIFT
|
old_conf
|=
sig
.
datamask_en
<<
DI_D3_DATAMSK_SHIFT
|
sig
.
clksel_en
<<
DI_D3_CLK_SEL_SHIFT
|
sig
.
clksel_en
<<
DI_D3_CLK_SEL_SHIFT
|
sig
.
clkidle_en
<<
DI_D3_CLK_IDLE_SHIFT
;
sig
.
clkidle_en
<<
DI_D3_CLK_IDLE_SHIFT
;
mx3fb_write_reg
(
mx3fb
,
old_conf
,
DI_DISP_IF_CONF
);
mx3fb_write_reg
(
mx3fb
,
old_conf
,
DI_DISP_IF_CONF
);
old_conf
=
mx3fb_read_reg
(
mx3fb
,
DI_DISP_SIG_POL
)
&
0xE0FFFFFF
;
old_conf
=
mx3fb_read_reg
(
mx3fb
,
DI_DISP_SIG_POL
)
&
0xE0FFFFFF
;
old_conf
|=
sig
.
data_pol
<<
DI_D3_DATA_POL_SHIFT
|
old_conf
|=
sig
.
data_pol
<<
DI_D3_DATA_POL_SHIFT
|
sig
.
clk_pol
<<
DI_D3_CLK_POL_SHIFT
|
sig
.
clk_pol
<<
DI_D3_CLK_POL_SHIFT
|
sig
.
enable_pol
<<
DI_D3_DRDY_SHARP_POL_SHIFT
|
sig
.
enable_pol
<<
DI_D3_DRDY_SHARP_POL_SHIFT
|
sig
.
Hsync_pol
<<
DI_D3_HSYNC_POL_SHIFT
|
sig
.
Hsync_pol
<<
DI_D3_HSYNC_POL_SHIFT
|
sig
.
Vsync_pol
<<
DI_D3_VSYNC_POL_SHIFT
;
sig
.
Vsync_pol
<<
DI_D3_VSYNC_POL_SHIFT
;
mx3fb_write_reg
(
mx3fb
,
old_conf
,
DI_DISP_SIG_POL
);
mx3fb_write_reg
(
mx3fb
,
old_conf
,
DI_DISP_SIG_POL
);
switch
(
pixel_fmt
)
{
switch
(
pixel_fmt
)
{
case
IPU_PIX_FMT_RGB24
:
case
IPU_PIX_FMT_RGB24
:
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
0
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
0
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
1
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
1
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
2
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
2
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
((
di_mappings
[
3
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
((
di_mappings
[
3
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
break
;
break
;
case
IPU_PIX_FMT_RGB666
:
case
IPU_PIX_FMT_RGB666
:
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
4
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
4
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
5
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
5
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
6
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
6
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
((
di_mappings
[
7
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
((
di_mappings
[
7
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
break
;
break
;
case
IPU_PIX_FMT_BGR666
:
case
IPU_PIX_FMT_BGR666
:
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
8
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
8
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
9
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
9
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
10
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
10
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
((
di_mappings
[
11
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
((
di_mappings
[
11
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
break
;
break
;
default:
default:
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
12
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
12
],
DI_DISP3_B0_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
13
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
13
],
DI_DISP3_B1_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
14
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
di_mappings
[
14
],
DI_DISP3_B2_MAP
);
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
mx3fb_write_reg
(
mx3fb
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_ACC_CC
)
|
((
di_mappings
[
15
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
((
di_mappings
[
15
]
-
1
)
<<
12
),
DI_DISP_ACC_CC
);
break
;
break
;
}
}
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
lock_flags
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
lock_flags
);
dev_dbg
(
mx3fb
->
dev
,
"DI_DISP_IF_CONF = 0x%08X
\n
"
,
dev_dbg
(
mx3fb
->
dev
,
"DI_DISP_IF_CONF = 0x%08X
\n
"
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_IF_CONF
));
mx3fb_read_reg
(
mx3fb
,
DI_DISP_IF_CONF
));
dev_dbg
(
mx3fb
->
dev
,
"DI_DISP_SIG_POL = 0x%08X
\n
"
,
dev_dbg
(
mx3fb
->
dev
,
"DI_DISP_SIG_POL = 0x%08X
\n
"
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP_SIG_POL
));
mx3fb_read_reg
(
mx3fb
,
DI_DISP_SIG_POL
));
dev_dbg
(
mx3fb
->
dev
,
"DI_DISP3_TIME_CONF = 0x%08X
\n
"
,
dev_dbg
(
mx3fb
->
dev
,
"DI_DISP3_TIME_CONF = 0x%08X
\n
"
,
mx3fb_read_reg
(
mx3fb
,
DI_DISP3_TIME_CONF
));
mx3fb_read_reg
(
mx3fb
,
DI_DISP3_TIME_CONF
));
return
0
;
return
0
;
}
}
/**
/**
* sdc_set_color_key() - set the transparent color key for SDC graphic plane.
* sdc_set_color_key() - set the transparent color key for SDC graphic plane.
* @mx3fb:
mx3fb context.
* @mx3fb:
mx3fb context.
* @channel:
IPU DMAC channel ID.
* @channel:
IPU DMAC channel ID.
* @enable:
boolean to enable or disable color keyl.
* @enable:
boolean to enable or disable color keyl.
* @color_key:
24-bit RGB color to use as transparent color key.
* @color_key:
24-bit RGB color to use as transparent color key.
* @return:
0 on success or negative error code on failure.
* @return:
0 on success or negative error code on failure.
*/
*/
static
int
sdc_set_color_key
(
struct
mx3fb_data
*
mx3fb
,
enum
ipu_channel
channel
,
static
int
sdc_set_color_key
(
struct
mx3fb_data
*
mx3fb
,
enum
ipu_channel
channel
,
bool
enable
,
uint32_t
color_key
)
bool
enable
,
uint32_t
color_key
)
{
{
uint32_t
reg
,
sdc_conf
;
uint32_t
reg
,
sdc_conf
;
unsigned
long
lock_flags
;
unsigned
long
lock_flags
;
spin_lock_irqsave
(
&
mx3fb
->
lock
,
lock_flags
);
spin_lock_irqsave
(
&
mx3fb
->
lock
,
lock_flags
);
sdc_conf
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
sdc_conf
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
if
(
channel
==
IDMAC_SDC_0
)
if
(
channel
==
IDMAC_SDC_0
)
sdc_conf
&=
~
SDC_COM_GWSEL
;
sdc_conf
&=
~
SDC_COM_GWSEL
;
else
else
sdc_conf
|=
SDC_COM_GWSEL
;
sdc_conf
|=
SDC_COM_GWSEL
;
if
(
enable
)
{
if
(
enable
)
{
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_GW_CTRL
)
&
0xFF000000L
;
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_GW_CTRL
)
&
0xFF000000L
;
mx3fb_write_reg
(
mx3fb
,
reg
|
(
color_key
&
0x00FFFFFFL
),
mx3fb_write_reg
(
mx3fb
,
reg
|
(
color_key
&
0x00FFFFFFL
),
SDC_GW_CTRL
);
SDC_GW_CTRL
);
sdc_conf
|=
SDC_COM_KEY_COLOR_G
;
sdc_conf
|=
SDC_COM_KEY_COLOR_G
;
}
else
{
}
else
{
sdc_conf
&=
~
SDC_COM_KEY_COLOR_G
;
sdc_conf
&=
~
SDC_COM_KEY_COLOR_G
;
}
}
mx3fb_write_reg
(
mx3fb
,
sdc_conf
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
sdc_conf
,
SDC_COM_CONF
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
lock_flags
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
lock_flags
);
return
0
;
return
0
;
}
}
/**
/**
* sdc_set_global_alpha() - set global alpha blending modes.
* sdc_set_global_alpha() - set global alpha blending modes.
* @mx3fb:
mx3fb context.
* @mx3fb:
mx3fb context.
* @enable:
boolean to enable or disable global alpha blending. If disabled,
* @enable:
boolean to enable or disable global alpha blending. If disabled,
*
per pixel blending is used.
*
per pixel blending is used.
* @alpha:
global alpha value.
* @alpha:
global alpha value.
* @return:
0 on success or negative error code on failure.
* @return:
0 on success or negative error code on failure.
*/
*/
static
int
sdc_set_global_alpha
(
struct
mx3fb_data
*
mx3fb
,
bool
enable
,
uint8_t
alpha
)
static
int
sdc_set_global_alpha
(
struct
mx3fb_data
*
mx3fb
,
bool
enable
,
uint8_t
alpha
)
{
{
uint32_t
reg
;
uint32_t
reg
;
unsigned
long
lock_flags
;
unsigned
long
lock_flags
;
spin_lock_irqsave
(
&
mx3fb
->
lock
,
lock_flags
);
spin_lock_irqsave
(
&
mx3fb
->
lock
,
lock_flags
);
if
(
enable
)
{
if
(
enable
)
{
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_GW_CTRL
)
&
0x00FFFFFFL
;
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_GW_CTRL
)
&
0x00FFFFFFL
;
mx3fb_write_reg
(
mx3fb
,
reg
|
((
uint32_t
)
alpha
<<
24
),
SDC_GW_CTRL
);
mx3fb_write_reg
(
mx3fb
,
reg
|
((
uint32_t
)
alpha
<<
24
),
SDC_GW_CTRL
);
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
|
SDC_COM_GLB_A
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
|
SDC_COM_GLB_A
,
SDC_COM_CONF
);
}
else
{
}
else
{
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
reg
=
mx3fb_read_reg
(
mx3fb
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
&
~
SDC_COM_GLB_A
,
SDC_COM_CONF
);
mx3fb_write_reg
(
mx3fb
,
reg
&
~
SDC_COM_GLB_A
,
SDC_COM_CONF
);
}
}
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
lock_flags
);
spin_unlock_irqrestore
(
&
mx3fb
->
lock
,
lock_flags
);
return
0
;
return
0
;
}
}
static
void
sdc_set_brightness
(
struct
mx3fb_data
*
mx3fb
,
uint8_t
value
)
static
void
sdc_set_brightness
(
struct
mx3fb_data
*
mx3fb
,
uint8_t
value
)
{
{
/* This might be board-specific */
/* This might be board-specific */
mx3fb_write_reg
(
mx3fb
,
0x03000000UL
|
value
<<
16
,
SDC_PWM_CTRL
);
mx3fb_write_reg
(
mx3fb
,
0x03000000UL
|
value
<<
16
,
SDC_PWM_CTRL
);
return
;
return
;
}
}
static
uint32_t
bpp_to_pixfmt
(
int
bpp
)
static
uint32_t
bpp_to_pixfmt
(
int
bpp
)
{
{
uint32_t
pixfmt
=
0
;
uint32_t
pixfmt
=
0
;
switch
(
bpp
)
{
switch
(
bpp
)
{
case
24
:
case
24
:
pixfmt
=
IPU_PIX_FMT_BGR24
;
pixfmt
=
IPU_PIX_FMT_BGR24
;
break
;
break
;
case
32
:
case
32
:
pixfmt
=
IPU_PIX_FMT_BGR32
;
pixfmt
=
IPU_PIX_FMT_BGR32
;
break
;
break
;
case
16
:
case
16
:
pixfmt
=
IPU_PIX_FMT_RGB565
;
pixfmt
=
IPU_PIX_FMT_RGB565
;
break
;
break
;
}
}
return
pixfmt
;
return
pixfmt
;
}
}
static
int
mx3fb_blank
(
int
blank
,
struct
fb_info
*
fbi
);
static
int
mx3fb_blank
(
int
blank
,
struct
fb_info
*
fbi
);
...
@@ -669,300 +669,300 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi);
...
@@ -669,300 +669,300 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi);
/**
/**
* mx3fb_set_fix() - set fixed framebuffer parameters from variable settings.
* mx3fb_set_fix() - set fixed framebuffer parameters from variable settings.
* @info:
framebuffer information pointer
* @info:
framebuffer information pointer
* @return:
0 on success or negative error code on failure.
* @return:
0 on success or negative error code on failure.
*/
*/
static
int
mx3fb_set_fix
(
struct
fb_info
*
fbi
)
static
int
mx3fb_set_fix
(
struct
fb_info
*
fbi
)
{
{
struct
fb_fix_screeninfo
*
fix
=
&
fbi
->
fix
;
struct
fb_fix_screeninfo
*
fix
=
&
fbi
->
fix
;
struct
fb_var_screeninfo
*
var
=
&
fbi
->
var
;
struct
fb_var_screeninfo
*
var
=
&
fbi
->
var
;
strncpy
(
fix
->
id
,
"DISP3 BG"
,
8
);
strncpy
(
fix
->
id
,
"DISP3 BG"
,
8
);
fix
->
line_length
=
var
->
xres_virtual
*
var
->
bits_per_pixel
/
8
;
fix
->
line_length
=
var
->
xres_virtual
*
var
->
bits_per_pixel
/
8
;
fix
->
type
=
FB_TYPE_PACKED_PIXELS
;
fix
->
type
=
FB_TYPE_PACKED_PIXELS
;
fix
->
accel
=
FB_ACCEL_NONE
;
fix
->
accel
=
FB_ACCEL_NONE
;
fix
->
visual
=
FB_VISUAL_TRUECOLOR
;
fix
->
visual
=
FB_VISUAL_TRUECOLOR
;
fix
->
xpanstep
=
1
;
fix
->
xpanstep
=
1
;
fix
->
ypanstep
=
1
;
fix
->
ypanstep
=
1
;
return
0
;
return
0
;
}
}
static
void
mx3fb_dma_done
(
void
*
arg
)
static
void
mx3fb_dma_done
(
void
*
arg
)
{
{
struct
idmac_tx_desc
*
tx_desc
=
to_tx_desc
(
arg
);
struct
idmac_tx_desc
*
tx_desc
=
to_tx_desc
(
arg
);
struct
dma_chan
*
chan
=
tx_desc
->
txd
.
chan
;
struct
dma_chan
*
chan
=
tx_desc
->
txd
.
chan
;
struct
idmac_channel
*
ichannel
=
to_idmac_chan
(
chan
);
struct
idmac_channel
*
ichannel
=
to_idmac_chan
(
chan
);
struct
mx3fb_data
*
mx3fb
=
ichannel
->
client
;
struct
mx3fb_data
*
mx3fb
=
ichannel
->
client
;
struct
mx3fb_info
*
mx3_fbi
=
mx3fb
->
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
mx3fb
->
fbi
->
par
;
dev_dbg
(
mx3fb
->
dev
,
"irq %d callback
\n
"
,
ichannel
->
eof_irq
);
dev_dbg
(
mx3fb
->
dev
,
"irq %d callback
\n
"
,
ichannel
->
eof_irq
);
/* We only need one interrupt, it will be re-enabled as needed */
/* We only need one interrupt, it will be re-enabled as needed */
disable_irq
(
ichannel
->
eof_irq
);
disable_irq
(
ichannel
->
eof_irq
);
complete
(
&
mx3_fbi
->
flip_cmpl
);
complete
(
&
mx3_fbi
->
flip_cmpl
);
}
}
/**
/**
* mx3fb_set_par() - set framebuffer parameters and change the operating mode.
* mx3fb_set_par() - set framebuffer parameters and change the operating mode.
* @fbi:
framebuffer information pointer.
* @fbi:
framebuffer information pointer.
* @return:
0 on success or negative error code on failure.
* @return:
0 on success or negative error code on failure.
*/
*/
static
int
mx3fb_set_par
(
struct
fb_info
*
fbi
)
static
int
mx3fb_set_par
(
struct
fb_info
*
fbi
)
{
{
u32
mem_len
;
u32
mem_len
;
struct
ipu_di_signal_cfg
sig_cfg
;
struct
ipu_di_signal_cfg
sig_cfg
;
enum
ipu_panel
mode
=
IPU_PANEL_TFT
;
enum
ipu_panel
mode
=
IPU_PANEL_TFT
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
struct
idmac_channel
*
ichan
=
mx3_fbi
->
idmac_channel
;
struct
idmac_channel
*
ichan
=
mx3_fbi
->
idmac_channel
;
struct
idmac_video_param
*
video
=
&
ichan
->
params
.
video
;
struct
idmac_video_param
*
video
=
&
ichan
->
params
.
video
;
struct
scatterlist
*
sg
=
mx3_fbi
->
sg
;
struct
scatterlist
*
sg
=
mx3_fbi
->
sg
;
size_t
screen_size
;
size_t
screen_size
;
dev_dbg
(
mx3fb
->
dev
,
"%s [%c]
\n
"
,
__func__
,
list_empty
(
&
ichan
->
queue
)
?
'-'
:
'+'
);
dev_dbg
(
mx3fb
->
dev
,
"%s [%c]
\n
"
,
__func__
,
list_empty
(
&
ichan
->
queue
)
?
'-'
:
'+'
);
mutex_lock
(
&
mx3_fbi
->
mutex
);
mutex_lock
(
&
mx3_fbi
->
mutex
);
/* Total cleanup */
/* Total cleanup */
if
(
mx3_fbi
->
txd
)
if
(
mx3_fbi
->
txd
)
sdc_disable_channel
(
mx3_fbi
);
sdc_disable_channel
(
mx3_fbi
);
mx3fb_set_fix
(
fbi
);
mx3fb_set_fix
(
fbi
);
mem_len
=
fbi
->
var
.
yres_virtual
*
fbi
->
fix
.
line_length
;
mem_len
=
fbi
->
var
.
yres_virtual
*
fbi
->
fix
.
line_length
;
if
(
mem_len
>
fbi
->
fix
.
smem_len
)
{
if
(
mem_len
>
fbi
->
fix
.
smem_len
)
{
if
(
fbi
->
fix
.
smem_start
)
if
(
fbi
->
fix
.
smem_start
)
mx3fb_unmap_video_memory
(
fbi
);
mx3fb_unmap_video_memory
(
fbi
);
fbi
->
fix
.
smem_len
=
mem_len
;
fbi
->
fix
.
smem_len
=
mem_len
;
if
(
mx3fb_map_video_memory
(
fbi
)
<
0
)
{
if
(
mx3fb_map_video_memory
(
fbi
)
<
0
)
{
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
}
}
screen_size
=
fbi
->
fix
.
line_length
*
fbi
->
var
.
yres
;
screen_size
=
fbi
->
fix
.
line_length
*
fbi
->
var
.
yres
;
sg_init_table
(
&
sg
[
0
],
1
);
sg_init_table
(
&
sg
[
0
],
1
);
sg_init_table
(
&
sg
[
1
],
1
);
sg_init_table
(
&
sg
[
1
],
1
);
sg_dma_address
(
&
sg
[
0
])
=
fbi
->
fix
.
smem_start
;
sg_dma_address
(
&
sg
[
0
])
=
fbi
->
fix
.
smem_start
;
sg_set_page
(
&
sg
[
0
],
virt_to_page
(
fbi
->
screen_base
),
sg_set_page
(
&
sg
[
0
],
virt_to_page
(
fbi
->
screen_base
),
fbi
->
fix
.
smem_len
,
fbi
->
fix
.
smem_len
,
offset_in_page
(
fbi
->
screen_base
));
offset_in_page
(
fbi
->
screen_base
));
if
(
mx3_fbi
->
ipu_ch
==
IDMAC_SDC_0
)
{
if
(
mx3_fbi
->
ipu_ch
==
IDMAC_SDC_0
)
{
memset
(
&
sig_cfg
,
0
,
sizeof
(
sig_cfg
));
memset
(
&
sig_cfg
,
0
,
sizeof
(
sig_cfg
));
if
(
fbi
->
var
.
sync
&
FB_SYNC_HOR_HIGH_ACT
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_HOR_HIGH_ACT
)
sig_cfg
.
Hsync_pol
=
true
;
sig_cfg
.
Hsync_pol
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_VERT_HIGH_ACT
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_VERT_HIGH_ACT
)
sig_cfg
.
Vsync_pol
=
true
;
sig_cfg
.
Vsync_pol
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_CLK_INVERT
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_CLK_INVERT
)
sig_cfg
.
clk_pol
=
true
;
sig_cfg
.
clk_pol
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_DATA_INVERT
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_DATA_INVERT
)
sig_cfg
.
data_pol
=
true
;
sig_cfg
.
data_pol
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_OE_ACT_HIGH
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_OE_ACT_HIGH
)
sig_cfg
.
enable_pol
=
true
;
sig_cfg
.
enable_pol
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_CLK_IDLE_EN
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_CLK_IDLE_EN
)
sig_cfg
.
clkidle_en
=
true
;
sig_cfg
.
clkidle_en
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_CLK_SEL_EN
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_CLK_SEL_EN
)
sig_cfg
.
clksel_en
=
true
;
sig_cfg
.
clksel_en
=
true
;
if
(
fbi
->
var
.
sync
&
FB_SYNC_SHARP_MODE
)
if
(
fbi
->
var
.
sync
&
FB_SYNC_SHARP_MODE
)
mode
=
IPU_PANEL_SHARP_TFT
;
mode
=
IPU_PANEL_SHARP_TFT
;
dev_dbg
(
fbi
->
device
,
"pixclock = %ul Hz
\n
"
,
dev_dbg
(
fbi
->
device
,
"pixclock = %ul Hz
\n
"
,
(
u32
)
(
PICOS2KHZ
(
fbi
->
var
.
pixclock
)
*
1000UL
));
(
u32
)
(
PICOS2KHZ
(
fbi
->
var
.
pixclock
)
*
1000UL
));
if
(
sdc_init_panel
(
mx3fb
,
mode
,
if
(
sdc_init_panel
(
mx3fb
,
mode
,
(
PICOS2KHZ
(
fbi
->
var
.
pixclock
))
*
1000UL
,
(
PICOS2KHZ
(
fbi
->
var
.
pixclock
))
*
1000UL
,
fbi
->
var
.
xres
,
fbi
->
var
.
yres
,
fbi
->
var
.
xres
,
fbi
->
var
.
yres
,
(
fbi
->
var
.
sync
&
FB_SYNC_SWAP_RGB
)
?
(
fbi
->
var
.
sync
&
FB_SYNC_SWAP_RGB
)
?
IPU_PIX_FMT_BGR666
:
IPU_PIX_FMT_RGB666
,
IPU_PIX_FMT_BGR666
:
IPU_PIX_FMT_RGB666
,
fbi
->
var
.
left_margin
,
fbi
->
var
.
left_margin
,
fbi
->
var
.
hsync_len
,
fbi
->
var
.
hsync_len
,
fbi
->
var
.
right_margin
+
fbi
->
var
.
right_margin
+
fbi
->
var
.
hsync_len
,
fbi
->
var
.
hsync_len
,
fbi
->
var
.
upper_margin
,
fbi
->
var
.
upper_margin
,
fbi
->
var
.
vsync_len
,
fbi
->
var
.
vsync_len
,
fbi
->
var
.
lower_margin
+
fbi
->
var
.
lower_margin
+
fbi
->
var
.
vsync_len
,
sig_cfg
)
!=
0
)
{
fbi
->
var
.
vsync_len
,
sig_cfg
)
!=
0
)
{
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
dev_err
(
fbi
->
device
,
dev_err
(
fbi
->
device
,
"mx3fb: Error initializing panel.
\n
"
);
"mx3fb: Error initializing panel.
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
}
}
sdc_set_window_pos
(
mx3fb
,
mx3_fbi
->
ipu_ch
,
0
,
0
);
sdc_set_window_pos
(
mx3fb
,
mx3_fbi
->
ipu_ch
,
0
,
0
);
mx3_fbi
->
cur_ipu_buf
=
0
;
mx3_fbi
->
cur_ipu_buf
=
0
;
video
->
out_pixel_fmt
=
bpp_to_pixfmt
(
fbi
->
var
.
bits_per_pixel
);
video
->
out_pixel_fmt
=
bpp_to_pixfmt
(
fbi
->
var
.
bits_per_pixel
);
video
->
out_width
=
fbi
->
var
.
xres
;
video
->
out_width
=
fbi
->
var
.
xres
;
video
->
out_height
=
fbi
->
var
.
yres
;
video
->
out_height
=
fbi
->
var
.
yres
;
video
->
out_stride
=
fbi
->
var
.
xres_virtual
;
video
->
out_stride
=
fbi
->
var
.
xres_virtual
;
if
(
mx3_fbi
->
blank
==
FB_BLANK_UNBLANK
)
if
(
mx3_fbi
->
blank
==
FB_BLANK_UNBLANK
)
sdc_enable_channel
(
mx3_fbi
);
sdc_enable_channel
(
mx3_fbi
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
return
0
;
return
0
;
}
}
/**
/**
* mx3fb_check_var() - check and adjust framebuffer variable parameters.
* mx3fb_check_var() - check and adjust framebuffer variable parameters.
* @var:
framebuffer variable parameters
* @var:
framebuffer variable parameters
* @fbi:
framebuffer information pointer
* @fbi:
framebuffer information pointer
*/
*/
static
int
mx3fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fbi
)
static
int
mx3fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fbi
)
{
{
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
u32
vtotal
;
u32
vtotal
;
u32
htotal
;
u32
htotal
;
dev_dbg
(
fbi
->
device
,
"%s
\n
"
,
__func__
);
dev_dbg
(
fbi
->
device
,
"%s
\n
"
,
__func__
);
if
(
var
->
xres_virtual
<
var
->
xres
)
if
(
var
->
xres_virtual
<
var
->
xres
)
var
->
xres_virtual
=
var
->
xres
;
var
->
xres_virtual
=
var
->
xres
;
if
(
var
->
yres_virtual
<
var
->
yres
)
if
(
var
->
yres_virtual
<
var
->
yres
)
var
->
yres_virtual
=
var
->
yres
;
var
->
yres_virtual
=
var
->
yres
;
if
((
var
->
bits_per_pixel
!=
32
)
&&
(
var
->
bits_per_pixel
!=
24
)
&&
if
((
var
->
bits_per_pixel
!=
32
)
&&
(
var
->
bits_per_pixel
!=
24
)
&&
(
var
->
bits_per_pixel
!=
16
))
(
var
->
bits_per_pixel
!=
16
))
var
->
bits_per_pixel
=
default_bpp
;
var
->
bits_per_pixel
=
default_bpp
;
switch
(
var
->
bits_per_pixel
)
{
switch
(
var
->
bits_per_pixel
)
{
case
16
:
case
16
:
var
->
red
.
length
=
5
;
var
->
red
.
length
=
5
;
var
->
red
.
offset
=
11
;
var
->
red
.
offset
=
11
;
var
->
red
.
msb_right
=
0
;
var
->
red
.
msb_right
=
0
;
var
->
green
.
length
=
6
;
var
->
green
.
length
=
6
;
var
->
green
.
offset
=
5
;
var
->
green
.
offset
=
5
;
var
->
green
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
length
=
5
;
var
->
blue
.
length
=
5
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
transp
.
length
=
0
;
var
->
transp
.
length
=
0
;
var
->
transp
.
offset
=
0
;
var
->
transp
.
offset
=
0
;
var
->
transp
.
msb_right
=
0
;
var
->
transp
.
msb_right
=
0
;
break
;
break
;
case
24
:
case
24
:
var
->
red
.
length
=
8
;
var
->
red
.
length
=
8
;
var
->
red
.
offset
=
16
;
var
->
red
.
offset
=
16
;
var
->
red
.
msb_right
=
0
;
var
->
red
.
msb_right
=
0
;
var
->
green
.
length
=
8
;
var
->
green
.
length
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
length
=
8
;
var
->
blue
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
transp
.
length
=
0
;
var
->
transp
.
length
=
0
;
var
->
transp
.
offset
=
0
;
var
->
transp
.
offset
=
0
;
var
->
transp
.
msb_right
=
0
;
var
->
transp
.
msb_right
=
0
;
break
;
break
;
case
32
:
case
32
:
var
->
red
.
length
=
8
;
var
->
red
.
length
=
8
;
var
->
red
.
offset
=
16
;
var
->
red
.
offset
=
16
;
var
->
red
.
msb_right
=
0
;
var
->
red
.
msb_right
=
0
;
var
->
green
.
length
=
8
;
var
->
green
.
length
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
length
=
8
;
var
->
blue
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
transp
.
length
=
8
;
var
->
transp
.
length
=
8
;
var
->
transp
.
offset
=
24
;
var
->
transp
.
offset
=
24
;
var
->
transp
.
msb_right
=
0
;
var
->
transp
.
msb_right
=
0
;
break
;
break
;
}
}
if
(
var
->
pixclock
<
1000
)
{
if
(
var
->
pixclock
<
1000
)
{
htotal
=
var
->
xres
+
var
->
right_margin
+
var
->
hsync_len
+
htotal
=
var
->
xres
+
var
->
right_margin
+
var
->
hsync_len
+
var
->
left_margin
;
var
->
left_margin
;
vtotal
=
var
->
yres
+
var
->
lower_margin
+
var
->
vsync_len
+
vtotal
=
var
->
yres
+
var
->
lower_margin
+
var
->
vsync_len
+
var
->
upper_margin
;
var
->
upper_margin
;
var
->
pixclock
=
(
vtotal
*
htotal
*
6UL
)
/
100UL
;
var
->
pixclock
=
(
vtotal
*
htotal
*
6UL
)
/
100UL
;
var
->
pixclock
=
KHZ2PICOS
(
var
->
pixclock
);
var
->
pixclock
=
KHZ2PICOS
(
var
->
pixclock
);
dev_dbg
(
fbi
->
device
,
"pixclock set for 60Hz refresh = %u ps
\n
"
,
dev_dbg
(
fbi
->
device
,
"pixclock set for 60Hz refresh = %u ps
\n
"
,
var
->
pixclock
);
var
->
pixclock
);
}
}
var
->
height
=
-
1
;
var
->
height
=
-
1
;
var
->
width
=
-
1
;
var
->
width
=
-
1
;
var
->
grayscale
=
0
;
var
->
grayscale
=
0
;
/* Preserve sync flags */
/* Preserve sync flags */
var
->
sync
|=
mx3_fbi
->
sync
;
var
->
sync
|=
mx3_fbi
->
sync
;
mx3_fbi
->
sync
|=
var
->
sync
;
mx3_fbi
->
sync
|=
var
->
sync
;
return
0
;
return
0
;
}
}
static
u32
chan_to_field
(
unsigned
int
chan
,
struct
fb_bitfield
*
bf
)
static
u32
chan_to_field
(
unsigned
int
chan
,
struct
fb_bitfield
*
bf
)
{
{
chan
&=
0xffff
;
chan
&=
0xffff
;
chan
>>=
16
-
bf
->
length
;
chan
>>=
16
-
bf
->
length
;
return
chan
<<
bf
->
offset
;
return
chan
<<
bf
->
offset
;
}
}
static
int
mx3fb_setcolreg
(
unsigned
int
regno
,
unsigned
int
red
,
static
int
mx3fb_setcolreg
(
unsigned
int
regno
,
unsigned
int
red
,
unsigned
int
green
,
unsigned
int
blue
,
unsigned
int
green
,
unsigned
int
blue
,
unsigned
int
trans
,
struct
fb_info
*
fbi
)
unsigned
int
trans
,
struct
fb_info
*
fbi
)
{
{
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
u32
val
;
u32
val
;
int
ret
=
1
;
int
ret
=
1
;
dev_dbg
(
fbi
->
device
,
"%s
\n
"
,
__func__
);
dev_dbg
(
fbi
->
device
,
"%s
\n
"
,
__func__
);
mutex_lock
(
&
mx3_fbi
->
mutex
);
mutex_lock
(
&
mx3_fbi
->
mutex
);
/*
/*
* If greyscale is true, then we convert the RGB value
* If greyscale is true, then we convert the RGB value
* to greyscale no matter what visual we are using.
* to greyscale no matter what visual we are using.
*/
*/
if
(
fbi
->
var
.
grayscale
)
if
(
fbi
->
var
.
grayscale
)
red
=
green
=
blue
=
(
19595
*
red
+
38470
*
green
+
red
=
green
=
blue
=
(
19595
*
red
+
38470
*
green
+
7471
*
blue
)
>>
16
;
7471
*
blue
)
>>
16
;
switch
(
fbi
->
fix
.
visual
)
{
switch
(
fbi
->
fix
.
visual
)
{
case
FB_VISUAL_TRUECOLOR
:
case
FB_VISUAL_TRUECOLOR
:
/*
/*
* 16-bit True Colour. We encode the RGB value
* 16-bit True Colour. We encode the RGB value
* according to the RGB bitfield information.
* according to the RGB bitfield information.
*/
*/
if
(
regno
<
16
)
{
if
(
regno
<
16
)
{
u32
*
pal
=
fbi
->
pseudo_palette
;
u32
*
pal
=
fbi
->
pseudo_palette
;
val
=
chan_to_field
(
red
,
&
fbi
->
var
.
red
);
val
=
chan_to_field
(
red
,
&
fbi
->
var
.
red
);
val
|=
chan_to_field
(
green
,
&
fbi
->
var
.
green
);
val
|=
chan_to_field
(
green
,
&
fbi
->
var
.
green
);
val
|=
chan_to_field
(
blue
,
&
fbi
->
var
.
blue
);
val
|=
chan_to_field
(
blue
,
&
fbi
->
var
.
blue
);
pal
[
regno
]
=
val
;
pal
[
regno
]
=
val
;
ret
=
0
;
ret
=
0
;
}
}
break
;
break
;
case
FB_VISUAL_STATIC_PSEUDOCOLOR
:
case
FB_VISUAL_STATIC_PSEUDOCOLOR
:
case
FB_VISUAL_PSEUDOCOLOR
:
case
FB_VISUAL_PSEUDOCOLOR
:
break
;
break
;
}
}
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
return
ret
;
return
ret
;
}
}
/**
/**
...
@@ -970,152 +970,152 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
...
@@ -970,152 +970,152 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
*/
*/
static
int
mx3fb_blank
(
int
blank
,
struct
fb_info
*
fbi
)
static
int
mx3fb_blank
(
int
blank
,
struct
fb_info
*
fbi
)
{
{
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
struct
mx3fb_data
*
mx3fb
=
mx3_fbi
->
mx3fb
;
dev_dbg
(
fbi
->
device
,
"%s
\n
"
,
__func__
);
dev_dbg
(
fbi
->
device
,
"%s
\n
"
,
__func__
);
dev_dbg
(
fbi
->
device
,
"blank = %d
\n
"
,
blank
);
dev_dbg
(
fbi
->
device
,
"blank = %d
\n
"
,
blank
);
if
(
mx3_fbi
->
blank
==
blank
)
if
(
mx3_fbi
->
blank
==
blank
)
return
0
;
return
0
;
mutex_lock
(
&
mx3_fbi
->
mutex
);
mutex_lock
(
&
mx3_fbi
->
mutex
);
mx3_fbi
->
blank
=
blank
;
mx3_fbi
->
blank
=
blank
;
switch
(
blank
)
{
switch
(
blank
)
{
case
FB_BLANK_POWERDOWN
:
case
FB_BLANK_POWERDOWN
:
case
FB_BLANK_VSYNC_SUSPEND
:
case
FB_BLANK_VSYNC_SUSPEND
:
case
FB_BLANK_HSYNC_SUSPEND
:
case
FB_BLANK_HSYNC_SUSPEND
:
case
FB_BLANK_NORMAL
:
case
FB_BLANK_NORMAL
:
sdc_disable_channel
(
mx3_fbi
);
sdc_disable_channel
(
mx3_fbi
);
sdc_set_brightness
(
mx3fb
,
0
);
sdc_set_brightness
(
mx3fb
,
0
);
break
;
break
;
case
FB_BLANK_UNBLANK
:
case
FB_BLANK_UNBLANK
:
sdc_enable_channel
(
mx3_fbi
);
sdc_enable_channel
(
mx3_fbi
);
sdc_set_brightness
(
mx3fb
,
mx3fb
->
backlight_level
);
sdc_set_brightness
(
mx3fb
,
mx3fb
->
backlight_level
);
break
;
break
;
}
}
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
return
0
;
return
0
;
}
}
/**
/**
* mx3fb_pan_display() - pan or wrap the display
* mx3fb_pan_display() - pan or wrap the display
* @var:
variable screen buffer information.
* @var:
variable screen buffer information.
* @info:
framebuffer information pointer.
* @info:
framebuffer information pointer.
*
*
* We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag
* We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
*/
static
int
mx3fb_pan_display
(
struct
fb_var_screeninfo
*
var
,
static
int
mx3fb_pan_display
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fbi
)
struct
fb_info
*
fbi
)
{
{
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
u32
y_bottom
;
u32
y_bottom
;
unsigned
long
base
;
unsigned
long
base
;
off_t
offset
;
off_t
offset
;
dma_cookie_t
cookie
;
dma_cookie_t
cookie
;
struct
scatterlist
*
sg
=
mx3_fbi
->
sg
;
struct
scatterlist
*
sg
=
mx3_fbi
->
sg
;
struct
dma_chan
*
dma_chan
=
&
mx3_fbi
->
idmac_channel
->
dma_chan
;
struct
dma_chan
*
dma_chan
=
&
mx3_fbi
->
idmac_channel
->
dma_chan
;
struct
dma_async_tx_descriptor
*
txd
;
struct
dma_async_tx_descriptor
*
txd
;
int
ret
;
int
ret
;
dev_dbg
(
fbi
->
device
,
"%s [%c]
\n
"
,
__func__
,
dev_dbg
(
fbi
->
device
,
"%s [%c]
\n
"
,
__func__
,
list_empty
(
&
mx3_fbi
->
idmac_channel
->
queue
)
?
'-'
:
'+'
);
list_empty
(
&
mx3_fbi
->
idmac_channel
->
queue
)
?
'-'
:
'+'
);
if
(
var
->
xoffset
>
0
)
{
if
(
var
->
xoffset
>
0
)
{
dev_dbg
(
fbi
->
device
,
"x panning not supported
\n
"
);
dev_dbg
(
fbi
->
device
,
"x panning not supported
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
fbi
->
var
.
xoffset
==
var
->
xoffset
&&
if
(
fbi
->
var
.
xoffset
==
var
->
xoffset
&&
fbi
->
var
.
yoffset
==
var
->
yoffset
)
fbi
->
var
.
yoffset
==
var
->
yoffset
)
return
0
;
/* No change, do nothing */
return
0
;
/* No change, do nothing */
y_bottom
=
var
->
yoffset
;
y_bottom
=
var
->
yoffset
;
if
(
!
(
var
->
vmode
&
FB_VMODE_YWRAP
))
if
(
!
(
var
->
vmode
&
FB_VMODE_YWRAP
))
y_bottom
+=
var
->
yres
;
y_bottom
+=
var
->
yres
;
if
(
y_bottom
>
fbi
->
var
.
yres_virtual
)
if
(
y_bottom
>
fbi
->
var
.
yres_virtual
)
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
mx3_fbi
->
mutex
);
mutex_lock
(
&
mx3_fbi
->
mutex
);
offset
=
(
var
->
yoffset
*
var
->
xres_virtual
+
var
->
xoffset
)
*
offset
=
(
var
->
yoffset
*
var
->
xres_virtual
+
var
->
xoffset
)
*
(
var
->
bits_per_pixel
/
8
);
(
var
->
bits_per_pixel
/
8
);
base
=
fbi
->
fix
.
smem_start
+
offset
;
base
=
fbi
->
fix
.
smem_start
+
offset
;
dev_dbg
(
fbi
->
device
,
"Updating SDC BG buf %d address=0x%08lX
\n
"
,
dev_dbg
(
fbi
->
device
,
"Updating SDC BG buf %d address=0x%08lX
\n
"
,
mx3_fbi
->
cur_ipu_buf
,
base
);
mx3_fbi
->
cur_ipu_buf
,
base
);
/*
/*
* We enable the End of Frame interrupt, which will free a tx-descriptor,
* We enable the End of Frame interrupt, which will free a tx-descriptor,
* which we will need for the next device_prep_slave_sg(). The
* which we will need for the next device_prep_slave_sg(). The
* IRQ-handler will disable the IRQ again.
* IRQ-handler will disable the IRQ again.
*/
*/
init_completion
(
&
mx3_fbi
->
flip_cmpl
);
init_completion
(
&
mx3_fbi
->
flip_cmpl
);
enable_irq
(
mx3_fbi
->
idmac_channel
->
eof_irq
);
enable_irq
(
mx3_fbi
->
idmac_channel
->
eof_irq
);
ret
=
wait_for_completion_timeout
(
&
mx3_fbi
->
flip_cmpl
,
HZ
/
10
);
ret
=
wait_for_completion_timeout
(
&
mx3_fbi
->
flip_cmpl
,
HZ
/
10
);
if
(
ret
<=
0
)
{
if
(
ret
<=
0
)
{
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
dev_info
(
fbi
->
device
,
"Panning failed due to %s
\n
"
,
ret
<
0
?
dev_info
(
fbi
->
device
,
"Panning failed due to %s
\n
"
,
ret
<
0
?
"user interrupt"
:
"timeout"
);
"user interrupt"
:
"timeout"
);
return
ret
?
:
-
ETIMEDOUT
;
return
ret
?
:
-
ETIMEDOUT
;
}
}
mx3_fbi
->
cur_ipu_buf
=
!
mx3_fbi
->
cur_ipu_buf
;
mx3_fbi
->
cur_ipu_buf
=
!
mx3_fbi
->
cur_ipu_buf
;
sg_dma_address
(
&
sg
[
mx3_fbi
->
cur_ipu_buf
])
=
base
;
sg_dma_address
(
&
sg
[
mx3_fbi
->
cur_ipu_buf
])
=
base
;
sg_set_page
(
&
sg
[
mx3_fbi
->
cur_ipu_buf
],
sg_set_page
(
&
sg
[
mx3_fbi
->
cur_ipu_buf
],
virt_to_page
(
fbi
->
screen_base
+
offset
),
fbi
->
fix
.
smem_len
,
virt_to_page
(
fbi
->
screen_base
+
offset
),
fbi
->
fix
.
smem_len
,
offset_in_page
(
fbi
->
screen_base
+
offset
));
offset_in_page
(
fbi
->
screen_base
+
offset
));
txd
=
dma_chan
->
device
->
device_prep_slave_sg
(
dma_chan
,
sg
+
txd
=
dma_chan
->
device
->
device_prep_slave_sg
(
dma_chan
,
sg
+
mx3_fbi
->
cur_ipu_buf
,
1
,
DMA_TO_DEVICE
,
DMA_PREP_INTERRUPT
);
mx3_fbi
->
cur_ipu_buf
,
1
,
DMA_TO_DEVICE
,
DMA_PREP_INTERRUPT
);
if
(
!
txd
)
{
if
(
!
txd
)
{
dev_err
(
fbi
->
device
,
dev_err
(
fbi
->
device
,
"Error preparing a DMA transaction descriptor.
\n
"
);
"Error preparing a DMA transaction descriptor.
\n
"
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
return
-
EIO
;
return
-
EIO
;
}
}
txd
->
callback_param
=
txd
;
txd
->
callback_param
=
txd
;
txd
->
callback
=
mx3fb_dma_done
;
txd
->
callback
=
mx3fb_dma_done
;
/*
/*
* Emulate original mx3fb behaviour: each new call to idmac_tx_submit()
* Emulate original mx3fb behaviour: each new call to idmac_tx_submit()
* should switch to another buffer
* should switch to another buffer
*/
*/
cookie
=
txd
->
tx_submit
(
txd
);
cookie
=
txd
->
tx_submit
(
txd
);
dev_dbg
(
fbi
->
device
,
"%d: Submit %p #%d
\n
"
,
__LINE__
,
txd
,
cookie
);
dev_dbg
(
fbi
->
device
,
"%d: Submit %p #%d
\n
"
,
__LINE__
,
txd
,
cookie
);
if
(
cookie
<
0
)
{
if
(
cookie
<
0
)
{
dev_err
(
fbi
->
device
,
dev_err
(
fbi
->
device
,
"Error updating SDC buf %d to address=0x%08lX
\n
"
,
"Error updating SDC buf %d to address=0x%08lX
\n
"
,
mx3_fbi
->
cur_ipu_buf
,
base
);
mx3_fbi
->
cur_ipu_buf
,
base
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
return
-
EIO
;
return
-
EIO
;
}
}
if
(
mx3_fbi
->
txd
)
if
(
mx3_fbi
->
txd
)
async_tx_ack
(
mx3_fbi
->
txd
);
async_tx_ack
(
mx3_fbi
->
txd
);
mx3_fbi
->
txd
=
txd
;
mx3_fbi
->
txd
=
txd
;
fbi
->
var
.
xoffset
=
var
->
xoffset
;
fbi
->
var
.
xoffset
=
var
->
xoffset
;
fbi
->
var
.
yoffset
=
var
->
yoffset
;
fbi
->
var
.
yoffset
=
var
->
yoffset
;
if
(
var
->
vmode
&
FB_VMODE_YWRAP
)
if
(
var
->
vmode
&
FB_VMODE_YWRAP
)
fbi
->
var
.
vmode
|=
FB_VMODE_YWRAP
;
fbi
->
var
.
vmode
|=
FB_VMODE_YWRAP
;
else
else
fbi
->
var
.
vmode
&=
~
FB_VMODE_YWRAP
;
fbi
->
var
.
vmode
&=
~
FB_VMODE_YWRAP
;
mutex_unlock
(
&
mx3_fbi
->
mutex
);
mutex_unlock
(
&
mx3_fbi
->
mutex
);
dev_dbg
(
fbi
->
device
,
"Update complete
\n
"
);
dev_dbg
(
fbi
->
device
,
"Update complete
\n
"
);
return
0
;
return
0
;
}
}
/*
/*
...
@@ -1124,15 +1124,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
...
@@ -1124,15 +1124,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
* blitting, rectangle filling, copy regions and cursor definition.
* blitting, rectangle filling, copy regions and cursor definition.
*/
*/
static
struct
fb_ops
mx3fb_ops
=
{
static
struct
fb_ops
mx3fb_ops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
fb_set_par
=
mx3fb_set_par
,
.
fb_set_par
=
mx3fb_set_par
,
.
fb_check_var
=
mx3fb_check_var
,
.
fb_check_var
=
mx3fb_check_var
,
.
fb_setcolreg
=
mx3fb_setcolreg
,
.
fb_setcolreg
=
mx3fb_setcolreg
,
.
fb_pan_display
=
mx3fb_pan_display
,
.
fb_pan_display
=
mx3fb_pan_display
,
.
fb_fillrect
=
cfb_fillrect
,
.
fb_fillrect
=
cfb_fillrect
,
.
fb_copyarea
=
cfb_copyarea
,
.
fb_copyarea
=
cfb_copyarea
,
.
fb_imageblit
=
cfb_imageblit
,
.
fb_imageblit
=
cfb_imageblit
,
.
fb_blank
=
mx3fb_blank
,
.
fb_blank
=
mx3fb_blank
,
};
};
#ifdef CONFIG_PM
#ifdef CONFIG_PM
...
@@ -1146,19 +1146,19 @@ static struct fb_ops mx3fb_ops = {
...
@@ -1146,19 +1146,19 @@ static struct fb_ops mx3fb_ops = {
*/
*/
static
int
mx3fb_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
static
int
mx3fb_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
{
{
struct
mx3fb_data
*
drv_data
=
platform_get_drvdata
(
pdev
);
struct
mx3fb_data
*
drv_data
=
platform_get_drvdata
(
pdev
);
struct
mx3fb_info
*
mx3_fbi
=
drv_data
->
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
drv_data
->
fbi
->
par
;
acquire_console_sem
();
acquire_console_sem
();
fb_set_suspend
(
drv_data
->
fbi
,
1
);
fb_set_suspend
(
drv_data
->
fbi
,
1
);
release_console_sem
();
release_console_sem
();
if
(
mx3_fbi
->
blank
==
FB_BLANK_UNBLANK
)
{
if
(
mx3_fbi
->
blank
==
FB_BLANK_UNBLANK
)
{
sdc_disable_channel
(
mx3_fbi
);
sdc_disable_channel
(
mx3_fbi
);
sdc_set_brightness
(
mx3fb
,
0
);
sdc_set_brightness
(
mx3fb
,
0
);
}
}
return
0
;
return
0
;
}
}
/*
/*
...
@@ -1166,19 +1166,19 @@ static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
...
@@ -1166,19 +1166,19 @@ static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
*/
*/
static
int
mx3fb_resume
(
struct
platform_device
*
pdev
)
static
int
mx3fb_resume
(
struct
platform_device
*
pdev
)
{
{
struct
mx3fb_data
*
drv_data
=
platform_get_drvdata
(
pdev
);
struct
mx3fb_data
*
drv_data
=
platform_get_drvdata
(
pdev
);
struct
mx3fb_info
*
mx3_fbi
=
drv_data
->
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
drv_data
->
fbi
->
par
;
if
(
mx3_fbi
->
blank
==
FB_BLANK_UNBLANK
)
{
if
(
mx3_fbi
->
blank
==
FB_BLANK_UNBLANK
)
{
sdc_enable_channel
(
mx3_fbi
);
sdc_enable_channel
(
mx3_fbi
);
sdc_set_brightness
(
mx3fb
,
drv_data
->
backlight_level
);
sdc_set_brightness
(
mx3fb
,
drv_data
->
backlight_level
);
}
}
acquire_console_sem
();
acquire_console_sem
();
fb_set_suspend
(
drv_data
->
fbi
,
0
);
fb_set_suspend
(
drv_data
->
fbi
,
0
);
release_console_sem
();
release_console_sem
();
return
0
;
return
0
;
}
}
#else
#else
#define mx3fb_suspend NULL
#define mx3fb_suspend NULL
...
@@ -1191,8 +1191,8 @@ static int mx3fb_resume(struct platform_device *pdev)
...
@@ -1191,8 +1191,8 @@ static int mx3fb_resume(struct platform_device *pdev)
/**
/**
* mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
* mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
* @fbi:
framebuffer information pointer
* @fbi:
framebuffer information pointer
* @return:
Error code indicating success or failure
* @return:
Error code indicating success or failure
*
*
* This buffer is remapped into a non-cached, non-buffered, memory region to
* This buffer is remapped into a non-cached, non-buffered, memory region to
* allow palette and pixel writes to occur without flushing the cache. Once this
* allow palette and pixel writes to occur without flushing the cache. Once this
...
@@ -1201,349 +1201,349 @@ static int mx3fb_resume(struct platform_device *pdev)
...
@@ -1201,349 +1201,349 @@ static int mx3fb_resume(struct platform_device *pdev)
*/
*/
static
int
mx3fb_map_video_memory
(
struct
fb_info
*
fbi
)
static
int
mx3fb_map_video_memory
(
struct
fb_info
*
fbi
)
{
{
int
retval
=
0
;
int
retval
=
0
;
dma_addr_t
addr
;
dma_addr_t
addr
;
fbi
->
screen_base
=
dma_alloc_writecombine
(
fbi
->
device
,
fbi
->
screen_base
=
dma_alloc_writecombine
(
fbi
->
device
,
fbi
->
fix
.
smem_len
,
fbi
->
fix
.
smem_len
,
&
addr
,
GFP_DMA
);
&
addr
,
GFP_DMA
);
if
(
!
fbi
->
screen_base
)
{
if
(
!
fbi
->
screen_base
)
{
dev_err
(
fbi
->
device
,
"Cannot allocate %u bytes framebuffer memory
\n
"
,
dev_err
(
fbi
->
device
,
"Cannot allocate %u bytes framebuffer memory
\n
"
,
fbi
->
fix
.
smem_len
);
fbi
->
fix
.
smem_len
);
retval
=
-
EBUSY
;
retval
=
-
EBUSY
;
goto
err0
;
goto
err0
;
}
}
fbi
->
fix
.
smem_start
=
addr
;
fbi
->
fix
.
smem_start
=
addr
;
dev_dbg
(
fbi
->
device
,
"allocated fb @ p=0x%08x, v=0x%p, size=%d.
\n
"
,
dev_dbg
(
fbi
->
device
,
"allocated fb @ p=0x%08x, v=0x%p, size=%d.
\n
"
,
(
uint32_t
)
fbi
->
fix
.
smem_start
,
fbi
->
screen_base
,
fbi
->
fix
.
smem_len
);
(
uint32_t
)
fbi
->
fix
.
smem_start
,
fbi
->
screen_base
,
fbi
->
fix
.
smem_len
);
fbi
->
screen_size
=
fbi
->
fix
.
smem_len
;
fbi
->
screen_size
=
fbi
->
fix
.
smem_len
;
/* Clear the screen */
/* Clear the screen */
memset
((
char
*
)
fbi
->
screen_base
,
0
,
fbi
->
fix
.
smem_len
);
memset
((
char
*
)
fbi
->
screen_base
,
0
,
fbi
->
fix
.
smem_len
);
return
0
;
return
0
;
err0:
err0:
fbi
->
fix
.
smem_len
=
0
;
fbi
->
fix
.
smem_len
=
0
;
fbi
->
fix
.
smem_start
=
0
;
fbi
->
fix
.
smem_start
=
0
;
fbi
->
screen_base
=
NULL
;
fbi
->
screen_base
=
NULL
;
return
retval
;
return
retval
;
}
}
/**
/**
* mx3fb_unmap_video_memory() - de-allocate frame buffer memory.
* mx3fb_unmap_video_memory() - de-allocate frame buffer memory.
* @fbi:
framebuffer information pointer
* @fbi:
framebuffer information pointer
* @return:
error code indicating success or failure
* @return:
error code indicating success or failure
*/
*/
static
int
mx3fb_unmap_video_memory
(
struct
fb_info
*
fbi
)
static
int
mx3fb_unmap_video_memory
(
struct
fb_info
*
fbi
)
{
{
dma_free_writecombine
(
fbi
->
device
,
fbi
->
fix
.
smem_len
,
dma_free_writecombine
(
fbi
->
device
,
fbi
->
fix
.
smem_len
,
fbi
->
screen_base
,
fbi
->
fix
.
smem_start
);
fbi
->
screen_base
,
fbi
->
fix
.
smem_start
);
fbi
->
screen_base
=
0
;
fbi
->
screen_base
=
0
;
fbi
->
fix
.
smem_start
=
0
;
fbi
->
fix
.
smem_start
=
0
;
fbi
->
fix
.
smem_len
=
0
;
fbi
->
fix
.
smem_len
=
0
;
return
0
;
return
0
;
}
}
/**
/**
* mx3fb_init_fbinfo() - initialize framebuffer information object.
* mx3fb_init_fbinfo() - initialize framebuffer information object.
* @return:
initialized framebuffer structure.
* @return:
initialized framebuffer structure.
*/
*/
static
struct
fb_info
*
mx3fb_init_fbinfo
(
struct
device
*
dev
,
struct
fb_ops
*
ops
)
static
struct
fb_info
*
mx3fb_init_fbinfo
(
struct
device
*
dev
,
struct
fb_ops
*
ops
)
{
{
struct
fb_info
*
fbi
;
struct
fb_info
*
fbi
;
struct
mx3fb_info
*
mx3fbi
;
struct
mx3fb_info
*
mx3fbi
;
int
ret
;
int
ret
;
/* Allocate sufficient memory for the fb structure */
/* Allocate sufficient memory for the fb structure */
fbi
=
framebuffer_alloc
(
sizeof
(
struct
mx3fb_info
),
dev
);
fbi
=
framebuffer_alloc
(
sizeof
(
struct
mx3fb_info
),
dev
);
if
(
!
fbi
)
if
(
!
fbi
)
return
NULL
;
return
NULL
;
mx3fbi
=
fbi
->
par
;
mx3fbi
=
fbi
->
par
;
mx3fbi
->
cookie
=
-
EINVAL
;
mx3fbi
->
cookie
=
-
EINVAL
;
mx3fbi
->
cur_ipu_buf
=
0
;
mx3fbi
->
cur_ipu_buf
=
0
;
fbi
->
var
.
activate
=
FB_ACTIVATE_NOW
;
fbi
->
var
.
activate
=
FB_ACTIVATE_NOW
;
fbi
->
fbops
=
ops
;
fbi
->
fbops
=
ops
;
fbi
->
flags
=
FBINFO_FLAG_DEFAULT
;
fbi
->
flags
=
FBINFO_FLAG_DEFAULT
;
fbi
->
pseudo_palette
=
mx3fbi
->
pseudo_palette
;
fbi
->
pseudo_palette
=
mx3fbi
->
pseudo_palette
;
mutex_init
(
&
mx3fbi
->
mutex
);
mutex_init
(
&
mx3fbi
->
mutex
);
/* Allocate colormap */
/* Allocate colormap */
ret
=
fb_alloc_cmap
(
&
fbi
->
cmap
,
16
,
0
);
ret
=
fb_alloc_cmap
(
&
fbi
->
cmap
,
16
,
0
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
framebuffer_release
(
fbi
);
framebuffer_release
(
fbi
);
return
NULL
;
return
NULL
;
}
}
return
fbi
;
return
fbi
;
}
}
static
int
init_fb_chan
(
struct
mx3fb_data
*
mx3fb
,
struct
idmac_channel
*
ichan
)
static
int
init_fb_chan
(
struct
mx3fb_data
*
mx3fb
,
struct
idmac_channel
*
ichan
)
{
{
struct
device
*
dev
=
mx3fb
->
dev
;
struct
device
*
dev
=
mx3fb
->
dev
;
struct
mx3fb_platform_data
*
mx3fb_pdata
=
dev
->
platform_data
;
struct
mx3fb_platform_data
*
mx3fb_pdata
=
dev
->
platform_data
;
const
char
*
name
=
mx3fb_pdata
->
name
;
const
char
*
name
=
mx3fb_pdata
->
name
;
unsigned
int
irq
;
unsigned
int
irq
;
struct
fb_info
*
fbi
;
struct
fb_info
*
fbi
;
struct
mx3fb_info
*
mx3fbi
;
struct
mx3fb_info
*
mx3fbi
;
const
struct
fb_videomode
*
mode
;
const
struct
fb_videomode
*
mode
;
int
ret
,
num_modes
;
int
ret
,
num_modes
;
ichan
->
client
=
mx3fb
;
ichan
->
client
=
mx3fb
;
irq
=
ichan
->
eof_irq
;
irq
=
ichan
->
eof_irq
;
if
(
ichan
->
dma_chan
.
chan_id
!=
IDMAC_SDC_0
)
if
(
ichan
->
dma_chan
.
chan_id
!=
IDMAC_SDC_0
)
return
-
EINVAL
;
return
-
EINVAL
;
fbi
=
mx3fb_init_fbinfo
(
dev
,
&
mx3fb_ops
);
fbi
=
mx3fb_init_fbinfo
(
dev
,
&
mx3fb_ops
);
if
(
!
fbi
)
if
(
!
fbi
)
return
-
ENOMEM
;
return
-
ENOMEM
;
if
(
!
fb_mode
)
if
(
!
fb_mode
)
fb_mode
=
name
;
fb_mode
=
name
;
if
(
!
fb_mode
)
{
if
(
!
fb_mode
)
{
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
goto
emode
;
goto
emode
;
}
}
if
(
mx3fb_pdata
->
mode
&&
mx3fb_pdata
->
num_modes
)
{
if
(
mx3fb_pdata
->
mode
&&
mx3fb_pdata
->
num_modes
)
{
mode
=
mx3fb_pdata
->
mode
;
mode
=
mx3fb_pdata
->
mode
;
num_modes
=
mx3fb_pdata
->
num_modes
;
num_modes
=
mx3fb_pdata
->
num_modes
;
}
else
{
}
else
{
mode
=
mx3fb_modedb
;
mode
=
mx3fb_modedb
;
num_modes
=
ARRAY_SIZE
(
mx3fb_modedb
);
num_modes
=
ARRAY_SIZE
(
mx3fb_modedb
);
}
}
if
(
!
fb_find_mode
(
&
fbi
->
var
,
fbi
,
fb_mode
,
mode
,
if
(
!
fb_find_mode
(
&
fbi
->
var
,
fbi
,
fb_mode
,
mode
,
num_modes
,
NULL
,
default_bpp
))
{
num_modes
,
NULL
,
default_bpp
))
{
ret
=
-
EBUSY
;
ret
=
-
EBUSY
;
goto
emode
;
goto
emode
;
}
}
fb_videomode_to_modelist
(
mode
,
num_modes
,
&
fbi
->
modelist
);
fb_videomode_to_modelist
(
mode
,
num_modes
,
&
fbi
->
modelist
);
/* Default Y virtual size is 2x panel size */
/* Default Y virtual size is 2x panel size */
fbi
->
var
.
yres_virtual
=
fbi
->
var
.
yres
*
2
;
fbi
->
var
.
yres_virtual
=
fbi
->
var
.
yres
*
2
;
mx3fb
->
fbi
=
fbi
;
mx3fb
->
fbi
=
fbi
;
/* set Display Interface clock period */
/* set Display Interface clock period */
mx3fb_write_reg
(
mx3fb
,
0x00100010L
,
DI_HSP_CLK_PER
);
mx3fb_write_reg
(
mx3fb
,
0x00100010L
,
DI_HSP_CLK_PER
);
/* Might need to trigger HSP clock change - see 44.3.3.8.5 */
/* Might need to trigger HSP clock change - see 44.3.3.8.5 */
sdc_set_brightness
(
mx3fb
,
255
);
sdc_set_brightness
(
mx3fb
,
255
);
sdc_set_global_alpha
(
mx3fb
,
true
,
0xFF
);
sdc_set_global_alpha
(
mx3fb
,
true
,
0xFF
);
sdc_set_color_key
(
mx3fb
,
IDMAC_SDC_0
,
false
,
0
);
sdc_set_color_key
(
mx3fb
,
IDMAC_SDC_0
,
false
,
0
);
mx3fbi
=
fbi
->
par
;
mx3fbi
=
fbi
->
par
;
mx3fbi
->
idmac_channel
=
ichan
;
mx3fbi
->
idmac_channel
=
ichan
;
mx3fbi
->
ipu_ch
=
ichan
->
dma_chan
.
chan_id
;
mx3fbi
->
ipu_ch
=
ichan
->
dma_chan
.
chan_id
;
mx3fbi
->
mx3fb
=
mx3fb
;
mx3fbi
->
mx3fb
=
mx3fb
;
mx3fbi
->
blank
=
FB_BLANK_NORMAL
;
mx3fbi
->
blank
=
FB_BLANK_NORMAL
;
init_completion
(
&
mx3fbi
->
flip_cmpl
);
init_completion
(
&
mx3fbi
->
flip_cmpl
);
disable_irq
(
ichan
->
eof_irq
);
disable_irq
(
ichan
->
eof_irq
);
dev_dbg
(
mx3fb
->
dev
,
"disabling irq %d
\n
"
,
ichan
->
eof_irq
);
dev_dbg
(
mx3fb
->
dev
,
"disabling irq %d
\n
"
,
ichan
->
eof_irq
);
ret
=
mx3fb_set_par
(
fbi
);
ret
=
mx3fb_set_par
(
fbi
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
esetpar
;
goto
esetpar
;
mx3fb_blank
(
FB_BLANK_UNBLANK
,
fbi
);
mx3fb_blank
(
FB_BLANK_UNBLANK
,
fbi
);
dev_info
(
dev
,
"mx3fb: fb registered, using mode %s
\n
"
,
fb_mode
);
dev_info
(
dev
,
"mx3fb: fb registered, using mode %s
\n
"
,
fb_mode
);
ret
=
register_framebuffer
(
fbi
);
ret
=
register_framebuffer
(
fbi
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
erfb
;
goto
erfb
;
return
0
;
return
0
;
erfb:
erfb:
esetpar:
esetpar:
emode:
emode:
fb_dealloc_cmap
(
&
fbi
->
cmap
);
fb_dealloc_cmap
(
&
fbi
->
cmap
);
framebuffer_release
(
fbi
);
framebuffer_release
(
fbi
);
return
ret
;
return
ret
;
}
}
static
bool
chan_filter
(
struct
dma_chan
*
chan
,
void
*
arg
)
static
bool
chan_filter
(
struct
dma_chan
*
chan
,
void
*
arg
)
{
{
struct
dma_chan_request
*
rq
=
arg
;
struct
dma_chan_request
*
rq
=
arg
;
struct
device
*
dev
;
struct
device
*
dev
;
struct
mx3fb_platform_data
*
mx3fb_pdata
;
struct
mx3fb_platform_data
*
mx3fb_pdata
;
if
(
!
rq
)
if
(
!
rq
)
return
false
;
return
false
;
dev
=
rq
->
mx3fb
->
dev
;
dev
=
rq
->
mx3fb
->
dev
;
mx3fb_pdata
=
dev
->
platform_data
;
mx3fb_pdata
=
dev
->
platform_data
;
return
rq
->
id
==
chan
->
chan_id
&&
return
rq
->
id
==
chan
->
chan_id
&&
mx3fb_pdata
->
dma_dev
==
chan
->
device
->
dev
;
mx3fb_pdata
->
dma_dev
==
chan
->
device
->
dev
;
}
}
static
void
release_fbi
(
struct
fb_info
*
fbi
)
static
void
release_fbi
(
struct
fb_info
*
fbi
)
{
{
mx3fb_unmap_video_memory
(
fbi
);
mx3fb_unmap_video_memory
(
fbi
);
fb_dealloc_cmap
(
&
fbi
->
cmap
);
fb_dealloc_cmap
(
&
fbi
->
cmap
);
unregister_framebuffer
(
fbi
);
unregister_framebuffer
(
fbi
);
framebuffer_release
(
fbi
);
framebuffer_release
(
fbi
);
}
}
static
int
mx3fb_probe
(
struct
platform_device
*
pdev
)
static
int
mx3fb_probe
(
struct
platform_device
*
pdev
)
{
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
int
ret
;
int
ret
;
struct
resource
*
sdc_reg
;
struct
resource
*
sdc_reg
;
struct
mx3fb_data
*
mx3fb
;
struct
mx3fb_data
*
mx3fb
;
dma_cap_mask_t
mask
;
dma_cap_mask_t
mask
;
struct
dma_chan
*
chan
;
struct
dma_chan
*
chan
;
struct
dma_chan_request
rq
;
struct
dma_chan_request
rq
;
/*
/*
* Display Interface (DI) and Synchronous Display Controller (SDC)
* Display Interface (DI) and Synchronous Display Controller (SDC)
* registers
* registers
*/
*/
sdc_reg
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
sdc_reg
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
sdc_reg
)
if
(
!
sdc_reg
)
return
-
EINVAL
;
return
-
EINVAL
;
mx3fb
=
kzalloc
(
sizeof
(
*
mx3fb
),
GFP_KERNEL
);
mx3fb
=
kzalloc
(
sizeof
(
*
mx3fb
),
GFP_KERNEL
);
if
(
!
mx3fb
)
if
(
!
mx3fb
)
return
-
ENOMEM
;
return
-
ENOMEM
;
spin_lock_init
(
&
mx3fb
->
lock
);
spin_lock_init
(
&
mx3fb
->
lock
);
mx3fb
->
reg_base
=
ioremap
(
sdc_reg
->
start
,
resource_size
(
sdc_reg
));
mx3fb
->
reg_base
=
ioremap
(
sdc_reg
->
start
,
resource_size
(
sdc_reg
));
if
(
!
mx3fb
->
reg_base
)
{
if
(
!
mx3fb
->
reg_base
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
eremap
;
goto
eremap
;
}
}
pr_debug
(
"Remapped %x to %x at %p
\n
"
,
sdc_reg
->
start
,
sdc_reg
->
end
,
pr_debug
(
"Remapped %x to %x at %p
\n
"
,
sdc_reg
->
start
,
sdc_reg
->
end
,
mx3fb
->
reg_base
);
mx3fb
->
reg_base
);
/* IDMAC interface */
/* IDMAC interface */
dmaengine_get
();
dmaengine_get
();
mx3fb
->
dev
=
dev
;
mx3fb
->
dev
=
dev
;
platform_set_drvdata
(
pdev
,
mx3fb
);
platform_set_drvdata
(
pdev
,
mx3fb
);
rq
.
mx3fb
=
mx3fb
;
rq
.
mx3fb
=
mx3fb
;
dma_cap_zero
(
mask
);
dma_cap_zero
(
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
dma_cap_set
(
DMA_PRIVATE
,
mask
);
dma_cap_set
(
DMA_PRIVATE
,
mask
);
rq
.
id
=
IDMAC_SDC_0
;
rq
.
id
=
IDMAC_SDC_0
;
chan
=
dma_request_channel
(
mask
,
chan_filter
,
&
rq
);
chan
=
dma_request_channel
(
mask
,
chan_filter
,
&
rq
);
if
(
!
chan
)
{
if
(
!
chan
)
{
ret
=
-
EBUSY
;
ret
=
-
EBUSY
;
goto
ersdc0
;
goto
ersdc0
;
}
}
ret
=
init_fb_chan
(
mx3fb
,
to_idmac_chan
(
chan
));
ret
=
init_fb_chan
(
mx3fb
,
to_idmac_chan
(
chan
));
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
eisdc0
;
goto
eisdc0
;
mx3fb
->
backlight_level
=
255
;
mx3fb
->
backlight_level
=
255
;
return
0
;
return
0
;
eisdc0:
eisdc0:
dma_release_channel
(
chan
);
dma_release_channel
(
chan
);
ersdc0:
ersdc0:
dmaengine_put
();
dmaengine_put
();
iounmap
(
mx3fb
->
reg_base
);
iounmap
(
mx3fb
->
reg_base
);
eremap:
eremap:
kfree
(
mx3fb
);
kfree
(
mx3fb
);
dev_err
(
dev
,
"mx3fb: failed to register fb
\n
"
);
dev_err
(
dev
,
"mx3fb: failed to register fb
\n
"
);
return
ret
;
return
ret
;
}
}
static
int
mx3fb_remove
(
struct
platform_device
*
dev
)
static
int
mx3fb_remove
(
struct
platform_device
*
dev
)
{
{
struct
mx3fb_data
*
mx3fb
=
platform_get_drvdata
(
dev
);
struct
mx3fb_data
*
mx3fb
=
platform_get_drvdata
(
dev
);
struct
fb_info
*
fbi
=
mx3fb
->
fbi
;
struct
fb_info
*
fbi
=
mx3fb
->
fbi
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
mx3fb_info
*
mx3_fbi
=
fbi
->
par
;
struct
dma_chan
*
chan
;
struct
dma_chan
*
chan
;
chan
=
&
mx3_fbi
->
idmac_channel
->
dma_chan
;
chan
=
&
mx3_fbi
->
idmac_channel
->
dma_chan
;
release_fbi
(
fbi
);
release_fbi
(
fbi
);
dma_release_channel
(
chan
);
dma_release_channel
(
chan
);
dmaengine_put
();
dmaengine_put
();
iounmap
(
mx3fb
->
reg_base
);
iounmap
(
mx3fb
->
reg_base
);
kfree
(
mx3fb
);
kfree
(
mx3fb
);
return
0
;
return
0
;
}
}
static
struct
platform_driver
mx3fb_driver
=
{
static
struct
platform_driver
mx3fb_driver
=
{
.
driver
=
{
.
driver
=
{
.
name
=
MX3FB_NAME
,
.
name
=
MX3FB_NAME
,
},
},
.
probe
=
mx3fb_probe
,
.
probe
=
mx3fb_probe
,
.
remove
=
mx3fb_remove
,
.
remove
=
mx3fb_remove
,
.
suspend
=
mx3fb_suspend
,
.
suspend
=
mx3fb_suspend
,
.
resume
=
mx3fb_resume
,
.
resume
=
mx3fb_resume
,
};
};
/*
/*
* Parse user specified options (`video=mx3fb:')
* Parse user specified options (`video=mx3fb:')
* example:
* example:
*
video=mx3fb:bpp=16
*
video=mx3fb:bpp=16
*/
*/
static
int
mx3fb_setup
(
void
)
static
int
mx3fb_setup
(
void
)
{
{
#ifndef MODULE
#ifndef MODULE
char
*
opt
,
*
options
=
NULL
;
char
*
opt
,
*
options
=
NULL
;
if
(
fb_get_options
(
"mx3fb"
,
&
options
))
if
(
fb_get_options
(
"mx3fb"
,
&
options
))
return
-
ENODEV
;
return
-
ENODEV
;
if
(
!
options
||
!*
options
)
if
(
!
options
||
!*
options
)
return
0
;
return
0
;
while
((
opt
=
strsep
(
&
options
,
","
))
!=
NULL
)
{
while
((
opt
=
strsep
(
&
options
,
","
))
!=
NULL
)
{
if
(
!*
opt
)
if
(
!*
opt
)
continue
;
continue
;
if
(
!
strncmp
(
opt
,
"bpp="
,
4
))
if
(
!
strncmp
(
opt
,
"bpp="
,
4
))
default_bpp
=
simple_strtoul
(
opt
+
4
,
NULL
,
0
);
default_bpp
=
simple_strtoul
(
opt
+
4
,
NULL
,
0
);
else
else
fb_mode
=
opt
;
fb_mode
=
opt
;
}
}
#endif
#endif
return
0
;
return
0
;
}
}
static
int
__init
mx3fb_init
(
void
)
static
int
__init
mx3fb_init
(
void
)
{
{
int
ret
=
mx3fb_setup
();
int
ret
=
mx3fb_setup
();
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
ret
=
platform_driver_register
(
&
mx3fb_driver
);
ret
=
platform_driver_register
(
&
mx3fb_driver
);
return
ret
;
return
ret
;
}
}
static
void
__exit
mx3fb_exit
(
void
)
static
void
__exit
mx3fb_exit
(
void
)
{
{
platform_driver_unregister
(
&
mx3fb_driver
);
platform_driver_unregister
(
&
mx3fb_driver
);
}
}
module_init
(
mx3fb_init
);
module_init
(
mx3fb_init
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment