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); |
