diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-05-24 22:06:36 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-05-24 22:06:36 -0400 |
commit | e2968f7018193eb5385a925225f135c9ba61eb93 (patch) | |
tree | 97e278a48d00c6c0d7feeb038b9d89fecf480a9f | |
parent | af1ce6b2fad7d572aef040d61a935da28a861853 (diff) | |
parent | f64d8a5fdec35ed36f76130517a5580974a324a4 (diff) |
Merge branch 'mb862xxfb-for-next' of git://git.denx.de/linux-2.6-agust
-rw-r--r-- | drivers/video/Kconfig | 9 | ||||
-rw-r--r-- | drivers/video/mb862xx/Makefile | 5 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xx-i2c.c | 177 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xx_reg.h | 58 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xxfb.h | 36 | ||||
-rw-r--r-- | drivers/video/mb862xx/mb862xxfbdrv.c (renamed from drivers/video/mb862xx/mb862xxfb.c) | 152 |
6 files changed, 425 insertions, 12 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7326962565ce..549b960667c8 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -2294,6 +2294,15 @@ config FB_MB862XX_LIME | |||
2294 | 2294 | ||
2295 | endchoice | 2295 | endchoice |
2296 | 2296 | ||
2297 | config FB_MB862XX_I2C | ||
2298 | bool "Support I2C bus on MB862XX GDC" | ||
2299 | depends on FB_MB862XX && I2C | ||
2300 | default y | ||
2301 | help | ||
2302 | Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter | ||
2303 | driver to support accessing I2C devices on controller's I2C bus. | ||
2304 | These are usually some video decoder chips. | ||
2305 | |||
2297 | config FB_EP93XX | 2306 | config FB_EP93XX |
2298 | tristate "EP93XX frame buffer support" | 2307 | tristate "EP93XX frame buffer support" |
2299 | depends on FB && ARCH_EP93XX | 2308 | depends on FB && ARCH_EP93XX |
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile index d7777714166b..5707ed0e31a7 100644 --- a/drivers/video/mb862xx/Makefile +++ b/drivers/video/mb862xx/Makefile | |||
@@ -2,4 +2,7 @@ | |||
2 | # Makefile for the MB862xx framebuffer driver | 2 | # Makefile for the MB862xx framebuffer driver |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o mb862xxfb_accel.o | 5 | obj-$(CONFIG_FB_MB862XX) += mb862xxfb.o |
6 | |||
7 | mb862xxfb-y := mb862xxfbdrv.o mb862xxfb_accel.o | ||
8 | mb862xxfb-$(CONFIG_FB_MB862XX_I2C) += mb862xx-i2c.o | ||
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c new file mode 100644 index 000000000000..cb77d3b4657d --- /dev/null +++ b/drivers/video/mb862xx/mb862xx-i2c.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Coral-P(A)/Lime I2C adapter driver | ||
3 | * | ||
4 | * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/fb.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/io.h> | ||
15 | |||
16 | #include "mb862xxfb.h" | ||
17 | #include "mb862xx_reg.h" | ||
18 | |||
19 | static int mb862xx_i2c_wait_event(struct i2c_adapter *adap) | ||
20 | { | ||
21 | struct mb862xxfb_par *par = adap->algo_data; | ||
22 | u32 reg; | ||
23 | |||
24 | do { | ||
25 | udelay(1); | ||
26 | reg = inreg(i2c, GC_I2C_BCR); | ||
27 | if (reg & (I2C_INT | I2C_BER)) | ||
28 | break; | ||
29 | } while (1); | ||
30 | |||
31 | return (reg & I2C_BER) ? 0 : 1; | ||
32 | } | ||
33 | |||
34 | static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr) | ||
35 | { | ||
36 | struct mb862xxfb_par *par = adap->algo_data; | ||
37 | |||
38 | outreg(i2c, GC_I2C_DAR, addr); | ||
39 | outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE); | ||
40 | outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START); | ||
41 | if (!mb862xx_i2c_wait_event(adap)) | ||
42 | return -EIO; | ||
43 | par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB); | ||
44 | return par->i2c_rs; | ||
45 | } | ||
46 | |||
47 | static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte) | ||
48 | { | ||
49 | struct mb862xxfb_par *par = adap->algo_data; | ||
50 | |||
51 | outreg(i2c, GC_I2C_DAR, byte); | ||
52 | outreg(i2c, GC_I2C_BCR, I2C_START); | ||
53 | if (!mb862xx_i2c_wait_event(adap)) | ||
54 | return -EIO; | ||
55 | return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB); | ||
56 | } | ||
57 | |||
58 | static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last) | ||
59 | { | ||
60 | struct mb862xxfb_par *par = adap->algo_data; | ||
61 | |||
62 | outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK)); | ||
63 | if (!mb862xx_i2c_wait_event(adap)) | ||
64 | return 0; | ||
65 | *byte = inreg(i2c, GC_I2C_DAR); | ||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | void mb862xx_i2c_stop(struct i2c_adapter *adap) | ||
70 | { | ||
71 | struct mb862xxfb_par *par = adap->algo_data; | ||
72 | |||
73 | outreg(i2c, GC_I2C_BCR, I2C_STOP); | ||
74 | outreg(i2c, GC_I2C_CCR, I2C_DISABLE); | ||
75 | par->i2c_rs = 0; | ||
76 | } | ||
77 | |||
78 | static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m) | ||
79 | { | ||
80 | int i, ret = 0; | ||
81 | int last = m->len - 1; | ||
82 | |||
83 | for (i = 0; i < m->len; i++) { | ||
84 | if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) { | ||
85 | ret = -EIO; | ||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m) | ||
93 | { | ||
94 | int i, ret = 0; | ||
95 | |||
96 | for (i = 0; i < m->len; i++) { | ||
97 | if (!mb862xx_i2c_write_byte(adap, m->buf[i])) { | ||
98 | ret = -EIO; | ||
99 | break; | ||
100 | } | ||
101 | } | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | ||
106 | int num) | ||
107 | { | ||
108 | struct mb862xxfb_par *par = adap->algo_data; | ||
109 | struct i2c_msg *m; | ||
110 | int addr; | ||
111 | int i = 0, err = 0; | ||
112 | |||
113 | dev_dbg(par->dev, "%s: %d msgs\n", __func__, num); | ||
114 | |||
115 | for (i = 0; i < num; i++) { | ||
116 | m = &msgs[i]; | ||
117 | if (!m->len) { | ||
118 | dev_dbg(par->dev, "%s: null msgs\n", __func__); | ||
119 | continue; | ||
120 | } | ||
121 | addr = m->addr; | ||
122 | if (m->flags & I2C_M_RD) | ||
123 | addr |= 1; | ||
124 | |||
125 | err = mb862xx_i2c_do_address(adap, addr); | ||
126 | if (err < 0) | ||
127 | break; | ||
128 | if (m->flags & I2C_M_RD) | ||
129 | err = mb862xx_i2c_read(adap, m); | ||
130 | else | ||
131 | err = mb862xx_i2c_write(adap, m); | ||
132 | } | ||
133 | |||
134 | if (i) | ||
135 | mb862xx_i2c_stop(adap); | ||
136 | |||
137 | return (err < 0) ? err : i; | ||
138 | } | ||
139 | |||
140 | static u32 mb862xx_func(struct i2c_adapter *adap) | ||
141 | { | ||
142 | return I2C_FUNC_SMBUS_BYTE_DATA; | ||
143 | } | ||
144 | |||
145 | static const struct i2c_algorithm mb862xx_algo = { | ||
146 | .master_xfer = mb862xx_xfer, | ||
147 | .functionality = mb862xx_func, | ||
148 | }; | ||
149 | |||
150 | static struct i2c_adapter mb862xx_i2c_adapter = { | ||
151 | .name = "MB862xx I2C adapter", | ||
152 | .algo = &mb862xx_algo, | ||
153 | .owner = THIS_MODULE, | ||
154 | }; | ||
155 | |||
156 | int mb862xx_i2c_init(struct mb862xxfb_par *par) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | mb862xx_i2c_adapter.algo_data = par; | ||
161 | par->adap = &mb862xx_i2c_adapter; | ||
162 | |||
163 | ret = i2c_add_adapter(par->adap); | ||
164 | if (ret < 0) { | ||
165 | dev_err(par->dev, "failed to add %s\n", | ||
166 | mb862xx_i2c_adapter.name); | ||
167 | } | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | void mb862xx_i2c_exit(struct mb862xxfb_par *par) | ||
172 | { | ||
173 | if (par->adap) { | ||
174 | i2c_del_adapter(par->adap); | ||
175 | par->adap = NULL; | ||
176 | } | ||
177 | } | ||
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h index 2ba65e118500..9df48b8edc94 100644 --- a/drivers/video/mb862xx/mb862xx_reg.h +++ b/drivers/video/mb862xx/mb862xx_reg.h | |||
@@ -5,11 +5,8 @@ | |||
5 | #ifndef _MB862XX_REG_H | 5 | #ifndef _MB862XX_REG_H |
6 | #define _MB862XX_REG_H | 6 | #define _MB862XX_REG_H |
7 | 7 | ||
8 | #ifdef MB862XX_MMIO_BOTTOM | ||
9 | #define MB862XX_MMIO_BASE 0x03fc0000 | ||
10 | #else | ||
11 | #define MB862XX_MMIO_BASE 0x01fc0000 | 8 | #define MB862XX_MMIO_BASE 0x01fc0000 |
12 | #endif | 9 | #define MB862XX_MMIO_HIGH_BASE 0x03fc0000 |
13 | #define MB862XX_I2C_BASE 0x0000c000 | 10 | #define MB862XX_I2C_BASE 0x0000c000 |
14 | #define MB862XX_DISP_BASE 0x00010000 | 11 | #define MB862XX_DISP_BASE 0x00010000 |
15 | #define MB862XX_CAP_BASE 0x00018000 | 12 | #define MB862XX_CAP_BASE 0x00018000 |
@@ -23,6 +20,7 @@ | |||
23 | #define GC_IMASK 0x00000024 | 20 | #define GC_IMASK 0x00000024 |
24 | #define GC_SRST 0x0000002c | 21 | #define GC_SRST 0x0000002c |
25 | #define GC_CCF 0x00000038 | 22 | #define GC_CCF 0x00000038 |
23 | #define GC_RSW 0x0000005c | ||
26 | #define GC_CID 0x000000f0 | 24 | #define GC_CID 0x000000f0 |
27 | #define GC_REVISION 0x00000084 | 25 | #define GC_REVISION 0x00000084 |
28 | 26 | ||
@@ -53,10 +51,16 @@ | |||
53 | #define GC_L0OA0 0x00000024 | 51 | #define GC_L0OA0 0x00000024 |
54 | #define GC_L0DA0 0x00000028 | 52 | #define GC_L0DA0 0x00000028 |
55 | #define GC_L0DY_L0DX 0x0000002c | 53 | #define GC_L0DY_L0DX 0x0000002c |
54 | #define GC_L1M 0x00000030 | ||
55 | #define GC_L1DA 0x00000034 | ||
56 | #define GC_DCM1 0x00000100 | 56 | #define GC_DCM1 0x00000100 |
57 | #define GC_L0EM 0x00000110 | 57 | #define GC_L0EM 0x00000110 |
58 | #define GC_L0WY_L0WX 0x00000114 | 58 | #define GC_L0WY_L0WX 0x00000114 |
59 | #define GC_L0WH_L0WW 0x00000118 | 59 | #define GC_L0WH_L0WW 0x00000118 |
60 | #define GC_L1EM 0x00000120 | ||
61 | #define GC_L1WY_L1WX 0x00000124 | ||
62 | #define GC_L1WH_L1WW 0x00000128 | ||
63 | #define GC_DLS 0x00000180 | ||
60 | #define GC_DCM2 0x00000104 | 64 | #define GC_DCM2 0x00000104 |
61 | #define GC_DCM3 0x00000108 | 65 | #define GC_DCM3 0x00000108 |
62 | #define GC_CPM_CUTC 0x000000a0 | 66 | #define GC_CPM_CUTC 0x000000a0 |
@@ -68,6 +72,11 @@ | |||
68 | 72 | ||
69 | #define GC_CPM_CEN0 0x00100000 | 73 | #define GC_CPM_CEN0 0x00100000 |
70 | #define GC_CPM_CEN1 0x00200000 | 74 | #define GC_CPM_CEN1 0x00200000 |
75 | #define GC_DCM1_DEN 0x80000000 | ||
76 | #define GC_DCM1_L1E 0x00020000 | ||
77 | #define GC_L1M_16 0x80000000 | ||
78 | #define GC_L1M_YC 0x40000000 | ||
79 | #define GC_L1M_CS 0x20000000 | ||
71 | 80 | ||
72 | #define GC_DCM01_ESY 0x00000004 | 81 | #define GC_DCM01_ESY 0x00000004 |
73 | #define GC_DCM01_SC 0x00003f00 | 82 | #define GC_DCM01_SC 0x00003f00 |
@@ -79,9 +88,50 @@ | |||
79 | #define GC_L0M_L0C_16 0x80000000 | 88 | #define GC_L0M_L0C_16 0x80000000 |
80 | #define GC_L0EM_L0EC_24 0x40000000 | 89 | #define GC_L0EM_L0EC_24 0x40000000 |
81 | #define GC_L0M_L0W_UNIT 64 | 90 | #define GC_L0M_L0W_UNIT 64 |
91 | #define GC_L1EM_DM 0x02000000 | ||
82 | 92 | ||
83 | #define GC_DISP_REFCLK_400 400 | 93 | #define GC_DISP_REFCLK_400 400 |
84 | 94 | ||
95 | /* I2C */ | ||
96 | #define GC_I2C_BSR 0x00000000 /* BSR */ | ||
97 | #define GC_I2C_BCR 0x00000004 /* BCR */ | ||
98 | #define GC_I2C_CCR 0x00000008 /* CCR */ | ||
99 | #define GC_I2C_ADR 0x0000000C /* ADR */ | ||
100 | #define GC_I2C_DAR 0x00000010 /* DAR */ | ||
101 | |||
102 | #define I2C_DISABLE 0x00000000 | ||
103 | #define I2C_STOP 0x00000000 | ||
104 | #define I2C_START 0x00000010 | ||
105 | #define I2C_REPEATED_START 0x00000030 | ||
106 | #define I2C_CLOCK_AND_ENABLE 0x0000003f | ||
107 | #define I2C_READY 0x01 | ||
108 | #define I2C_INT 0x01 | ||
109 | #define I2C_INTE 0x02 | ||
110 | #define I2C_ACK 0x08 | ||
111 | #define I2C_BER 0x80 | ||
112 | #define I2C_BEIE 0x40 | ||
113 | #define I2C_TRX 0x80 | ||
114 | #define I2C_LRB 0x10 | ||
115 | |||
116 | /* Capture registers and bits */ | ||
117 | #define GC_CAP_VCM 0x00000000 | ||
118 | #define GC_CAP_CSC 0x00000004 | ||
119 | #define GC_CAP_VCS 0x00000008 | ||
120 | #define GC_CAP_CBM 0x00000010 | ||
121 | #define GC_CAP_CBOA 0x00000014 | ||
122 | #define GC_CAP_CBLA 0x00000018 | ||
123 | #define GC_CAP_IMG_START 0x0000001C | ||
124 | #define GC_CAP_IMG_END 0x00000020 | ||
125 | #define GC_CAP_CMSS 0x00000048 | ||
126 | #define GC_CAP_CMDS 0x0000004C | ||
127 | |||
128 | #define GC_VCM_VIE 0x80000000 | ||
129 | #define GC_VCM_CM 0x03000000 | ||
130 | #define GC_VCM_VS_PAL 0x00000002 | ||
131 | #define GC_CBM_OO 0x80000000 | ||
132 | #define GC_CBM_HRV 0x00000010 | ||
133 | #define GC_CBM_CBST 0x00000001 | ||
134 | |||
85 | /* Carmine specific */ | 135 | /* Carmine specific */ |
86 | #define MB86297_DRAW_BASE 0x00020000 | 136 | #define MB86297_DRAW_BASE 0x00020000 |
87 | #define MB86297_DISP0_BASE 0x00100000 | 137 | #define MB86297_DISP0_BASE 0x00100000 |
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h index d7e7cb76bbf2..8550630c1e01 100644 --- a/drivers/video/mb862xx/mb862xxfb.h +++ b/drivers/video/mb862xx/mb862xxfb.h | |||
@@ -1,6 +1,26 @@ | |||
1 | #ifndef __MB862XX_H__ | 1 | #ifndef __MB862XX_H__ |
2 | #define __MB862XX_H__ | 2 | #define __MB862XX_H__ |
3 | 3 | ||
4 | struct mb862xx_l1_cfg { | ||
5 | unsigned short sx; | ||
6 | unsigned short sy; | ||
7 | unsigned short sw; | ||
8 | unsigned short sh; | ||
9 | unsigned short dx; | ||
10 | unsigned short dy; | ||
11 | unsigned short dw; | ||
12 | unsigned short dh; | ||
13 | int mirror; | ||
14 | }; | ||
15 | |||
16 | #define MB862XX_BASE 'M' | ||
17 | #define MB862XX_L1_GET_CFG _IOR(MB862XX_BASE, 0, struct mb862xx_l1_cfg*) | ||
18 | #define MB862XX_L1_SET_CFG _IOW(MB862XX_BASE, 1, struct mb862xx_l1_cfg*) | ||
19 | #define MB862XX_L1_ENABLE _IOW(MB862XX_BASE, 2, int) | ||
20 | #define MB862XX_L1_CAP_CTL _IOW(MB862XX_BASE, 3, int) | ||
21 | |||
22 | #ifdef __KERNEL__ | ||
23 | |||
4 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf | 24 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf |
5 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 | 25 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 |
6 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e | 26 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e |
@@ -38,6 +58,8 @@ struct mb862xxfb_par { | |||
38 | void __iomem *mmio_base; /* remapped registers */ | 58 | void __iomem *mmio_base; /* remapped registers */ |
39 | size_t mapped_vram; /* length of remapped vram */ | 59 | size_t mapped_vram; /* length of remapped vram */ |
40 | size_t mmio_len; /* length of register region */ | 60 | size_t mmio_len; /* length of register region */ |
61 | unsigned long cap_buf; /* capture buffers offset */ | ||
62 | size_t cap_len; /* length of capture buffers */ | ||
41 | 63 | ||
42 | void __iomem *host; /* relocatable reg. bases */ | 64 | void __iomem *host; /* relocatable reg. bases */ |
43 | void __iomem *i2c; | 65 | void __iomem *i2c; |
@@ -57,11 +79,23 @@ struct mb862xxfb_par { | |||
57 | unsigned int refclk; /* disp. reference clock */ | 79 | unsigned int refclk; /* disp. reference clock */ |
58 | struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ | 80 | struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ |
59 | int pre_init; /* don't init display if 1 */ | 81 | int pre_init; /* don't init display if 1 */ |
82 | struct i2c_adapter *adap; /* GDC I2C bus adapter */ | ||
83 | int i2c_rs; | ||
84 | |||
85 | struct mb862xx_l1_cfg l1_cfg; | ||
86 | int l1_stride; | ||
60 | 87 | ||
61 | u32 pseudo_palette[16]; | 88 | u32 pseudo_palette[16]; |
62 | }; | 89 | }; |
63 | 90 | ||
64 | extern void mb862xxfb_init_accel(struct fb_info *info, int xres); | 91 | extern void mb862xxfb_init_accel(struct fb_info *info, int xres); |
92 | #ifdef CONFIG_FB_MB862XX_I2C | ||
93 | extern int mb862xx_i2c_init(struct mb862xxfb_par *par); | ||
94 | extern void mb862xx_i2c_exit(struct mb862xxfb_par *par); | ||
95 | #else | ||
96 | static inline int mb862xx_i2c_init(struct mb862xxfb_par *par) { return 0; } | ||
97 | static inline void mb862xx_i2c_exit(struct mb862xxfb_par *par) { } | ||
98 | #endif | ||
65 | 99 | ||
66 | #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) | 100 | #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) |
67 | #error "Select Lime GDC or CoralP/Carmine support, but not both together" | 101 | #error "Select Lime GDC or CoralP/Carmine support, but not both together" |
@@ -82,4 +116,6 @@ extern void mb862xxfb_init_accel(struct fb_info *info, int xres); | |||
82 | 116 | ||
83 | #define pack(a, b) (((a) << 16) | (b)) | 117 | #define pack(a, b) (((a) << 16) | (b)) |
84 | 118 | ||
119 | #endif /* __KERNEL__ */ | ||
120 | |||
85 | #endif | 121 | #endif |
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfbdrv.c index c76e663a6cd4..ea39336addfb 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #define NR_PALETTE 256 | 28 | #define NR_PALETTE 256 |
29 | #define MB862XX_MEM_SIZE 0x1000000 | 29 | #define MB862XX_MEM_SIZE 0x1000000 |
30 | #define CORALP_MEM_SIZE 0x4000000 | 30 | #define CORALP_MEM_SIZE 0x2000000 |
31 | #define CARMINE_MEM_SIZE 0x8000000 | 31 | #define CARMINE_MEM_SIZE 0x8000000 |
32 | #define DRV_NAME "mb862xxfb" | 32 | #define DRV_NAME "mb862xxfb" |
33 | 33 | ||
@@ -309,6 +309,97 @@ static int mb862xxfb_blank(int mode, struct fb_info *fbi) | |||
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd, | ||
313 | unsigned long arg) | ||
314 | { | ||
315 | struct mb862xxfb_par *par = fbi->par; | ||
316 | struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg; | ||
317 | void __user *argp = (void __user *)arg; | ||
318 | int *enable; | ||
319 | u32 l1em = 0; | ||
320 | |||
321 | switch (cmd) { | ||
322 | case MB862XX_L1_GET_CFG: | ||
323 | if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg))) | ||
324 | return -EFAULT; | ||
325 | break; | ||
326 | case MB862XX_L1_SET_CFG: | ||
327 | if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg))) | ||
328 | return -EFAULT; | ||
329 | if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) { | ||
330 | /* downscaling */ | ||
331 | outreg(cap, GC_CAP_CSC, | ||
332 | pack((l1_cfg->sh << 11) / l1_cfg->dh, | ||
333 | (l1_cfg->sw << 11) / l1_cfg->dw)); | ||
334 | l1em = inreg(disp, GC_L1EM); | ||
335 | l1em &= ~GC_L1EM_DM; | ||
336 | } else if ((l1_cfg->sw <= l1_cfg->dw) && | ||
337 | (l1_cfg->sh <= l1_cfg->dh)) { | ||
338 | /* upscaling */ | ||
339 | outreg(cap, GC_CAP_CSC, | ||
340 | pack((l1_cfg->sh << 11) / l1_cfg->dh, | ||
341 | (l1_cfg->sw << 11) / l1_cfg->dw)); | ||
342 | outreg(cap, GC_CAP_CMSS, | ||
343 | pack(l1_cfg->sw >> 1, l1_cfg->sh)); | ||
344 | outreg(cap, GC_CAP_CMDS, | ||
345 | pack(l1_cfg->dw >> 1, l1_cfg->dh)); | ||
346 | l1em = inreg(disp, GC_L1EM); | ||
347 | l1em |= GC_L1EM_DM; | ||
348 | } | ||
349 | |||
350 | if (l1_cfg->mirror) { | ||
351 | outreg(cap, GC_CAP_CBM, | ||
352 | inreg(cap, GC_CAP_CBM) | GC_CBM_HRV); | ||
353 | l1em |= l1_cfg->dw * 2 - 8; | ||
354 | } else { | ||
355 | outreg(cap, GC_CAP_CBM, | ||
356 | inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV); | ||
357 | l1em &= 0xffff0000; | ||
358 | } | ||
359 | outreg(disp, GC_L1EM, l1em); | ||
360 | break; | ||
361 | case MB862XX_L1_ENABLE: | ||
362 | enable = (int *)arg; | ||
363 | if (*enable) { | ||
364 | outreg(disp, GC_L1DA, par->cap_buf); | ||
365 | outreg(cap, GC_CAP_IMG_START, | ||
366 | pack(l1_cfg->sy >> 1, l1_cfg->sx)); | ||
367 | outreg(cap, GC_CAP_IMG_END, | ||
368 | pack(l1_cfg->sh, l1_cfg->sw)); | ||
369 | outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS | | ||
370 | (par->l1_stride << 16)); | ||
371 | outreg(disp, GC_L1WY_L1WX, | ||
372 | pack(l1_cfg->dy, l1_cfg->dx)); | ||
373 | outreg(disp, GC_L1WH_L1WW, | ||
374 | pack(l1_cfg->dh - 1, l1_cfg->dw)); | ||
375 | outreg(disp, GC_DLS, 1); | ||
376 | outreg(cap, GC_CAP_VCM, | ||
377 | GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL); | ||
378 | outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) | | ||
379 | GC_DCM1_DEN | GC_DCM1_L1E); | ||
380 | } else { | ||
381 | outreg(cap, GC_CAP_VCM, | ||
382 | inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE); | ||
383 | outreg(disp, GC_DCM1, | ||
384 | inreg(disp, GC_DCM1) & ~GC_DCM1_L1E); | ||
385 | } | ||
386 | break; | ||
387 | case MB862XX_L1_CAP_CTL: | ||
388 | enable = (int *)arg; | ||
389 | if (*enable) { | ||
390 | outreg(cap, GC_CAP_VCM, | ||
391 | inreg(cap, GC_CAP_VCM) | GC_VCM_VIE); | ||
392 | } else { | ||
393 | outreg(cap, GC_CAP_VCM, | ||
394 | inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE); | ||
395 | } | ||
396 | break; | ||
397 | default: | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | return 0; | ||
401 | } | ||
402 | |||
312 | /* framebuffer ops */ | 403 | /* framebuffer ops */ |
313 | static struct fb_ops mb862xxfb_ops = { | 404 | static struct fb_ops mb862xxfb_ops = { |
314 | .owner = THIS_MODULE, | 405 | .owner = THIS_MODULE, |
@@ -320,6 +411,7 @@ static struct fb_ops mb862xxfb_ops = { | |||
320 | .fb_fillrect = cfb_fillrect, | 411 | .fb_fillrect = cfb_fillrect, |
321 | .fb_copyarea = cfb_copyarea, | 412 | .fb_copyarea = cfb_copyarea, |
322 | .fb_imageblit = cfb_imageblit, | 413 | .fb_imageblit = cfb_imageblit, |
414 | .fb_ioctl = mb862xxfb_ioctl, | ||
323 | }; | 415 | }; |
324 | 416 | ||
325 | /* initialize fb_info data */ | 417 | /* initialize fb_info data */ |
@@ -328,6 +420,7 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
328 | struct mb862xxfb_par *par = fbi->par; | 420 | struct mb862xxfb_par *par = fbi->par; |
329 | struct mb862xx_gc_mode *mode = par->gc_mode; | 421 | struct mb862xx_gc_mode *mode = par->gc_mode; |
330 | unsigned long reg; | 422 | unsigned long reg; |
423 | int stride; | ||
331 | 424 | ||
332 | fbi->fbops = &mb862xxfb_ops; | 425 | fbi->fbops = &mb862xxfb_ops; |
333 | fbi->pseudo_palette = par->pseudo_palette; | 426 | fbi->pseudo_palette = par->pseudo_palette; |
@@ -336,7 +429,6 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
336 | 429 | ||
337 | strcpy(fbi->fix.id, DRV_NAME); | 430 | strcpy(fbi->fix.id, DRV_NAME); |
338 | fbi->fix.smem_start = (unsigned long)par->fb_base_phys; | 431 | fbi->fix.smem_start = (unsigned long)par->fb_base_phys; |
339 | fbi->fix.smem_len = par->mapped_vram; | ||
340 | fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; | 432 | fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; |
341 | fbi->fix.mmio_len = par->mmio_len; | 433 | fbi->fix.mmio_len = par->mmio_len; |
342 | fbi->fix.accel = FB_ACCEL_NONE; | 434 | fbi->fix.accel = FB_ACCEL_NONE; |
@@ -420,6 +512,28 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | |||
420 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 512 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
421 | fbi->fix.line_length = (fbi->var.xres_virtual * | 513 | fbi->fix.line_length = (fbi->var.xres_virtual * |
422 | fbi->var.bits_per_pixel) / 8; | 514 | fbi->var.bits_per_pixel) / 8; |
515 | fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual; | ||
516 | |||
517 | /* | ||
518 | * reserve space for capture buffers and two cursors | ||
519 | * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16. | ||
520 | */ | ||
521 | par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000; | ||
522 | par->cap_len = 0x1bd800; | ||
523 | par->l1_cfg.sx = 0; | ||
524 | par->l1_cfg.sy = 0; | ||
525 | par->l1_cfg.sw = 720; | ||
526 | par->l1_cfg.sh = 576; | ||
527 | par->l1_cfg.dx = 0; | ||
528 | par->l1_cfg.dy = 0; | ||
529 | par->l1_cfg.dw = 720; | ||
530 | par->l1_cfg.dh = 576; | ||
531 | stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8); | ||
532 | par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0); | ||
533 | outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST | | ||
534 | (par->l1_stride << 16)); | ||
535 | outreg(cap, GC_CAP_CBOA, par->cap_buf); | ||
536 | outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len); | ||
423 | return 0; | 537 | return 0; |
424 | } | 538 | } |
425 | 539 | ||
@@ -742,22 +856,38 @@ static int coralp_init(struct mb862xxfb_par *par) | |||
742 | 856 | ||
743 | par->refclk = GC_DISP_REFCLK_400; | 857 | par->refclk = GC_DISP_REFCLK_400; |
744 | 858 | ||
859 | if (par->mapped_vram >= 0x2000000) { | ||
860 | /* relocate gdc registers space */ | ||
861 | writel(1, par->fb_base + MB862XX_MMIO_BASE + GC_RSW); | ||
862 | udelay(1); /* wait at least 20 bus cycles */ | ||
863 | } | ||
864 | |||
745 | ver = inreg(host, GC_CID); | 865 | ver = inreg(host, GC_CID); |
746 | cn = (ver & GC_CID_CNAME_MSK) >> 8; | 866 | cn = (ver & GC_CID_CNAME_MSK) >> 8; |
747 | ver = ver & GC_CID_VERSION_MSK; | 867 | ver = ver & GC_CID_VERSION_MSK; |
748 | if (cn == 3) { | 868 | if (cn == 3) { |
869 | unsigned long reg; | ||
870 | |||
749 | dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ | 871 | dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ |
750 | (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", | 872 | (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", |
751 | par->pdev->revision); | 873 | par->pdev->revision); |
752 | outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); | 874 | reg = inreg(disp, GC_DCM1); |
753 | udelay(200); | 875 | if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) |
754 | outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); | 876 | par->pre_init = 1; |
755 | udelay(10); | 877 | |
878 | if (!par->pre_init) { | ||
879 | outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); | ||
880 | udelay(200); | ||
881 | outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); | ||
882 | udelay(10); | ||
883 | } | ||
756 | /* Clear interrupt status */ | 884 | /* Clear interrupt status */ |
757 | outreg(host, GC_IST, 0); | 885 | outreg(host, GC_IST, 0); |
758 | } else { | 886 | } else { |
759 | return -ENODEV; | 887 | return -ENODEV; |
760 | } | 888 | } |
889 | |||
890 | mb862xx_i2c_init(par); | ||
761 | return 0; | 891 | return 0; |
762 | } | 892 | } |
763 | 893 | ||
@@ -899,7 +1029,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, | |||
899 | case PCI_DEVICE_ID_FUJITSU_CORALPA: | 1029 | case PCI_DEVICE_ID_FUJITSU_CORALPA: |
900 | par->fb_base_phys = pci_resource_start(par->pdev, 0); | 1030 | par->fb_base_phys = pci_resource_start(par->pdev, 0); |
901 | par->mapped_vram = CORALP_MEM_SIZE; | 1031 | par->mapped_vram = CORALP_MEM_SIZE; |
902 | par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; | 1032 | if (par->mapped_vram >= 0x2000000) { |
1033 | par->mmio_base_phys = par->fb_base_phys + | ||
1034 | MB862XX_MMIO_HIGH_BASE; | ||
1035 | } else { | ||
1036 | par->mmio_base_phys = par->fb_base_phys + | ||
1037 | MB862XX_MMIO_BASE; | ||
1038 | } | ||
903 | par->mmio_len = MB862XX_MMIO_SIZE; | 1039 | par->mmio_len = MB862XX_MMIO_SIZE; |
904 | par->type = BT_CORALP; | 1040 | par->type = BT_CORALP; |
905 | break; | 1041 | break; |
@@ -1009,6 +1145,8 @@ static void __devexit mb862xx_pci_remove(struct pci_dev *pdev) | |||
1009 | outreg(host, GC_IMASK, 0); | 1145 | outreg(host, GC_IMASK, 0); |
1010 | } | 1146 | } |
1011 | 1147 | ||
1148 | mb862xx_i2c_exit(par); | ||
1149 | |||
1012 | device_remove_file(&pdev->dev, &dev_attr_dispregs); | 1150 | device_remove_file(&pdev->dev, &dev_attr_dispregs); |
1013 | 1151 | ||
1014 | pci_set_drvdata(pdev, NULL); | 1152 | pci_set_drvdata(pdev, NULL); |