Commit 370630359cb8db711cf0941cd2a242e28ccfb61e
1 parent
94082f3588
Exists in
master
video: da8xx-fb: reset LCDC only if functional clock changes with DVFS
LCDC functional clock may or may not be derived from CPU/MPU DPLL, For example, AM335x => Separate independent DPLL for LCDC Davinci => Same DPLL as MPU So, on platforms where LCDC functional clock is not derived from CPU/MPU PLL it is not required to reset LCDC module as its functional clock does not change with DVFS. This patch adds check to do reset only if functional clock changes between pre and post notifier callbacks with DVFS. Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Showing 1 changed file with 10 additions and 5 deletions Inline Diff
drivers/video/da8xx-fb.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2008-2009 MontaVista Software Inc. | 2 | * Copyright (C) 2008-2009 MontaVista Software Inc. |
3 | * Copyright (C) 2008-2009 Texas Instruments Inc | 3 | * Copyright (C) 2008-2009 Texas Instruments Inc |
4 | * | 4 | * |
5 | * Based on the LCD driver for TI Avalanche processors written by | 5 | * Based on the LCD driver for TI Avalanche processors written by |
6 | * Ajay Singh and Shalom Hai. | 6 | * Ajay Singh and Shalom Hai. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option)any later version. | 11 | * (at your option)any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/fb.h> | 24 | #include <linux/fb.h> |
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/cpufreq.h> | 31 | #include <linux/cpufreq.h> |
32 | #include <linux/console.h> | 32 | #include <linux/console.h> |
33 | #include <linux/spinlock.h> | 33 | #include <linux/spinlock.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <video/da8xx-fb.h> | 35 | #include <video/da8xx-fb.h> |
36 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
37 | 37 | ||
38 | #define DRIVER_NAME "da8xx_lcdc" | 38 | #define DRIVER_NAME "da8xx_lcdc" |
39 | 39 | ||
40 | #define LCD_VERSION_1 1 | 40 | #define LCD_VERSION_1 1 |
41 | #define LCD_VERSION_2 2 | 41 | #define LCD_VERSION_2 2 |
42 | 42 | ||
43 | /* LCD Status Register */ | 43 | /* LCD Status Register */ |
44 | #define LCD_END_OF_FRAME1 BIT(9) | 44 | #define LCD_END_OF_FRAME1 BIT(9) |
45 | #define LCD_END_OF_FRAME0 BIT(8) | 45 | #define LCD_END_OF_FRAME0 BIT(8) |
46 | #define LCD_PL_LOAD_DONE BIT(6) | 46 | #define LCD_PL_LOAD_DONE BIT(6) |
47 | #define LCD_FIFO_UNDERFLOW BIT(5) | 47 | #define LCD_FIFO_UNDERFLOW BIT(5) |
48 | #define LCD_SYNC_LOST BIT(2) | 48 | #define LCD_SYNC_LOST BIT(2) |
49 | 49 | ||
50 | /* LCD DMA Control Register */ | 50 | /* LCD DMA Control Register */ |
51 | #define LCD_DMA_BURST_SIZE(x) ((x) << 4) | 51 | #define LCD_DMA_BURST_SIZE(x) ((x) << 4) |
52 | #define LCD_DMA_BURST_1 0x0 | 52 | #define LCD_DMA_BURST_1 0x0 |
53 | #define LCD_DMA_BURST_2 0x1 | 53 | #define LCD_DMA_BURST_2 0x1 |
54 | #define LCD_DMA_BURST_4 0x2 | 54 | #define LCD_DMA_BURST_4 0x2 |
55 | #define LCD_DMA_BURST_8 0x3 | 55 | #define LCD_DMA_BURST_8 0x3 |
56 | #define LCD_DMA_BURST_16 0x4 | 56 | #define LCD_DMA_BURST_16 0x4 |
57 | #define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) | 57 | #define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) |
58 | #define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) | 58 | #define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) |
59 | #define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) | 59 | #define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) |
60 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) | 60 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) |
61 | 61 | ||
62 | /* LCD Control Register */ | 62 | /* LCD Control Register */ |
63 | #define LCD_CLK_DIVISOR(x) ((x) << 8) | 63 | #define LCD_CLK_DIVISOR(x) ((x) << 8) |
64 | #define LCD_RASTER_MODE 0x01 | 64 | #define LCD_RASTER_MODE 0x01 |
65 | 65 | ||
66 | /* LCD Raster Control Register */ | 66 | /* LCD Raster Control Register */ |
67 | #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) | 67 | #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) |
68 | #define PALETTE_AND_DATA 0x00 | 68 | #define PALETTE_AND_DATA 0x00 |
69 | #define PALETTE_ONLY 0x01 | 69 | #define PALETTE_ONLY 0x01 |
70 | #define DATA_ONLY 0x02 | 70 | #define DATA_ONLY 0x02 |
71 | 71 | ||
72 | #define LCD_MONO_8BIT_MODE BIT(9) | 72 | #define LCD_MONO_8BIT_MODE BIT(9) |
73 | #define LCD_RASTER_ORDER BIT(8) | 73 | #define LCD_RASTER_ORDER BIT(8) |
74 | #define LCD_TFT_MODE BIT(7) | 74 | #define LCD_TFT_MODE BIT(7) |
75 | #define LCD_V1_UNDERFLOW_INT_ENA BIT(6) | 75 | #define LCD_V1_UNDERFLOW_INT_ENA BIT(6) |
76 | #define LCD_V2_UNDERFLOW_INT_ENA BIT(5) | 76 | #define LCD_V2_UNDERFLOW_INT_ENA BIT(5) |
77 | #define LCD_V1_PL_INT_ENA BIT(4) | 77 | #define LCD_V1_PL_INT_ENA BIT(4) |
78 | #define LCD_V2_PL_INT_ENA BIT(6) | 78 | #define LCD_V2_PL_INT_ENA BIT(6) |
79 | #define LCD_MONOCHROME_MODE BIT(1) | 79 | #define LCD_MONOCHROME_MODE BIT(1) |
80 | #define LCD_RASTER_ENABLE BIT(0) | 80 | #define LCD_RASTER_ENABLE BIT(0) |
81 | #define LCD_TFT_ALT_ENABLE BIT(23) | 81 | #define LCD_TFT_ALT_ENABLE BIT(23) |
82 | #define LCD_STN_565_ENABLE BIT(24) | 82 | #define LCD_STN_565_ENABLE BIT(24) |
83 | #define LCD_V2_DMA_CLK_EN BIT(2) | 83 | #define LCD_V2_DMA_CLK_EN BIT(2) |
84 | #define LCD_V2_LIDD_CLK_EN BIT(1) | 84 | #define LCD_V2_LIDD_CLK_EN BIT(1) |
85 | #define LCD_V2_CORE_CLK_EN BIT(0) | 85 | #define LCD_V2_CORE_CLK_EN BIT(0) |
86 | #define LCD_V2_LPP_B10 26 | 86 | #define LCD_V2_LPP_B10 26 |
87 | #define LCD_V2_TFT_24BPP_MODE BIT(25) | 87 | #define LCD_V2_TFT_24BPP_MODE BIT(25) |
88 | #define LCD_V2_TFT_24BPP_UNPACK BIT(26) | 88 | #define LCD_V2_TFT_24BPP_UNPACK BIT(26) |
89 | 89 | ||
90 | /* LCD Raster Timing 2 Register */ | 90 | /* LCD Raster Timing 2 Register */ |
91 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) | 91 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) |
92 | #define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) | 92 | #define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) |
93 | #define LCD_SYNC_CTRL BIT(25) | 93 | #define LCD_SYNC_CTRL BIT(25) |
94 | #define LCD_SYNC_EDGE BIT(24) | 94 | #define LCD_SYNC_EDGE BIT(24) |
95 | #define LCD_INVERT_PIXEL_CLOCK BIT(22) | 95 | #define LCD_INVERT_PIXEL_CLOCK BIT(22) |
96 | #define LCD_INVERT_LINE_CLOCK BIT(21) | 96 | #define LCD_INVERT_LINE_CLOCK BIT(21) |
97 | #define LCD_INVERT_FRAME_CLOCK BIT(20) | 97 | #define LCD_INVERT_FRAME_CLOCK BIT(20) |
98 | 98 | ||
99 | /* LCD Block */ | 99 | /* LCD Block */ |
100 | #define LCD_PID_REG 0x0 | 100 | #define LCD_PID_REG 0x0 |
101 | #define LCD_CTRL_REG 0x4 | 101 | #define LCD_CTRL_REG 0x4 |
102 | #define LCD_STAT_REG 0x8 | 102 | #define LCD_STAT_REG 0x8 |
103 | #define LCD_RASTER_CTRL_REG 0x28 | 103 | #define LCD_RASTER_CTRL_REG 0x28 |
104 | #define LCD_RASTER_TIMING_0_REG 0x2C | 104 | #define LCD_RASTER_TIMING_0_REG 0x2C |
105 | #define LCD_RASTER_TIMING_1_REG 0x30 | 105 | #define LCD_RASTER_TIMING_1_REG 0x30 |
106 | #define LCD_RASTER_TIMING_2_REG 0x34 | 106 | #define LCD_RASTER_TIMING_2_REG 0x34 |
107 | #define LCD_DMA_CTRL_REG 0x40 | 107 | #define LCD_DMA_CTRL_REG 0x40 |
108 | #define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 | 108 | #define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 |
109 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 | 109 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 |
110 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C | 110 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C |
111 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 | 111 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 |
112 | 112 | ||
113 | /* Interrupt Registers available only in Version 2 */ | 113 | /* Interrupt Registers available only in Version 2 */ |
114 | #define LCD_RAW_STAT_REG 0x58 | 114 | #define LCD_RAW_STAT_REG 0x58 |
115 | #define LCD_MASKED_STAT_REG 0x5c | 115 | #define LCD_MASKED_STAT_REG 0x5c |
116 | #define LCD_INT_ENABLE_SET_REG 0x60 | 116 | #define LCD_INT_ENABLE_SET_REG 0x60 |
117 | #define LCD_INT_ENABLE_CLR_REG 0x64 | 117 | #define LCD_INT_ENABLE_CLR_REG 0x64 |
118 | #define LCD_END_OF_INT_IND_REG 0x68 | 118 | #define LCD_END_OF_INT_IND_REG 0x68 |
119 | 119 | ||
120 | /* Clock registers available only on Version 2 */ | 120 | /* Clock registers available only on Version 2 */ |
121 | #define LCD_CLK_ENABLE_REG 0x6c | 121 | #define LCD_CLK_ENABLE_REG 0x6c |
122 | #define LCD_CLK_RESET_REG 0x70 | 122 | #define LCD_CLK_RESET_REG 0x70 |
123 | #define LCD_CLK_MAIN_RESET BIT(3) | 123 | #define LCD_CLK_MAIN_RESET BIT(3) |
124 | 124 | ||
125 | #define LCD_NUM_BUFFERS 2 | 125 | #define LCD_NUM_BUFFERS 2 |
126 | 126 | ||
127 | #define WSI_TIMEOUT 50 | 127 | #define WSI_TIMEOUT 50 |
128 | #define PALETTE_SIZE 256 | 128 | #define PALETTE_SIZE 256 |
129 | #define LEFT_MARGIN 64 | 129 | #define LEFT_MARGIN 64 |
130 | #define RIGHT_MARGIN 64 | 130 | #define RIGHT_MARGIN 64 |
131 | #define UPPER_MARGIN 32 | 131 | #define UPPER_MARGIN 32 |
132 | #define LOWER_MARGIN 32 | 132 | #define LOWER_MARGIN 32 |
133 | 133 | ||
134 | static resource_size_t da8xx_fb_reg_base; | 134 | static resource_size_t da8xx_fb_reg_base; |
135 | static struct resource *lcdc_regs; | 135 | static struct resource *lcdc_regs; |
136 | static unsigned int lcd_revision; | 136 | static unsigned int lcd_revision; |
137 | static irq_handler_t lcdc_irq_handler; | 137 | static irq_handler_t lcdc_irq_handler; |
138 | 138 | ||
139 | static inline unsigned int lcdc_read(unsigned int addr) | 139 | static inline unsigned int lcdc_read(unsigned int addr) |
140 | { | 140 | { |
141 | return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); | 141 | return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); |
142 | } | 142 | } |
143 | 143 | ||
144 | static inline void lcdc_write(unsigned int val, unsigned int addr) | 144 | static inline void lcdc_write(unsigned int val, unsigned int addr) |
145 | { | 145 | { |
146 | __raw_writel(val, da8xx_fb_reg_base + (addr)); | 146 | __raw_writel(val, da8xx_fb_reg_base + (addr)); |
147 | } | 147 | } |
148 | 148 | ||
149 | struct da8xx_fb_par { | 149 | struct da8xx_fb_par { |
150 | resource_size_t p_palette_base; | 150 | resource_size_t p_palette_base; |
151 | unsigned char *v_palette_base; | 151 | unsigned char *v_palette_base; |
152 | dma_addr_t vram_phys; | 152 | dma_addr_t vram_phys; |
153 | unsigned long vram_size; | 153 | unsigned long vram_size; |
154 | void *vram_virt; | 154 | void *vram_virt; |
155 | unsigned int dma_start; | 155 | unsigned int dma_start; |
156 | unsigned int dma_end; | 156 | unsigned int dma_end; |
157 | struct clk *lcdc_clk; | 157 | struct clk *lcdc_clk; |
158 | int irq; | 158 | int irq; |
159 | unsigned short pseudo_palette[32]; | 159 | unsigned short pseudo_palette[32]; |
160 | unsigned int palette_sz; | 160 | unsigned int palette_sz; |
161 | unsigned int pxl_clk; | 161 | unsigned int pxl_clk; |
162 | int blank; | 162 | int blank; |
163 | wait_queue_head_t vsync_wait; | 163 | wait_queue_head_t vsync_wait; |
164 | int vsync_flag; | 164 | int vsync_flag; |
165 | int vsync_timeout; | 165 | int vsync_timeout; |
166 | spinlock_t lock_for_chan_update; | 166 | spinlock_t lock_for_chan_update; |
167 | 167 | ||
168 | /* | 168 | /* |
169 | * LCDC has 2 ping pong DMA channels, channel 0 | 169 | * LCDC has 2 ping pong DMA channels, channel 0 |
170 | * and channel 1. | 170 | * and channel 1. |
171 | */ | 171 | */ |
172 | unsigned int which_dma_channel_done; | 172 | unsigned int which_dma_channel_done; |
173 | #ifdef CONFIG_CPU_FREQ | 173 | #ifdef CONFIG_CPU_FREQ |
174 | struct notifier_block freq_transition; | 174 | struct notifier_block freq_transition; |
175 | unsigned int lcd_fck_rate; | ||
175 | #endif | 176 | #endif |
176 | void (*panel_power_ctrl)(int); | 177 | void (*panel_power_ctrl)(int); |
177 | }; | 178 | }; |
178 | 179 | ||
179 | /* Variable Screen Information */ | 180 | /* Variable Screen Information */ |
180 | static struct fb_var_screeninfo da8xx_fb_var __devinitdata = { | 181 | static struct fb_var_screeninfo da8xx_fb_var __devinitdata = { |
181 | .xoffset = 0, | 182 | .xoffset = 0, |
182 | .yoffset = 0, | 183 | .yoffset = 0, |
183 | .transp = {0, 0, 0}, | 184 | .transp = {0, 0, 0}, |
184 | .nonstd = 0, | 185 | .nonstd = 0, |
185 | .activate = 0, | 186 | .activate = 0, |
186 | .height = -1, | 187 | .height = -1, |
187 | .width = -1, | 188 | .width = -1, |
188 | .pixclock = 33333,/*Pico Sec*/ | 189 | .pixclock = 33333,/*Pico Sec*/ |
189 | .accel_flags = 0, | 190 | .accel_flags = 0, |
190 | .left_margin = LEFT_MARGIN, | 191 | .left_margin = LEFT_MARGIN, |
191 | .right_margin = RIGHT_MARGIN, | 192 | .right_margin = RIGHT_MARGIN, |
192 | .upper_margin = UPPER_MARGIN, | 193 | .upper_margin = UPPER_MARGIN, |
193 | .lower_margin = LOWER_MARGIN, | 194 | .lower_margin = LOWER_MARGIN, |
194 | .sync = 0, | 195 | .sync = 0, |
195 | .vmode = FB_VMODE_NONINTERLACED | 196 | .vmode = FB_VMODE_NONINTERLACED |
196 | }; | 197 | }; |
197 | 198 | ||
198 | static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = { | 199 | static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = { |
199 | .id = "DA8xx FB Drv", | 200 | .id = "DA8xx FB Drv", |
200 | .type = FB_TYPE_PACKED_PIXELS, | 201 | .type = FB_TYPE_PACKED_PIXELS, |
201 | .type_aux = 0, | 202 | .type_aux = 0, |
202 | .visual = FB_VISUAL_PSEUDOCOLOR, | 203 | .visual = FB_VISUAL_PSEUDOCOLOR, |
203 | .xpanstep = 0, | 204 | .xpanstep = 0, |
204 | .ypanstep = 1, | 205 | .ypanstep = 1, |
205 | .ywrapstep = 0, | 206 | .ywrapstep = 0, |
206 | .accel = FB_ACCEL_NONE | 207 | .accel = FB_ACCEL_NONE |
207 | }; | 208 | }; |
208 | 209 | ||
209 | struct da8xx_panel { | 210 | struct da8xx_panel { |
210 | const char name[25]; /* Full name <vendor>_<model> */ | 211 | const char name[25]; /* Full name <vendor>_<model> */ |
211 | unsigned short width; | 212 | unsigned short width; |
212 | unsigned short height; | 213 | unsigned short height; |
213 | int hfp; /* Horizontal front porch */ | 214 | int hfp; /* Horizontal front porch */ |
214 | int hbp; /* Horizontal back porch */ | 215 | int hbp; /* Horizontal back porch */ |
215 | int hsw; /* Horizontal Sync Pulse Width */ | 216 | int hsw; /* Horizontal Sync Pulse Width */ |
216 | int vfp; /* Vertical front porch */ | 217 | int vfp; /* Vertical front porch */ |
217 | int vbp; /* Vertical back porch */ | 218 | int vbp; /* Vertical back porch */ |
218 | int vsw; /* Vertical Sync Pulse Width */ | 219 | int vsw; /* Vertical Sync Pulse Width */ |
219 | unsigned int pxl_clk; /* Pixel clock */ | 220 | unsigned int pxl_clk; /* Pixel clock */ |
220 | unsigned char invert_pxl_clk; /* Invert Pixel clock */ | 221 | unsigned char invert_pxl_clk; /* Invert Pixel clock */ |
221 | }; | 222 | }; |
222 | 223 | ||
223 | static vsync_callback_t vsync_cb_handler; | 224 | static vsync_callback_t vsync_cb_handler; |
224 | static void *vsync_cb_arg; | 225 | static void *vsync_cb_arg; |
225 | 226 | ||
226 | static struct da8xx_panel known_lcd_panels[] = { | 227 | static struct da8xx_panel known_lcd_panels[] = { |
227 | /* Sharp LCD035Q3DG01 */ | 228 | /* Sharp LCD035Q3DG01 */ |
228 | [0] = { | 229 | [0] = { |
229 | .name = "Sharp_LCD035Q3DG01", | 230 | .name = "Sharp_LCD035Q3DG01", |
230 | .width = 320, | 231 | .width = 320, |
231 | .height = 240, | 232 | .height = 240, |
232 | .hfp = 8, | 233 | .hfp = 8, |
233 | .hbp = 6, | 234 | .hbp = 6, |
234 | .hsw = 0, | 235 | .hsw = 0, |
235 | .vfp = 2, | 236 | .vfp = 2, |
236 | .vbp = 2, | 237 | .vbp = 2, |
237 | .vsw = 0, | 238 | .vsw = 0, |
238 | .pxl_clk = 4608000, | 239 | .pxl_clk = 4608000, |
239 | .invert_pxl_clk = 1, | 240 | .invert_pxl_clk = 1, |
240 | }, | 241 | }, |
241 | /* Sharp LK043T1DG01 */ | 242 | /* Sharp LK043T1DG01 */ |
242 | [1] = { | 243 | [1] = { |
243 | .name = "Sharp_LK043T1DG01", | 244 | .name = "Sharp_LK043T1DG01", |
244 | .width = 480, | 245 | .width = 480, |
245 | .height = 272, | 246 | .height = 272, |
246 | .hfp = 2, | 247 | .hfp = 2, |
247 | .hbp = 2, | 248 | .hbp = 2, |
248 | .hsw = 41, | 249 | .hsw = 41, |
249 | .vfp = 3, | 250 | .vfp = 3, |
250 | .vbp = 3, | 251 | .vbp = 3, |
251 | .vsw = 10, | 252 | .vsw = 10, |
252 | .pxl_clk = 7833600, | 253 | .pxl_clk = 7833600, |
253 | .invert_pxl_clk = 0, | 254 | .invert_pxl_clk = 0, |
254 | }, | 255 | }, |
255 | /* ThreeFive S9700RTWV35TR */ | 256 | /* ThreeFive S9700RTWV35TR */ |
256 | [2] = { | 257 | [2] = { |
257 | .name = "TFC_S9700RTWV35TR_01B", | 258 | .name = "TFC_S9700RTWV35TR_01B", |
258 | .width = 800, | 259 | .width = 800, |
259 | .height = 480, | 260 | .height = 480, |
260 | .hfp = 39, | 261 | .hfp = 39, |
261 | .hbp = 39, | 262 | .hbp = 39, |
262 | .hsw = 47, | 263 | .hsw = 47, |
263 | .vfp = 13, | 264 | .vfp = 13, |
264 | .vbp = 29, | 265 | .vbp = 29, |
265 | .vsw = 2, | 266 | .vsw = 2, |
266 | .pxl_clk = 30000000, | 267 | .pxl_clk = 30000000, |
267 | .invert_pxl_clk = 0, | 268 | .invert_pxl_clk = 0, |
268 | }, | 269 | }, |
269 | }; | 270 | }; |
270 | 271 | ||
271 | /* Enable the Raster Engine of the LCD Controller */ | 272 | /* Enable the Raster Engine of the LCD Controller */ |
272 | static inline void lcd_enable_raster(void) | 273 | static inline void lcd_enable_raster(void) |
273 | { | 274 | { |
274 | u32 reg; | 275 | u32 reg; |
275 | 276 | ||
276 | /* Bring LCDC out of reset */ | 277 | /* Bring LCDC out of reset */ |
277 | if (lcd_revision == LCD_VERSION_2) | 278 | if (lcd_revision == LCD_VERSION_2) |
278 | lcdc_write(0, LCD_CLK_RESET_REG); | 279 | lcdc_write(0, LCD_CLK_RESET_REG); |
279 | 280 | ||
280 | reg = lcdc_read(LCD_RASTER_CTRL_REG); | 281 | reg = lcdc_read(LCD_RASTER_CTRL_REG); |
281 | if (!(reg & LCD_RASTER_ENABLE)) | 282 | if (!(reg & LCD_RASTER_ENABLE)) |
282 | lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); | 283 | lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); |
283 | } | 284 | } |
284 | 285 | ||
285 | /* Disable the Raster Engine of the LCD Controller */ | 286 | /* Disable the Raster Engine of the LCD Controller */ |
286 | static inline void lcd_disable_raster(void) | 287 | static inline void lcd_disable_raster(void) |
287 | { | 288 | { |
288 | u32 reg; | 289 | u32 reg; |
289 | 290 | ||
290 | reg = lcdc_read(LCD_RASTER_CTRL_REG); | 291 | reg = lcdc_read(LCD_RASTER_CTRL_REG); |
291 | if (reg & LCD_RASTER_ENABLE) | 292 | if (reg & LCD_RASTER_ENABLE) |
292 | lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); | 293 | lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); |
293 | 294 | ||
294 | if (lcd_revision == LCD_VERSION_2) | 295 | if (lcd_revision == LCD_VERSION_2) |
295 | /* Write 1 to reset LCDC */ | 296 | /* Write 1 to reset LCDC */ |
296 | lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); | 297 | lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); |
297 | } | 298 | } |
298 | 299 | ||
299 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | 300 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) |
300 | { | 301 | { |
301 | u32 start; | 302 | u32 start; |
302 | u32 end; | 303 | u32 end; |
303 | u32 reg_ras; | 304 | u32 reg_ras; |
304 | u32 reg_dma; | 305 | u32 reg_dma; |
305 | u32 reg_int; | 306 | u32 reg_int; |
306 | 307 | ||
307 | /* init reg to clear PLM (loading mode) fields */ | 308 | /* init reg to clear PLM (loading mode) fields */ |
308 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 309 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
309 | reg_ras &= ~(3 << 20); | 310 | reg_ras &= ~(3 << 20); |
310 | 311 | ||
311 | reg_dma = lcdc_read(LCD_DMA_CTRL_REG); | 312 | reg_dma = lcdc_read(LCD_DMA_CTRL_REG); |
312 | 313 | ||
313 | if (load_mode == LOAD_DATA) { | 314 | if (load_mode == LOAD_DATA) { |
314 | start = par->dma_start; | 315 | start = par->dma_start; |
315 | end = par->dma_end; | 316 | end = par->dma_end; |
316 | 317 | ||
317 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); | 318 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); |
318 | if (lcd_revision == LCD_VERSION_1) { | 319 | if (lcd_revision == LCD_VERSION_1) { |
319 | reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; | 320 | reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; |
320 | } else { | 321 | } else { |
321 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | 322 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | |
322 | LCD_V2_END_OF_FRAME0_INT_ENA | | 323 | LCD_V2_END_OF_FRAME0_INT_ENA | |
323 | LCD_V2_END_OF_FRAME1_INT_ENA; | 324 | LCD_V2_END_OF_FRAME1_INT_ENA; |
324 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | 325 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); |
325 | } | 326 | } |
326 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; | 327 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; |
327 | 328 | ||
328 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 329 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
329 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 330 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
330 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | 331 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); |
331 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | 332 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); |
332 | } else if (load_mode == LOAD_PALETTE) { | 333 | } else if (load_mode == LOAD_PALETTE) { |
333 | start = par->p_palette_base; | 334 | start = par->p_palette_base; |
334 | end = start + par->palette_sz - 1; | 335 | end = start + par->palette_sz - 1; |
335 | 336 | ||
336 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); | 337 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); |
337 | 338 | ||
338 | if (lcd_revision == LCD_VERSION_1) { | 339 | if (lcd_revision == LCD_VERSION_1) { |
339 | reg_ras |= LCD_V1_PL_INT_ENA; | 340 | reg_ras |= LCD_V1_PL_INT_ENA; |
340 | } else { | 341 | } else { |
341 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | 342 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | |
342 | LCD_V2_PL_INT_ENA; | 343 | LCD_V2_PL_INT_ENA; |
343 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | 344 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); |
344 | } | 345 | } |
345 | 346 | ||
346 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 347 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
347 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 348 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
348 | } | 349 | } |
349 | 350 | ||
350 | lcdc_write(reg_dma, LCD_DMA_CTRL_REG); | 351 | lcdc_write(reg_dma, LCD_DMA_CTRL_REG); |
351 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); | 352 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); |
352 | 353 | ||
353 | /* | 354 | /* |
354 | * The Raster enable bit must be set after all other control fields are | 355 | * The Raster enable bit must be set after all other control fields are |
355 | * set. | 356 | * set. |
356 | */ | 357 | */ |
357 | lcd_enable_raster(); | 358 | lcd_enable_raster(); |
358 | } | 359 | } |
359 | 360 | ||
360 | /* Configure the Burst Size and fifo threhold of DMA */ | 361 | /* Configure the Burst Size and fifo threhold of DMA */ |
361 | static int lcd_cfg_dma(int burst_size, int fifo_th) | 362 | static int lcd_cfg_dma(int burst_size, int fifo_th) |
362 | { | 363 | { |
363 | u32 reg; | 364 | u32 reg; |
364 | 365 | ||
365 | reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001; | 366 | reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001; |
366 | switch (burst_size) { | 367 | switch (burst_size) { |
367 | case 1: | 368 | case 1: |
368 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); | 369 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); |
369 | break; | 370 | break; |
370 | case 2: | 371 | case 2: |
371 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); | 372 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); |
372 | break; | 373 | break; |
373 | case 4: | 374 | case 4: |
374 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); | 375 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); |
375 | break; | 376 | break; |
376 | case 8: | 377 | case 8: |
377 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); | 378 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); |
378 | break; | 379 | break; |
379 | case 16: | 380 | case 16: |
380 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); | 381 | reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); |
381 | break; | 382 | break; |
382 | default: | 383 | default: |
383 | return -EINVAL; | 384 | return -EINVAL; |
384 | } | 385 | } |
385 | 386 | ||
386 | reg |= (fifo_th << 8); | 387 | reg |= (fifo_th << 8); |
387 | 388 | ||
388 | lcdc_write(reg, LCD_DMA_CTRL_REG); | 389 | lcdc_write(reg, LCD_DMA_CTRL_REG); |
389 | 390 | ||
390 | return 0; | 391 | return 0; |
391 | } | 392 | } |
392 | 393 | ||
393 | static void lcd_cfg_ac_bias(int period, int transitions_per_int) | 394 | static void lcd_cfg_ac_bias(int period, int transitions_per_int) |
394 | { | 395 | { |
395 | u32 reg; | 396 | u32 reg; |
396 | 397 | ||
397 | /* Set the AC Bias Period and Number of Transisitons per Interrupt */ | 398 | /* Set the AC Bias Period and Number of Transisitons per Interrupt */ |
398 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000; | 399 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000; |
399 | reg |= LCD_AC_BIAS_FREQUENCY(period) | | 400 | reg |= LCD_AC_BIAS_FREQUENCY(period) | |
400 | LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); | 401 | LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); |
401 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); | 402 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); |
402 | } | 403 | } |
403 | 404 | ||
404 | static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, | 405 | static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, |
405 | int front_porch) | 406 | int front_porch) |
406 | { | 407 | { |
407 | u32 reg; | 408 | u32 reg; |
408 | 409 | ||
409 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf; | 410 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf; |
410 | reg |= ((back_porch & 0xff) << 24) | 411 | reg |= ((back_porch & 0xff) << 24) |
411 | | ((front_porch & 0xff) << 16) | 412 | | ((front_porch & 0xff) << 16) |
412 | | ((pulse_width & 0x3f) << 10); | 413 | | ((pulse_width & 0x3f) << 10); |
413 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); | 414 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); |
414 | } | 415 | } |
415 | 416 | ||
416 | static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, | 417 | static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, |
417 | int front_porch) | 418 | int front_porch) |
418 | { | 419 | { |
419 | u32 reg; | 420 | u32 reg; |
420 | 421 | ||
421 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff; | 422 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff; |
422 | reg |= ((back_porch & 0xff) << 24) | 423 | reg |= ((back_porch & 0xff) << 24) |
423 | | ((front_porch & 0xff) << 16) | 424 | | ((front_porch & 0xff) << 16) |
424 | | ((pulse_width & 0x3f) << 10); | 425 | | ((pulse_width & 0x3f) << 10); |
425 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); | 426 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); |
426 | } | 427 | } |
427 | 428 | ||
428 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | 429 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) |
429 | { | 430 | { |
430 | u32 reg; | 431 | u32 reg; |
431 | u32 reg_int; | 432 | u32 reg_int; |
432 | 433 | ||
433 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | | 434 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | |
434 | LCD_MONO_8BIT_MODE | | 435 | LCD_MONO_8BIT_MODE | |
435 | LCD_MONOCHROME_MODE); | 436 | LCD_MONOCHROME_MODE); |
436 | 437 | ||
437 | switch (cfg->p_disp_panel->panel_shade) { | 438 | switch (cfg->p_disp_panel->panel_shade) { |
438 | case MONOCHROME: | 439 | case MONOCHROME: |
439 | reg |= LCD_MONOCHROME_MODE; | 440 | reg |= LCD_MONOCHROME_MODE; |
440 | if (cfg->mono_8bit_mode) | 441 | if (cfg->mono_8bit_mode) |
441 | reg |= LCD_MONO_8BIT_MODE; | 442 | reg |= LCD_MONO_8BIT_MODE; |
442 | break; | 443 | break; |
443 | case COLOR_ACTIVE: | 444 | case COLOR_ACTIVE: |
444 | reg |= LCD_TFT_MODE; | 445 | reg |= LCD_TFT_MODE; |
445 | if (cfg->tft_alt_mode) | 446 | if (cfg->tft_alt_mode) |
446 | reg |= LCD_TFT_ALT_ENABLE; | 447 | reg |= LCD_TFT_ALT_ENABLE; |
447 | break; | 448 | break; |
448 | 449 | ||
449 | case COLOR_PASSIVE: | 450 | case COLOR_PASSIVE: |
450 | if (cfg->stn_565_mode) | 451 | if (cfg->stn_565_mode) |
451 | reg |= LCD_STN_565_ENABLE; | 452 | reg |= LCD_STN_565_ENABLE; |
452 | break; | 453 | break; |
453 | 454 | ||
454 | default: | 455 | default: |
455 | return -EINVAL; | 456 | return -EINVAL; |
456 | } | 457 | } |
457 | 458 | ||
458 | /* enable additional interrupts here */ | 459 | /* enable additional interrupts here */ |
459 | if (lcd_revision == LCD_VERSION_1) { | 460 | if (lcd_revision == LCD_VERSION_1) { |
460 | reg |= LCD_V1_UNDERFLOW_INT_ENA; | 461 | reg |= LCD_V1_UNDERFLOW_INT_ENA; |
461 | } else { | 462 | } else { |
462 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | 463 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | |
463 | LCD_V2_UNDERFLOW_INT_ENA; | 464 | LCD_V2_UNDERFLOW_INT_ENA; |
464 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | 465 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); |
465 | } | 466 | } |
466 | 467 | ||
467 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | 468 | lcdc_write(reg, LCD_RASTER_CTRL_REG); |
468 | 469 | ||
469 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); | 470 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); |
470 | 471 | ||
471 | if (cfg->sync_ctrl) | 472 | if (cfg->sync_ctrl) |
472 | reg |= LCD_SYNC_CTRL; | 473 | reg |= LCD_SYNC_CTRL; |
473 | else | 474 | else |
474 | reg &= ~LCD_SYNC_CTRL; | 475 | reg &= ~LCD_SYNC_CTRL; |
475 | 476 | ||
476 | if (cfg->sync_edge) | 477 | if (cfg->sync_edge) |
477 | reg |= LCD_SYNC_EDGE; | 478 | reg |= LCD_SYNC_EDGE; |
478 | else | 479 | else |
479 | reg &= ~LCD_SYNC_EDGE; | 480 | reg &= ~LCD_SYNC_EDGE; |
480 | 481 | ||
481 | if (cfg->invert_line_clock) | 482 | if (cfg->invert_line_clock) |
482 | reg |= LCD_INVERT_LINE_CLOCK; | 483 | reg |= LCD_INVERT_LINE_CLOCK; |
483 | else | 484 | else |
484 | reg &= ~LCD_INVERT_LINE_CLOCK; | 485 | reg &= ~LCD_INVERT_LINE_CLOCK; |
485 | 486 | ||
486 | if (cfg->invert_frm_clock) | 487 | if (cfg->invert_frm_clock) |
487 | reg |= LCD_INVERT_FRAME_CLOCK; | 488 | reg |= LCD_INVERT_FRAME_CLOCK; |
488 | else | 489 | else |
489 | reg &= ~LCD_INVERT_FRAME_CLOCK; | 490 | reg &= ~LCD_INVERT_FRAME_CLOCK; |
490 | 491 | ||
491 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); | 492 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); |
492 | 493 | ||
493 | return 0; | 494 | return 0; |
494 | } | 495 | } |
495 | 496 | ||
496 | static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | 497 | static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, |
497 | u32 bpp, u32 raster_order) | 498 | u32 bpp, u32 raster_order) |
498 | { | 499 | { |
499 | u32 reg; | 500 | u32 reg; |
500 | 501 | ||
501 | /* Set the Panel Width */ | 502 | /* Set the Panel Width */ |
502 | /* Pixels per line = (PPL + 1)*16 */ | 503 | /* Pixels per line = (PPL + 1)*16 */ |
503 | if (lcd_revision == LCD_VERSION_1) { | 504 | if (lcd_revision == LCD_VERSION_1) { |
504 | /* | 505 | /* |
505 | * 0x3F in bits 4..9 gives max horizontal resolution = 1024 | 506 | * 0x3F in bits 4..9 gives max horizontal resolution = 1024 |
506 | * pixels. | 507 | * pixels. |
507 | */ | 508 | */ |
508 | width &= 0x3f0; | 509 | width &= 0x3f0; |
509 | } else { | 510 | } else { |
510 | /* | 511 | /* |
511 | * 0x7F in bits 4..10 gives max horizontal resolution = 2048 | 512 | * 0x7F in bits 4..10 gives max horizontal resolution = 2048 |
512 | * pixels. | 513 | * pixels. |
513 | */ | 514 | */ |
514 | width &= 0x7f0; | 515 | width &= 0x7f0; |
515 | } | 516 | } |
516 | 517 | ||
517 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG); | 518 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG); |
518 | reg &= 0xfffffc00; | 519 | reg &= 0xfffffc00; |
519 | if (lcd_revision == LCD_VERSION_1) { | 520 | if (lcd_revision == LCD_VERSION_1) { |
520 | reg |= ((width >> 4) - 1) << 4; | 521 | reg |= ((width >> 4) - 1) << 4; |
521 | } else { | 522 | } else { |
522 | width = (width >> 4) - 1; | 523 | width = (width >> 4) - 1; |
523 | reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); | 524 | reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); |
524 | } | 525 | } |
525 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); | 526 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); |
526 | 527 | ||
527 | /* Set the Panel Height */ | 528 | /* Set the Panel Height */ |
528 | /* Set bits 9:0 of Lines Per Pixel */ | 529 | /* Set bits 9:0 of Lines Per Pixel */ |
529 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG); | 530 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG); |
530 | reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); | 531 | reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); |
531 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); | 532 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); |
532 | 533 | ||
533 | /* Set bit 10 of Lines Per Pixel */ | 534 | /* Set bit 10 of Lines Per Pixel */ |
534 | if (lcd_revision == LCD_VERSION_2) { | 535 | if (lcd_revision == LCD_VERSION_2) { |
535 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); | 536 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); |
536 | reg |= ((height - 1) & 0x400) << 16; | 537 | reg |= ((height - 1) & 0x400) << 16; |
537 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); | 538 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); |
538 | } | 539 | } |
539 | 540 | ||
540 | /* Set the Raster Order of the Frame Buffer */ | 541 | /* Set the Raster Order of the Frame Buffer */ |
541 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); | 542 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); |
542 | if (raster_order) | 543 | if (raster_order) |
543 | reg |= LCD_RASTER_ORDER; | 544 | reg |= LCD_RASTER_ORDER; |
544 | 545 | ||
545 | if (bpp == 24) | 546 | if (bpp == 24) |
546 | reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE); | 547 | reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE); |
547 | else if (bpp == 32) | 548 | else if (bpp == 32) |
548 | reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE | 549 | reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE |
549 | | LCD_V2_TFT_24BPP_UNPACK); | 550 | | LCD_V2_TFT_24BPP_UNPACK); |
550 | 551 | ||
551 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | 552 | lcdc_write(reg, LCD_RASTER_CTRL_REG); |
552 | 553 | ||
553 | switch (bpp) { | 554 | switch (bpp) { |
554 | case 1: | 555 | case 1: |
555 | case 2: | 556 | case 2: |
556 | case 4: | 557 | case 4: |
557 | case 16: | 558 | case 16: |
558 | case 24: | 559 | case 24: |
559 | case 32: | 560 | case 32: |
560 | par->palette_sz = 16 * 2; | 561 | par->palette_sz = 16 * 2; |
561 | break; | 562 | break; |
562 | 563 | ||
563 | case 8: | 564 | case 8: |
564 | par->palette_sz = 256 * 2; | 565 | par->palette_sz = 256 * 2; |
565 | break; | 566 | break; |
566 | 567 | ||
567 | default: | 568 | default: |
568 | return -EINVAL; | 569 | return -EINVAL; |
569 | } | 570 | } |
570 | 571 | ||
571 | return 0; | 572 | return 0; |
572 | } | 573 | } |
573 | 574 | ||
574 | static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | 575 | static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, |
575 | unsigned blue, unsigned transp, | 576 | unsigned blue, unsigned transp, |
576 | struct fb_info *info) | 577 | struct fb_info *info) |
577 | { | 578 | { |
578 | struct da8xx_fb_par *par = info->par; | 579 | struct da8xx_fb_par *par = info->par; |
579 | unsigned short *palette = (unsigned short *) par->v_palette_base; | 580 | unsigned short *palette = (unsigned short *) par->v_palette_base; |
580 | u_short pal; | 581 | u_short pal; |
581 | int update_hw = 0; | 582 | int update_hw = 0; |
582 | 583 | ||
583 | if (regno > 255) | 584 | if (regno > 255) |
584 | return 1; | 585 | return 1; |
585 | 586 | ||
586 | if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) | 587 | if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) |
587 | return 1; | 588 | return 1; |
588 | 589 | ||
589 | if (info->var.bits_per_pixel == 8) { | 590 | if (info->var.bits_per_pixel == 8) { |
590 | red >>= 4; | 591 | red >>= 4; |
591 | green >>= 8; | 592 | green >>= 8; |
592 | blue >>= 12; | 593 | blue >>= 12; |
593 | 594 | ||
594 | pal = (red & 0x0f00); | 595 | pal = (red & 0x0f00); |
595 | pal |= (green & 0x00f0); | 596 | pal |= (green & 0x00f0); |
596 | pal |= (blue & 0x000f); | 597 | pal |= (blue & 0x000f); |
597 | 598 | ||
598 | if (palette[regno] != pal) { | 599 | if (palette[regno] != pal) { |
599 | update_hw = 1; | 600 | update_hw = 1; |
600 | palette[regno] = pal; | 601 | palette[regno] = pal; |
601 | } | 602 | } |
602 | } else if ((info->var.bits_per_pixel == 16) && regno < 16) { | 603 | } else if ((info->var.bits_per_pixel == 16) && regno < 16) { |
603 | red >>= (16 - info->var.red.length); | 604 | red >>= (16 - info->var.red.length); |
604 | red <<= info->var.red.offset; | 605 | red <<= info->var.red.offset; |
605 | 606 | ||
606 | green >>= (16 - info->var.green.length); | 607 | green >>= (16 - info->var.green.length); |
607 | green <<= info->var.green.offset; | 608 | green <<= info->var.green.offset; |
608 | 609 | ||
609 | blue >>= (16 - info->var.blue.length); | 610 | blue >>= (16 - info->var.blue.length); |
610 | blue <<= info->var.blue.offset; | 611 | blue <<= info->var.blue.offset; |
611 | 612 | ||
612 | par->pseudo_palette[regno] = red | green | blue; | 613 | par->pseudo_palette[regno] = red | green | blue; |
613 | 614 | ||
614 | if (palette[0] != 0x4000) { | 615 | if (palette[0] != 0x4000) { |
615 | update_hw = 1; | 616 | update_hw = 1; |
616 | palette[0] = 0x4000; | 617 | palette[0] = 0x4000; |
617 | } | 618 | } |
618 | } else if (((info->var.bits_per_pixel == 32) && regno < 32) || | 619 | } else if (((info->var.bits_per_pixel == 32) && regno < 32) || |
619 | ((info->var.bits_per_pixel == 24) && regno < 24)) { | 620 | ((info->var.bits_per_pixel == 24) && regno < 24)) { |
620 | red >>= (24 - info->var.red.length); | 621 | red >>= (24 - info->var.red.length); |
621 | red <<= info->var.red.offset; | 622 | red <<= info->var.red.offset; |
622 | 623 | ||
623 | green >>= (24 - info->var.green.length); | 624 | green >>= (24 - info->var.green.length); |
624 | green <<= info->var.green.offset; | 625 | green <<= info->var.green.offset; |
625 | 626 | ||
626 | blue >>= (24 - info->var.blue.length); | 627 | blue >>= (24 - info->var.blue.length); |
627 | blue <<= info->var.blue.offset; | 628 | blue <<= info->var.blue.offset; |
628 | 629 | ||
629 | par->pseudo_palette[regno] = red | green | blue; | 630 | par->pseudo_palette[regno] = red | green | blue; |
630 | 631 | ||
631 | if (palette[0] != 0x4000) { | 632 | if (palette[0] != 0x4000) { |
632 | update_hw = 1; | 633 | update_hw = 1; |
633 | palette[0] = 0x4000; | 634 | palette[0] = 0x4000; |
634 | } | 635 | } |
635 | } | 636 | } |
636 | 637 | ||
637 | /* Update the palette in the h/w as needed. */ | 638 | /* Update the palette in the h/w as needed. */ |
638 | if (update_hw) | 639 | if (update_hw) |
639 | lcd_blit(LOAD_PALETTE, par); | 640 | lcd_blit(LOAD_PALETTE, par); |
640 | 641 | ||
641 | return 0; | 642 | return 0; |
642 | } | 643 | } |
643 | 644 | ||
644 | static void lcd_reset(struct da8xx_fb_par *par) | 645 | static void lcd_reset(struct da8xx_fb_par *par) |
645 | { | 646 | { |
646 | /* Disable the Raster if previously Enabled */ | 647 | /* Disable the Raster if previously Enabled */ |
647 | lcd_disable_raster(); | 648 | lcd_disable_raster(); |
648 | 649 | ||
649 | /* DMA has to be disabled */ | 650 | /* DMA has to be disabled */ |
650 | lcdc_write(0, LCD_DMA_CTRL_REG); | 651 | lcdc_write(0, LCD_DMA_CTRL_REG); |
651 | lcdc_write(0, LCD_RASTER_CTRL_REG); | 652 | lcdc_write(0, LCD_RASTER_CTRL_REG); |
652 | 653 | ||
653 | if (lcd_revision == LCD_VERSION_2) { | 654 | if (lcd_revision == LCD_VERSION_2) { |
654 | lcdc_write(0, LCD_INT_ENABLE_SET_REG); | 655 | lcdc_write(0, LCD_INT_ENABLE_SET_REG); |
655 | /* Write 1 to reset */ | 656 | /* Write 1 to reset */ |
656 | lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); | 657 | lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); |
657 | lcdc_write(0, LCD_CLK_RESET_REG); | 658 | lcdc_write(0, LCD_CLK_RESET_REG); |
658 | } | 659 | } |
659 | } | 660 | } |
660 | 661 | ||
661 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | 662 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) |
662 | { | 663 | { |
663 | unsigned int lcd_clk, div; | 664 | unsigned int lcd_clk, div; |
664 | 665 | ||
665 | lcd_clk = clk_get_rate(par->lcdc_clk); | 666 | lcd_clk = clk_get_rate(par->lcdc_clk); |
666 | div = lcd_clk / par->pxl_clk; | 667 | div = lcd_clk / par->pxl_clk; |
667 | 668 | ||
668 | /* Configure the LCD clock divisor. */ | 669 | /* Configure the LCD clock divisor. */ |
669 | lcdc_write(LCD_CLK_DIVISOR(div) | | 670 | lcdc_write(LCD_CLK_DIVISOR(div) | |
670 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); | 671 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); |
671 | 672 | ||
672 | if (lcd_revision == LCD_VERSION_2) | 673 | if (lcd_revision == LCD_VERSION_2) |
673 | lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | | 674 | lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | |
674 | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); | 675 | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); |
675 | 676 | ||
676 | } | 677 | } |
677 | 678 | ||
678 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | 679 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, |
679 | struct da8xx_panel *panel) | 680 | struct da8xx_panel *panel) |
680 | { | 681 | { |
681 | u32 bpp; | 682 | u32 bpp; |
682 | int ret = 0; | 683 | int ret = 0; |
683 | 684 | ||
684 | lcd_reset(par); | 685 | lcd_reset(par); |
685 | 686 | ||
686 | /* Calculate the divider */ | 687 | /* Calculate the divider */ |
687 | lcd_calc_clk_divider(par); | 688 | lcd_calc_clk_divider(par); |
688 | 689 | ||
689 | if (panel->invert_pxl_clk) | 690 | if (panel->invert_pxl_clk) |
690 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | | 691 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | |
691 | LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); | 692 | LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); |
692 | else | 693 | else |
693 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & | 694 | lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & |
694 | ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); | 695 | ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); |
695 | 696 | ||
696 | /* Configure the DMA burst size and fifo threshold. */ | 697 | /* Configure the DMA burst size and fifo threshold. */ |
697 | ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th); | 698 | ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th); |
698 | if (ret < 0) | 699 | if (ret < 0) |
699 | return ret; | 700 | return ret; |
700 | 701 | ||
701 | /* Configure the AC bias properties. */ | 702 | /* Configure the AC bias properties. */ |
702 | lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); | 703 | lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); |
703 | 704 | ||
704 | /* Configure the vertical and horizontal sync properties. */ | 705 | /* Configure the vertical and horizontal sync properties. */ |
705 | lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); | 706 | lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); |
706 | lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); | 707 | lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); |
707 | 708 | ||
708 | /* Configure for disply */ | 709 | /* Configure for disply */ |
709 | ret = lcd_cfg_display(cfg); | 710 | ret = lcd_cfg_display(cfg); |
710 | if (ret < 0) | 711 | if (ret < 0) |
711 | return ret; | 712 | return ret; |
712 | 713 | ||
713 | 714 | ||
714 | if ((QVGA != cfg->p_disp_panel->panel_type) && | 715 | if ((QVGA != cfg->p_disp_panel->panel_type) && |
715 | (WVGA != cfg->p_disp_panel->panel_type)) | 716 | (WVGA != cfg->p_disp_panel->panel_type)) |
716 | return -EINVAL; | 717 | return -EINVAL; |
717 | 718 | ||
718 | if (cfg->bpp <= cfg->p_disp_panel->max_bpp && | 719 | if (cfg->bpp <= cfg->p_disp_panel->max_bpp && |
719 | cfg->bpp >= cfg->p_disp_panel->min_bpp) | 720 | cfg->bpp >= cfg->p_disp_panel->min_bpp) |
720 | bpp = cfg->bpp; | 721 | bpp = cfg->bpp; |
721 | else | 722 | else |
722 | bpp = cfg->p_disp_panel->max_bpp; | 723 | bpp = cfg->p_disp_panel->max_bpp; |
723 | if (bpp == 12) | 724 | if (bpp == 12) |
724 | bpp = 16; | 725 | bpp = 16; |
725 | ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, | 726 | ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, |
726 | (unsigned int)panel->height, bpp, | 727 | (unsigned int)panel->height, bpp, |
727 | cfg->raster_order); | 728 | cfg->raster_order); |
728 | if (ret < 0) | 729 | if (ret < 0) |
729 | return ret; | 730 | return ret; |
730 | 731 | ||
731 | /* Configure FDD */ | 732 | /* Configure FDD */ |
732 | lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | | 733 | lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | |
733 | (cfg->fdd << 12), LCD_RASTER_CTRL_REG); | 734 | (cfg->fdd << 12), LCD_RASTER_CTRL_REG); |
734 | 735 | ||
735 | return 0; | 736 | return 0; |
736 | } | 737 | } |
737 | 738 | ||
738 | int register_vsync_cb(vsync_callback_t handler, void *arg, int idx) | 739 | int register_vsync_cb(vsync_callback_t handler, void *arg, int idx) |
739 | { | 740 | { |
740 | if ((vsync_cb_handler == NULL) && (vsync_cb_arg == NULL)) { | 741 | if ((vsync_cb_handler == NULL) && (vsync_cb_arg == NULL)) { |
741 | vsync_cb_handler = handler; | 742 | vsync_cb_handler = handler; |
742 | vsync_cb_arg = arg; | 743 | vsync_cb_arg = arg; |
743 | } else { | 744 | } else { |
744 | return -EEXIST; | 745 | return -EEXIST; |
745 | } | 746 | } |
746 | 747 | ||
747 | return 0; | 748 | return 0; |
748 | } | 749 | } |
749 | EXPORT_SYMBOL(register_vsync_cb); | 750 | EXPORT_SYMBOL(register_vsync_cb); |
750 | 751 | ||
751 | int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx) | 752 | int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx) |
752 | { | 753 | { |
753 | if ((vsync_cb_handler == handler) && (vsync_cb_arg == arg)) { | 754 | if ((vsync_cb_handler == handler) && (vsync_cb_arg == arg)) { |
754 | vsync_cb_handler = NULL; | 755 | vsync_cb_handler = NULL; |
755 | vsync_cb_arg = NULL; | 756 | vsync_cb_arg = NULL; |
756 | } else { | 757 | } else { |
757 | return -ENXIO; | 758 | return -ENXIO; |
758 | } | 759 | } |
759 | 760 | ||
760 | return 0; | 761 | return 0; |
761 | } | 762 | } |
762 | EXPORT_SYMBOL(unregister_vsync_cb); | 763 | EXPORT_SYMBOL(unregister_vsync_cb); |
763 | 764 | ||
764 | /* IRQ handler for version 2 of LCDC */ | 765 | /* IRQ handler for version 2 of LCDC */ |
765 | static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | 766 | static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) |
766 | { | 767 | { |
767 | struct da8xx_fb_par *par = arg; | 768 | struct da8xx_fb_par *par = arg; |
768 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); | 769 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); |
769 | u32 reg_int; | 770 | u32 reg_int; |
770 | 771 | ||
771 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | 772 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { |
772 | printk(KERN_ERR "LCDC sync lost or underflow error occured\n"); | 773 | printk(KERN_ERR "LCDC sync lost or underflow error occured\n"); |
773 | lcd_disable_raster(); | 774 | lcd_disable_raster(); |
774 | clk_disable(par->lcdc_clk); | 775 | clk_disable(par->lcdc_clk); |
775 | lcdc_write(stat, LCD_MASKED_STAT_REG); | 776 | lcdc_write(stat, LCD_MASKED_STAT_REG); |
776 | lcd_enable_raster(); | 777 | lcd_enable_raster(); |
777 | clk_enable(par->lcdc_clk); | 778 | clk_enable(par->lcdc_clk); |
778 | } else if (stat & LCD_PL_LOAD_DONE) { | 779 | } else if (stat & LCD_PL_LOAD_DONE) { |
779 | /* | 780 | /* |
780 | * Must disable raster before changing state of any control bit. | 781 | * Must disable raster before changing state of any control bit. |
781 | * And also must be disabled before clearing the PL loading | 782 | * And also must be disabled before clearing the PL loading |
782 | * interrupt via the following write to the status register. If | 783 | * interrupt via the following write to the status register. If |
783 | * this is done after then one gets multiple PL done interrupts. | 784 | * this is done after then one gets multiple PL done interrupts. |
784 | */ | 785 | */ |
785 | lcd_disable_raster(); | 786 | lcd_disable_raster(); |
786 | 787 | ||
787 | lcdc_write(stat, LCD_MASKED_STAT_REG); | 788 | lcdc_write(stat, LCD_MASKED_STAT_REG); |
788 | 789 | ||
789 | /* Disable PL completion inerrupt */ | 790 | /* Disable PL completion inerrupt */ |
790 | reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | | 791 | reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | |
791 | (LCD_V2_PL_INT_ENA); | 792 | (LCD_V2_PL_INT_ENA); |
792 | lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); | 793 | lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); |
793 | 794 | ||
794 | /* Setup and start data loading mode */ | 795 | /* Setup and start data loading mode */ |
795 | lcd_blit(LOAD_DATA, par); | 796 | lcd_blit(LOAD_DATA, par); |
796 | } else { | 797 | } else { |
797 | lcdc_write(stat, LCD_MASKED_STAT_REG); | 798 | lcdc_write(stat, LCD_MASKED_STAT_REG); |
798 | 799 | ||
799 | if (stat & LCD_END_OF_FRAME0) { | 800 | if (stat & LCD_END_OF_FRAME0) { |
800 | par->which_dma_channel_done = 0; | 801 | par->which_dma_channel_done = 0; |
801 | lcdc_write(par->dma_start, | 802 | lcdc_write(par->dma_start, |
802 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 803 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
803 | lcdc_write(par->dma_end, | 804 | lcdc_write(par->dma_end, |
804 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 805 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
805 | par->vsync_flag = 1; | 806 | par->vsync_flag = 1; |
806 | wake_up_interruptible(&par->vsync_wait); | 807 | wake_up_interruptible(&par->vsync_wait); |
807 | if (vsync_cb_handler) | 808 | if (vsync_cb_handler) |
808 | vsync_cb_handler(vsync_cb_arg); | 809 | vsync_cb_handler(vsync_cb_arg); |
809 | } | 810 | } |
810 | 811 | ||
811 | if (stat & LCD_END_OF_FRAME1) { | 812 | if (stat & LCD_END_OF_FRAME1) { |
812 | par->which_dma_channel_done = 1; | 813 | par->which_dma_channel_done = 1; |
813 | lcdc_write(par->dma_start, | 814 | lcdc_write(par->dma_start, |
814 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | 815 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); |
815 | lcdc_write(par->dma_end, | 816 | lcdc_write(par->dma_end, |
816 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | 817 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); |
817 | par->vsync_flag = 1; | 818 | par->vsync_flag = 1; |
818 | wake_up_interruptible(&par->vsync_wait); | 819 | wake_up_interruptible(&par->vsync_wait); |
819 | if (vsync_cb_handler) | 820 | if (vsync_cb_handler) |
820 | vsync_cb_handler(vsync_cb_arg); | 821 | vsync_cb_handler(vsync_cb_arg); |
821 | } | 822 | } |
822 | } | 823 | } |
823 | 824 | ||
824 | lcdc_write(0, LCD_END_OF_INT_IND_REG); | 825 | lcdc_write(0, LCD_END_OF_INT_IND_REG); |
825 | return IRQ_HANDLED; | 826 | return IRQ_HANDLED; |
826 | } | 827 | } |
827 | 828 | ||
828 | /* IRQ handler for version 1 LCDC */ | 829 | /* IRQ handler for version 1 LCDC */ |
829 | static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) | 830 | static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) |
830 | { | 831 | { |
831 | struct da8xx_fb_par *par = arg; | 832 | struct da8xx_fb_par *par = arg; |
832 | u32 stat = lcdc_read(LCD_STAT_REG); | 833 | u32 stat = lcdc_read(LCD_STAT_REG); |
833 | u32 reg_ras; | 834 | u32 reg_ras; |
834 | 835 | ||
835 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | 836 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { |
836 | printk(KERN_ERR "LCDC sync lost or underflow error occured\n"); | 837 | printk(KERN_ERR "LCDC sync lost or underflow error occured\n"); |
837 | lcd_disable_raster(); | 838 | lcd_disable_raster(); |
838 | clk_disable(par->lcdc_clk); | 839 | clk_disable(par->lcdc_clk); |
839 | lcdc_write(stat, LCD_STAT_REG); | 840 | lcdc_write(stat, LCD_STAT_REG); |
840 | lcd_enable_raster(); | 841 | lcd_enable_raster(); |
841 | clk_enable(par->lcdc_clk); | 842 | clk_enable(par->lcdc_clk); |
842 | } else if (stat & LCD_PL_LOAD_DONE) { | 843 | } else if (stat & LCD_PL_LOAD_DONE) { |
843 | /* | 844 | /* |
844 | * Must disable raster before changing state of any control bit. | 845 | * Must disable raster before changing state of any control bit. |
845 | * And also must be disabled before clearing the PL loading | 846 | * And also must be disabled before clearing the PL loading |
846 | * interrupt via the following write to the status register. If | 847 | * interrupt via the following write to the status register. If |
847 | * this is done after then one gets multiple PL done interrupts. | 848 | * this is done after then one gets multiple PL done interrupts. |
848 | */ | 849 | */ |
849 | lcd_disable_raster(); | 850 | lcd_disable_raster(); |
850 | 851 | ||
851 | lcdc_write(stat, LCD_STAT_REG); | 852 | lcdc_write(stat, LCD_STAT_REG); |
852 | 853 | ||
853 | /* Disable PL completion inerrupt */ | 854 | /* Disable PL completion inerrupt */ |
854 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 855 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
855 | reg_ras &= ~LCD_V1_PL_INT_ENA; | 856 | reg_ras &= ~LCD_V1_PL_INT_ENA; |
856 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); | 857 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); |
857 | 858 | ||
858 | /* Setup and start data loading mode */ | 859 | /* Setup and start data loading mode */ |
859 | lcd_blit(LOAD_DATA, par); | 860 | lcd_blit(LOAD_DATA, par); |
860 | } else { | 861 | } else { |
861 | lcdc_write(stat, LCD_STAT_REG); | 862 | lcdc_write(stat, LCD_STAT_REG); |
862 | 863 | ||
863 | if (stat & LCD_END_OF_FRAME0) { | 864 | if (stat & LCD_END_OF_FRAME0) { |
864 | lcdc_write(par->dma_start, | 865 | lcdc_write(par->dma_start, |
865 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 866 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
866 | lcdc_write(par->dma_end, | 867 | lcdc_write(par->dma_end, |
867 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 868 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
868 | par->vsync_flag = 1; | 869 | par->vsync_flag = 1; |
869 | wake_up_interruptible(&par->vsync_wait); | 870 | wake_up_interruptible(&par->vsync_wait); |
870 | } | 871 | } |
871 | 872 | ||
872 | if (stat & LCD_END_OF_FRAME1) { | 873 | if (stat & LCD_END_OF_FRAME1) { |
873 | lcdc_write(par->dma_start, | 874 | lcdc_write(par->dma_start, |
874 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | 875 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); |
875 | lcdc_write(par->dma_end, | 876 | lcdc_write(par->dma_end, |
876 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | 877 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); |
877 | par->vsync_flag = 1; | 878 | par->vsync_flag = 1; |
878 | wake_up_interruptible(&par->vsync_wait); | 879 | wake_up_interruptible(&par->vsync_wait); |
879 | } | 880 | } |
880 | } | 881 | } |
881 | 882 | ||
882 | return IRQ_HANDLED; | 883 | return IRQ_HANDLED; |
883 | } | 884 | } |
884 | 885 | ||
885 | static int fb_check_var(struct fb_var_screeninfo *var, | 886 | static int fb_check_var(struct fb_var_screeninfo *var, |
886 | struct fb_info *info) | 887 | struct fb_info *info) |
887 | { | 888 | { |
888 | int err = 0; | 889 | int err = 0; |
889 | 890 | ||
890 | switch (var->bits_per_pixel) { | 891 | switch (var->bits_per_pixel) { |
891 | case 1: | 892 | case 1: |
892 | case 8: | 893 | case 8: |
893 | var->red.offset = 0; | 894 | var->red.offset = 0; |
894 | var->red.length = 8; | 895 | var->red.length = 8; |
895 | var->green.offset = 0; | 896 | var->green.offset = 0; |
896 | var->green.length = 8; | 897 | var->green.length = 8; |
897 | var->blue.offset = 0; | 898 | var->blue.offset = 0; |
898 | var->blue.length = 8; | 899 | var->blue.length = 8; |
899 | var->transp.offset = 0; | 900 | var->transp.offset = 0; |
900 | var->transp.length = 0; | 901 | var->transp.length = 0; |
901 | break; | 902 | break; |
902 | case 4: | 903 | case 4: |
903 | var->red.offset = 0; | 904 | var->red.offset = 0; |
904 | var->red.length = 4; | 905 | var->red.length = 4; |
905 | var->green.offset = 0; | 906 | var->green.offset = 0; |
906 | var->green.length = 4; | 907 | var->green.length = 4; |
907 | var->blue.offset = 0; | 908 | var->blue.offset = 0; |
908 | var->blue.length = 4; | 909 | var->blue.length = 4; |
909 | var->transp.offset = 0; | 910 | var->transp.offset = 0; |
910 | var->transp.length = 0; | 911 | var->transp.length = 0; |
911 | break; | 912 | break; |
912 | case 16: /* RGB 565 */ | 913 | case 16: /* RGB 565 */ |
913 | var->red.offset = 11; | 914 | var->red.offset = 11; |
914 | var->red.length = 5; | 915 | var->red.length = 5; |
915 | var->green.offset = 5; | 916 | var->green.offset = 5; |
916 | var->green.length = 6; | 917 | var->green.length = 6; |
917 | var->blue.offset = 0; | 918 | var->blue.offset = 0; |
918 | var->blue.length = 5; | 919 | var->blue.length = 5; |
919 | var->transp.offset = 0; | 920 | var->transp.offset = 0; |
920 | var->transp.length = 0; | 921 | var->transp.length = 0; |
921 | break; | 922 | break; |
922 | case 24: | 923 | case 24: |
923 | var->red.offset = 16; | 924 | var->red.offset = 16; |
924 | var->red.length = 8; | 925 | var->red.length = 8; |
925 | var->green.offset = 8; | 926 | var->green.offset = 8; |
926 | var->green.length = 8; | 927 | var->green.length = 8; |
927 | var->blue.offset = 0; | 928 | var->blue.offset = 0; |
928 | var->blue.length = 8; | 929 | var->blue.length = 8; |
929 | break; | 930 | break; |
930 | case 32: | 931 | case 32: |
931 | var->transp.offset = 24; | 932 | var->transp.offset = 24; |
932 | var->transp.length = 8; | 933 | var->transp.length = 8; |
933 | var->red.offset = 16; | 934 | var->red.offset = 16; |
934 | var->red.length = 8; | 935 | var->red.length = 8; |
935 | var->green.offset = 8; | 936 | var->green.offset = 8; |
936 | var->green.length = 8; | 937 | var->green.length = 8; |
937 | var->blue.offset = 0; | 938 | var->blue.offset = 0; |
938 | var->blue.length = 8; | 939 | var->blue.length = 8; |
939 | break; | 940 | break; |
940 | default: | 941 | default: |
941 | err = -EINVAL; | 942 | err = -EINVAL; |
942 | } | 943 | } |
943 | 944 | ||
944 | var->red.msb_right = 0; | 945 | var->red.msb_right = 0; |
945 | var->green.msb_right = 0; | 946 | var->green.msb_right = 0; |
946 | var->blue.msb_right = 0; | 947 | var->blue.msb_right = 0; |
947 | var->transp.msb_right = 0; | 948 | var->transp.msb_right = 0; |
948 | return err; | 949 | return err; |
949 | } | 950 | } |
950 | 951 | ||
951 | #ifdef CONFIG_CPU_FREQ | 952 | #ifdef CONFIG_CPU_FREQ |
952 | static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, | 953 | static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, |
953 | unsigned long val, void *data) | 954 | unsigned long val, void *data) |
954 | { | 955 | { |
955 | struct da8xx_fb_par *par; | 956 | struct da8xx_fb_par *par; |
956 | 957 | ||
957 | par = container_of(nb, struct da8xx_fb_par, freq_transition); | 958 | par = container_of(nb, struct da8xx_fb_par, freq_transition); |
958 | if (val == CPUFREQ_PRECHANGE) { | 959 | if (val == CPUFREQ_POSTCHANGE) { |
959 | lcd_disable_raster(); | 960 | if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) { |
960 | } else if (val == CPUFREQ_POSTCHANGE) { | 961 | lcd_disable_raster(); |
961 | lcd_calc_clk_divider(par); | 962 | lcd_calc_clk_divider(par); |
962 | lcd_enable_raster(); | 963 | lcd_enable_raster(); |
964 | } | ||
963 | } | 965 | } |
964 | 966 | ||
965 | return 0; | 967 | return 0; |
966 | } | 968 | } |
967 | 969 | ||
968 | static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) | 970 | static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) |
969 | { | 971 | { |
970 | par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition; | 972 | par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition; |
971 | 973 | ||
972 | return cpufreq_register_notifier(&par->freq_transition, | 974 | return cpufreq_register_notifier(&par->freq_transition, |
973 | CPUFREQ_TRANSITION_NOTIFIER); | 975 | CPUFREQ_TRANSITION_NOTIFIER); |
974 | } | 976 | } |
975 | 977 | ||
976 | static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) | 978 | static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) |
977 | { | 979 | { |
978 | cpufreq_unregister_notifier(&par->freq_transition, | 980 | cpufreq_unregister_notifier(&par->freq_transition, |
979 | CPUFREQ_TRANSITION_NOTIFIER); | 981 | CPUFREQ_TRANSITION_NOTIFIER); |
980 | } | 982 | } |
981 | #endif | 983 | #endif |
982 | 984 | ||
983 | static int __devexit fb_remove(struct platform_device *dev) | 985 | static int __devexit fb_remove(struct platform_device *dev) |
984 | { | 986 | { |
985 | struct fb_info *info = dev_get_drvdata(&dev->dev); | 987 | struct fb_info *info = dev_get_drvdata(&dev->dev); |
986 | 988 | ||
987 | if (info) { | 989 | if (info) { |
988 | struct da8xx_fb_par *par = info->par; | 990 | struct da8xx_fb_par *par = info->par; |
989 | 991 | ||
990 | #ifdef CONFIG_CPU_FREQ | 992 | #ifdef CONFIG_CPU_FREQ |
991 | lcd_da8xx_cpufreq_deregister(par); | 993 | lcd_da8xx_cpufreq_deregister(par); |
992 | #endif | 994 | #endif |
993 | if (par->panel_power_ctrl) | 995 | if (par->panel_power_ctrl) |
994 | par->panel_power_ctrl(0); | 996 | par->panel_power_ctrl(0); |
995 | 997 | ||
996 | lcd_disable_raster(); | 998 | lcd_disable_raster(); |
997 | lcdc_write(0, LCD_RASTER_CTRL_REG); | 999 | lcdc_write(0, LCD_RASTER_CTRL_REG); |
998 | 1000 | ||
999 | /* disable DMA */ | 1001 | /* disable DMA */ |
1000 | lcdc_write(0, LCD_DMA_CTRL_REG); | 1002 | lcdc_write(0, LCD_DMA_CTRL_REG); |
1001 | 1003 | ||
1002 | unregister_framebuffer(info); | 1004 | unregister_framebuffer(info); |
1003 | fb_dealloc_cmap(&info->cmap); | 1005 | fb_dealloc_cmap(&info->cmap); |
1004 | dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, | 1006 | dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, |
1005 | par->p_palette_base); | 1007 | par->p_palette_base); |
1006 | dma_free_coherent(NULL, par->vram_size, par->vram_virt, | 1008 | dma_free_coherent(NULL, par->vram_size, par->vram_virt, |
1007 | par->vram_phys); | 1009 | par->vram_phys); |
1008 | free_irq(par->irq, par); | 1010 | free_irq(par->irq, par); |
1009 | clk_disable(par->lcdc_clk); | 1011 | clk_disable(par->lcdc_clk); |
1010 | clk_put(par->lcdc_clk); | 1012 | clk_put(par->lcdc_clk); |
1011 | framebuffer_release(info); | 1013 | framebuffer_release(info); |
1012 | iounmap((void __iomem *)da8xx_fb_reg_base); | 1014 | iounmap((void __iomem *)da8xx_fb_reg_base); |
1013 | release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); | 1015 | release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); |
1014 | 1016 | ||
1015 | } | 1017 | } |
1016 | return 0; | 1018 | return 0; |
1017 | } | 1019 | } |
1018 | 1020 | ||
1019 | /* | 1021 | /* |
1020 | * Function to wait for vertical sync which for this LCD peripheral | 1022 | * Function to wait for vertical sync which for this LCD peripheral |
1021 | * translates into waiting for the current raster frame to complete. | 1023 | * translates into waiting for the current raster frame to complete. |
1022 | */ | 1024 | */ |
1023 | static int fb_wait_for_vsync(struct fb_info *info) | 1025 | static int fb_wait_for_vsync(struct fb_info *info) |
1024 | { | 1026 | { |
1025 | struct da8xx_fb_par *par = info->par; | 1027 | struct da8xx_fb_par *par = info->par; |
1026 | int ret; | 1028 | int ret; |
1027 | 1029 | ||
1028 | /* | 1030 | /* |
1029 | * Set flag to 0 and wait for isr to set to 1. It would seem there is a | 1031 | * Set flag to 0 and wait for isr to set to 1. It would seem there is a |
1030 | * race condition here where the ISR could have occurred just before or | 1032 | * race condition here where the ISR could have occurred just before or |
1031 | * just after this set. But since we are just coarsely waiting for | 1033 | * just after this set. But since we are just coarsely waiting for |
1032 | * a frame to complete then that's OK. i.e. if the frame completed | 1034 | * a frame to complete then that's OK. i.e. if the frame completed |
1033 | * just before this code executed then we have to wait another full | 1035 | * just before this code executed then we have to wait another full |
1034 | * frame time but there is no way to avoid such a situation. On the | 1036 | * frame time but there is no way to avoid such a situation. On the |
1035 | * other hand if the frame completed just after then we don't need | 1037 | * other hand if the frame completed just after then we don't need |
1036 | * to wait long at all. Either way we are guaranteed to return to the | 1038 | * to wait long at all. Either way we are guaranteed to return to the |
1037 | * user immediately after a frame completion which is all that is | 1039 | * user immediately after a frame completion which is all that is |
1038 | * required. | 1040 | * required. |
1039 | */ | 1041 | */ |
1040 | par->vsync_flag = 0; | 1042 | par->vsync_flag = 0; |
1041 | ret = wait_event_interruptible_timeout(par->vsync_wait, | 1043 | ret = wait_event_interruptible_timeout(par->vsync_wait, |
1042 | par->vsync_flag != 0, | 1044 | par->vsync_flag != 0, |
1043 | par->vsync_timeout); | 1045 | par->vsync_timeout); |
1044 | if (ret < 0) | 1046 | if (ret < 0) |
1045 | return ret; | 1047 | return ret; |
1046 | if (ret == 0) | 1048 | if (ret == 0) |
1047 | return -ETIMEDOUT; | 1049 | return -ETIMEDOUT; |
1048 | 1050 | ||
1049 | if (par->panel_power_ctrl) { | 1051 | if (par->panel_power_ctrl) { |
1050 | /* Switch off panel power and backlight */ | 1052 | /* Switch off panel power and backlight */ |
1051 | par->panel_power_ctrl(0); | 1053 | par->panel_power_ctrl(0); |
1052 | 1054 | ||
1053 | /* Switch on panel power and backlight */ | 1055 | /* Switch on panel power and backlight */ |
1054 | par->panel_power_ctrl(1); | 1056 | par->panel_power_ctrl(1); |
1055 | } | 1057 | } |
1056 | 1058 | ||
1057 | return 0; | 1059 | return 0; |
1058 | } | 1060 | } |
1059 | 1061 | ||
1060 | static int fb_ioctl(struct fb_info *info, unsigned int cmd, | 1062 | static int fb_ioctl(struct fb_info *info, unsigned int cmd, |
1061 | unsigned long arg) | 1063 | unsigned long arg) |
1062 | { | 1064 | { |
1063 | struct lcd_sync_arg sync_arg; | 1065 | struct lcd_sync_arg sync_arg; |
1064 | 1066 | ||
1065 | switch (cmd) { | 1067 | switch (cmd) { |
1066 | case FBIOGET_CONTRAST: | 1068 | case FBIOGET_CONTRAST: |
1067 | case FBIOPUT_CONTRAST: | 1069 | case FBIOPUT_CONTRAST: |
1068 | case FBIGET_BRIGHTNESS: | 1070 | case FBIGET_BRIGHTNESS: |
1069 | case FBIPUT_BRIGHTNESS: | 1071 | case FBIPUT_BRIGHTNESS: |
1070 | case FBIGET_COLOR: | 1072 | case FBIGET_COLOR: |
1071 | case FBIPUT_COLOR: | 1073 | case FBIPUT_COLOR: |
1072 | return -ENOTTY; | 1074 | return -ENOTTY; |
1073 | case FBIPUT_HSYNC: | 1075 | case FBIPUT_HSYNC: |
1074 | if (copy_from_user(&sync_arg, (char *)arg, | 1076 | if (copy_from_user(&sync_arg, (char *)arg, |
1075 | sizeof(struct lcd_sync_arg))) | 1077 | sizeof(struct lcd_sync_arg))) |
1076 | return -EFAULT; | 1078 | return -EFAULT; |
1077 | lcd_cfg_horizontal_sync(sync_arg.back_porch, | 1079 | lcd_cfg_horizontal_sync(sync_arg.back_porch, |
1078 | sync_arg.pulse_width, | 1080 | sync_arg.pulse_width, |
1079 | sync_arg.front_porch); | 1081 | sync_arg.front_porch); |
1080 | break; | 1082 | break; |
1081 | case FBIPUT_VSYNC: | 1083 | case FBIPUT_VSYNC: |
1082 | if (copy_from_user(&sync_arg, (char *)arg, | 1084 | if (copy_from_user(&sync_arg, (char *)arg, |
1083 | sizeof(struct lcd_sync_arg))) | 1085 | sizeof(struct lcd_sync_arg))) |
1084 | return -EFAULT; | 1086 | return -EFAULT; |
1085 | lcd_cfg_vertical_sync(sync_arg.back_porch, | 1087 | lcd_cfg_vertical_sync(sync_arg.back_porch, |
1086 | sync_arg.pulse_width, | 1088 | sync_arg.pulse_width, |
1087 | sync_arg.front_porch); | 1089 | sync_arg.front_porch); |
1088 | break; | 1090 | break; |
1089 | case FBIO_WAITFORVSYNC: | 1091 | case FBIO_WAITFORVSYNC: |
1090 | return fb_wait_for_vsync(info); | 1092 | return fb_wait_for_vsync(info); |
1091 | default: | 1093 | default: |
1092 | return -EINVAL; | 1094 | return -EINVAL; |
1093 | } | 1095 | } |
1094 | return 0; | 1096 | return 0; |
1095 | } | 1097 | } |
1096 | 1098 | ||
1097 | static int cfb_blank(int blank, struct fb_info *info) | 1099 | static int cfb_blank(int blank, struct fb_info *info) |
1098 | { | 1100 | { |
1099 | struct da8xx_fb_par *par = info->par; | 1101 | struct da8xx_fb_par *par = info->par; |
1100 | int ret = 0; | 1102 | int ret = 0; |
1101 | 1103 | ||
1102 | if (par->blank == blank) | 1104 | if (par->blank == blank) |
1103 | return 0; | 1105 | return 0; |
1104 | 1106 | ||
1105 | par->blank = blank; | 1107 | par->blank = blank; |
1106 | switch (blank) { | 1108 | switch (blank) { |
1107 | case FB_BLANK_UNBLANK: | 1109 | case FB_BLANK_UNBLANK: |
1108 | if (par->panel_power_ctrl) | 1110 | if (par->panel_power_ctrl) |
1109 | par->panel_power_ctrl(1); | 1111 | par->panel_power_ctrl(1); |
1110 | 1112 | ||
1111 | lcd_enable_raster(); | 1113 | lcd_enable_raster(); |
1112 | break; | 1114 | break; |
1113 | case FB_BLANK_POWERDOWN: | 1115 | case FB_BLANK_POWERDOWN: |
1114 | if (par->panel_power_ctrl) | 1116 | if (par->panel_power_ctrl) |
1115 | par->panel_power_ctrl(0); | 1117 | par->panel_power_ctrl(0); |
1116 | 1118 | ||
1117 | lcd_disable_raster(); | 1119 | lcd_disable_raster(); |
1118 | break; | 1120 | break; |
1119 | default: | 1121 | default: |
1120 | ret = -EINVAL; | 1122 | ret = -EINVAL; |
1121 | } | 1123 | } |
1122 | 1124 | ||
1123 | return ret; | 1125 | return ret; |
1124 | } | 1126 | } |
1125 | 1127 | ||
1126 | /* | 1128 | /* |
1127 | * Set new x,y offsets in the virtual display for the visible area and switch | 1129 | * Set new x,y offsets in the virtual display for the visible area and switch |
1128 | * to the new mode. | 1130 | * to the new mode. |
1129 | */ | 1131 | */ |
1130 | static int da8xx_pan_display(struct fb_var_screeninfo *var, | 1132 | static int da8xx_pan_display(struct fb_var_screeninfo *var, |
1131 | struct fb_info *fbi) | 1133 | struct fb_info *fbi) |
1132 | { | 1134 | { |
1133 | int ret = 0; | 1135 | int ret = 0; |
1134 | struct fb_var_screeninfo new_var; | 1136 | struct fb_var_screeninfo new_var; |
1135 | struct da8xx_fb_par *par = fbi->par; | 1137 | struct da8xx_fb_par *par = fbi->par; |
1136 | struct fb_fix_screeninfo *fix = &fbi->fix; | 1138 | struct fb_fix_screeninfo *fix = &fbi->fix; |
1137 | unsigned int end; | 1139 | unsigned int end; |
1138 | unsigned int start; | 1140 | unsigned int start; |
1139 | unsigned long irq_flags; | 1141 | unsigned long irq_flags; |
1140 | 1142 | ||
1141 | if (var->xoffset != fbi->var.xoffset || | 1143 | if (var->xoffset != fbi->var.xoffset || |
1142 | var->yoffset != fbi->var.yoffset) { | 1144 | var->yoffset != fbi->var.yoffset) { |
1143 | memcpy(&new_var, &fbi->var, sizeof(new_var)); | 1145 | memcpy(&new_var, &fbi->var, sizeof(new_var)); |
1144 | new_var.xoffset = var->xoffset; | 1146 | new_var.xoffset = var->xoffset; |
1145 | new_var.yoffset = var->yoffset; | 1147 | new_var.yoffset = var->yoffset; |
1146 | if (fb_check_var(&new_var, fbi)) | 1148 | if (fb_check_var(&new_var, fbi)) |
1147 | ret = -EINVAL; | 1149 | ret = -EINVAL; |
1148 | else { | 1150 | else { |
1149 | memcpy(&fbi->var, &new_var, sizeof(new_var)); | 1151 | memcpy(&fbi->var, &new_var, sizeof(new_var)); |
1150 | 1152 | ||
1151 | start = fix->smem_start + | 1153 | start = fix->smem_start + |
1152 | new_var.yoffset * fix->line_length + | 1154 | new_var.yoffset * fix->line_length + |
1153 | new_var.xoffset * var->bits_per_pixel / 8; | 1155 | new_var.xoffset * var->bits_per_pixel / 8; |
1154 | end = start + var->yres * fix->line_length - 1; | 1156 | end = start + var->yres * fix->line_length - 1; |
1155 | par->dma_start = start; | 1157 | par->dma_start = start; |
1156 | par->dma_end = end; | 1158 | par->dma_end = end; |
1157 | spin_lock_irqsave(&par->lock_for_chan_update, | 1159 | spin_lock_irqsave(&par->lock_for_chan_update, |
1158 | irq_flags); | 1160 | irq_flags); |
1159 | if (par->which_dma_channel_done == 0) { | 1161 | if (par->which_dma_channel_done == 0) { |
1160 | lcdc_write(par->dma_start, | 1162 | lcdc_write(par->dma_start, |
1161 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 1163 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
1162 | lcdc_write(par->dma_end, | 1164 | lcdc_write(par->dma_end, |
1163 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 1165 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
1164 | } else if (par->which_dma_channel_done == 1) { | 1166 | } else if (par->which_dma_channel_done == 1) { |
1165 | lcdc_write(par->dma_start, | 1167 | lcdc_write(par->dma_start, |
1166 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | 1168 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); |
1167 | lcdc_write(par->dma_end, | 1169 | lcdc_write(par->dma_end, |
1168 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | 1170 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); |
1169 | } | 1171 | } |
1170 | spin_unlock_irqrestore(&par->lock_for_chan_update, | 1172 | spin_unlock_irqrestore(&par->lock_for_chan_update, |
1171 | irq_flags); | 1173 | irq_flags); |
1172 | } | 1174 | } |
1173 | } | 1175 | } |
1174 | 1176 | ||
1175 | return ret; | 1177 | return ret; |
1176 | } | 1178 | } |
1177 | 1179 | ||
1178 | static struct fb_ops da8xx_fb_ops = { | 1180 | static struct fb_ops da8xx_fb_ops = { |
1179 | .owner = THIS_MODULE, | 1181 | .owner = THIS_MODULE, |
1180 | .fb_check_var = fb_check_var, | 1182 | .fb_check_var = fb_check_var, |
1181 | .fb_setcolreg = fb_setcolreg, | 1183 | .fb_setcolreg = fb_setcolreg, |
1182 | .fb_pan_display = da8xx_pan_display, | 1184 | .fb_pan_display = da8xx_pan_display, |
1183 | .fb_ioctl = fb_ioctl, | 1185 | .fb_ioctl = fb_ioctl, |
1184 | .fb_fillrect = cfb_fillrect, | 1186 | .fb_fillrect = cfb_fillrect, |
1185 | .fb_copyarea = cfb_copyarea, | 1187 | .fb_copyarea = cfb_copyarea, |
1186 | .fb_imageblit = cfb_imageblit, | 1188 | .fb_imageblit = cfb_imageblit, |
1187 | .fb_blank = cfb_blank, | 1189 | .fb_blank = cfb_blank, |
1188 | }; | 1190 | }; |
1189 | 1191 | ||
1190 | static int __devinit fb_probe(struct platform_device *device) | 1192 | static int __devinit fb_probe(struct platform_device *device) |
1191 | { | 1193 | { |
1192 | struct da8xx_lcdc_platform_data *fb_pdata = | 1194 | struct da8xx_lcdc_platform_data *fb_pdata = |
1193 | device->dev.platform_data; | 1195 | device->dev.platform_data; |
1194 | struct lcd_ctrl_config *lcd_cfg; | 1196 | struct lcd_ctrl_config *lcd_cfg; |
1195 | struct da8xx_panel *lcdc_info; | 1197 | struct da8xx_panel *lcdc_info; |
1196 | struct fb_info *da8xx_fb_info; | 1198 | struct fb_info *da8xx_fb_info; |
1197 | struct clk *fb_clk = NULL; | 1199 | struct clk *fb_clk = NULL; |
1198 | struct clk *fb_l3ick = NULL, *fb_l4ick = NULL; | 1200 | struct clk *fb_l3ick = NULL, *fb_l4ick = NULL; |
1199 | struct da8xx_fb_par *par; | 1201 | struct da8xx_fb_par *par; |
1200 | resource_size_t len; | 1202 | resource_size_t len; |
1201 | int ret, i; | 1203 | int ret, i; |
1202 | 1204 | ||
1203 | if (fb_pdata == NULL) { | 1205 | if (fb_pdata == NULL) { |
1204 | dev_err(&device->dev, "Can not get platform data\n"); | 1206 | dev_err(&device->dev, "Can not get platform data\n"); |
1205 | return -ENOENT; | 1207 | return -ENOENT; |
1206 | } | 1208 | } |
1207 | 1209 | ||
1208 | lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); | 1210 | lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); |
1209 | if (!lcdc_regs) { | 1211 | if (!lcdc_regs) { |
1210 | dev_err(&device->dev, | 1212 | dev_err(&device->dev, |
1211 | "Can not get memory resource for LCD controller\n"); | 1213 | "Can not get memory resource for LCD controller\n"); |
1212 | return -ENOENT; | 1214 | return -ENOENT; |
1213 | } | 1215 | } |
1214 | 1216 | ||
1215 | len = resource_size(lcdc_regs); | 1217 | len = resource_size(lcdc_regs); |
1216 | 1218 | ||
1217 | lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name); | 1219 | lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name); |
1218 | if (!lcdc_regs) | 1220 | if (!lcdc_regs) |
1219 | return -EBUSY; | 1221 | return -EBUSY; |
1220 | 1222 | ||
1221 | da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len); | 1223 | da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len); |
1222 | if (!da8xx_fb_reg_base) { | 1224 | if (!da8xx_fb_reg_base) { |
1223 | ret = -EBUSY; | 1225 | ret = -EBUSY; |
1224 | goto err_request_mem; | 1226 | goto err_request_mem; |
1225 | } | 1227 | } |
1226 | 1228 | ||
1227 | if (machine_is_am335xevm()) { | 1229 | if (machine_is_am335xevm()) { |
1228 | fb_l3ick = clk_get(&device->dev, "lcdc_ick_l3_clk"); | 1230 | fb_l3ick = clk_get(&device->dev, "lcdc_ick_l3_clk"); |
1229 | if (IS_ERR(fb_l3ick)) { | 1231 | if (IS_ERR(fb_l3ick)) { |
1230 | dev_err(&device->dev, "Can not get l3 interface" | 1232 | dev_err(&device->dev, "Can not get l3 interface" |
1231 | "clock\n"); | 1233 | "clock\n"); |
1232 | ret = -ENODEV; | 1234 | ret = -ENODEV; |
1233 | goto err_ioremap; | 1235 | goto err_ioremap; |
1234 | } | 1236 | } |
1235 | ret = clk_enable(fb_l3ick); | 1237 | ret = clk_enable(fb_l3ick); |
1236 | if (ret) | 1238 | if (ret) |
1237 | goto err_clk_put0; | 1239 | goto err_clk_put0; |
1238 | 1240 | ||
1239 | fb_l4ick = clk_get(&device->dev, "lcdc_ick_l4_clk"); | 1241 | fb_l4ick = clk_get(&device->dev, "lcdc_ick_l4_clk"); |
1240 | if (IS_ERR(fb_l4ick)) { | 1242 | if (IS_ERR(fb_l4ick)) { |
1241 | dev_err(&device->dev, "Can not get l4 interface" | 1243 | dev_err(&device->dev, "Can not get l4 interface" |
1242 | "clock\n"); | 1244 | "clock\n"); |
1243 | ret = -ENODEV; | 1245 | ret = -ENODEV; |
1244 | goto err_clk_get0; | 1246 | goto err_clk_get0; |
1245 | } | 1247 | } |
1246 | ret = clk_enable(fb_l4ick); | 1248 | ret = clk_enable(fb_l4ick); |
1247 | if (ret) | 1249 | if (ret) |
1248 | goto err_clk_put1; | 1250 | goto err_clk_put1; |
1249 | } | 1251 | } |
1250 | 1252 | ||
1251 | fb_clk = clk_get(&device->dev, NULL); | 1253 | fb_clk = clk_get(&device->dev, NULL); |
1252 | if (IS_ERR(fb_clk)) { | 1254 | if (IS_ERR(fb_clk)) { |
1253 | dev_err(&device->dev, "Can not get device clock\n"); | 1255 | dev_err(&device->dev, "Can not get device clock\n"); |
1254 | ret = -ENODEV; | 1256 | ret = -ENODEV; |
1255 | goto err_clk_get1; | 1257 | goto err_clk_get1; |
1256 | } | 1258 | } |
1257 | ret = clk_enable(fb_clk); | 1259 | ret = clk_enable(fb_clk); |
1258 | if (ret) | 1260 | if (ret) |
1259 | goto err_clk_put2; | 1261 | goto err_clk_put2; |
1260 | 1262 | ||
1261 | /* Determine LCD IP Version */ | 1263 | /* Determine LCD IP Version */ |
1262 | switch (lcdc_read(LCD_PID_REG)) { | 1264 | switch (lcdc_read(LCD_PID_REG)) { |
1263 | case 0x4C100102: | 1265 | case 0x4C100102: |
1264 | lcd_revision = LCD_VERSION_1; | 1266 | lcd_revision = LCD_VERSION_1; |
1265 | break; | 1267 | break; |
1266 | case 0x4F200800: | 1268 | case 0x4F200800: |
1267 | case 0x4F201000: | 1269 | case 0x4F201000: |
1268 | lcd_revision = LCD_VERSION_2; | 1270 | lcd_revision = LCD_VERSION_2; |
1269 | break; | 1271 | break; |
1270 | default: | 1272 | default: |
1271 | dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " | 1273 | dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " |
1272 | "defaulting to LCD revision 1\n", | 1274 | "defaulting to LCD revision 1\n", |
1273 | lcdc_read(LCD_PID_REG)); | 1275 | lcdc_read(LCD_PID_REG)); |
1274 | lcd_revision = LCD_VERSION_1; | 1276 | lcd_revision = LCD_VERSION_1; |
1275 | break; | 1277 | break; |
1276 | } | 1278 | } |
1277 | 1279 | ||
1278 | for (i = 0, lcdc_info = known_lcd_panels; | 1280 | for (i = 0, lcdc_info = known_lcd_panels; |
1279 | i < ARRAY_SIZE(known_lcd_panels); | 1281 | i < ARRAY_SIZE(known_lcd_panels); |
1280 | i++, lcdc_info++) { | 1282 | i++, lcdc_info++) { |
1281 | if (strcmp(fb_pdata->type, lcdc_info->name) == 0) | 1283 | if (strcmp(fb_pdata->type, lcdc_info->name) == 0) |
1282 | break; | 1284 | break; |
1283 | } | 1285 | } |
1284 | 1286 | ||
1285 | if (i == ARRAY_SIZE(known_lcd_panels)) { | 1287 | if (i == ARRAY_SIZE(known_lcd_panels)) { |
1286 | dev_err(&device->dev, "GLCD: No valid panel found\n"); | 1288 | dev_err(&device->dev, "GLCD: No valid panel found\n"); |
1287 | ret = -ENODEV; | 1289 | ret = -ENODEV; |
1288 | goto err_clk_disable; | 1290 | goto err_clk_disable; |
1289 | } else | 1291 | } else |
1290 | dev_info(&device->dev, "GLCD: Found %s panel\n", | 1292 | dev_info(&device->dev, "GLCD: Found %s panel\n", |
1291 | fb_pdata->type); | 1293 | fb_pdata->type); |
1292 | 1294 | ||
1293 | lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; | 1295 | lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; |
1294 | 1296 | ||
1295 | da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), | 1297 | da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), |
1296 | &device->dev); | 1298 | &device->dev); |
1297 | if (!da8xx_fb_info) { | 1299 | if (!da8xx_fb_info) { |
1298 | dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); | 1300 | dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); |
1299 | ret = -ENOMEM; | 1301 | ret = -ENOMEM; |
1300 | goto err_clk_disable; | 1302 | goto err_clk_disable; |
1301 | } | 1303 | } |
1302 | 1304 | ||
1303 | par = da8xx_fb_info->par; | 1305 | par = da8xx_fb_info->par; |
1304 | par->lcdc_clk = fb_clk; | 1306 | par->lcdc_clk = fb_clk; |
1307 | #ifdef CONFIG_CPU_FREQ | ||
1308 | par->lcd_fck_rate = clk_get_rate(fb_clk); | ||
1309 | #endif | ||
1305 | par->pxl_clk = lcdc_info->pxl_clk; | 1310 | par->pxl_clk = lcdc_info->pxl_clk; |
1306 | if (fb_pdata->panel_power_ctrl) { | 1311 | if (fb_pdata->panel_power_ctrl) { |
1307 | par->panel_power_ctrl = fb_pdata->panel_power_ctrl; | 1312 | par->panel_power_ctrl = fb_pdata->panel_power_ctrl; |
1308 | par->panel_power_ctrl(1); | 1313 | par->panel_power_ctrl(1); |
1309 | } | 1314 | } |
1310 | 1315 | ||
1311 | if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { | 1316 | if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { |
1312 | dev_err(&device->dev, "lcd_init failed\n"); | 1317 | dev_err(&device->dev, "lcd_init failed\n"); |
1313 | ret = -EFAULT; | 1318 | ret = -EFAULT; |
1314 | goto err_release_fb; | 1319 | goto err_release_fb; |
1315 | } | 1320 | } |
1316 | 1321 | ||
1317 | /* allocate frame buffer */ | 1322 | /* allocate frame buffer */ |
1318 | par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; | 1323 | par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; |
1319 | par->vram_size = PAGE_ALIGN(par->vram_size/8); | 1324 | par->vram_size = PAGE_ALIGN(par->vram_size/8); |
1320 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; | 1325 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; |
1321 | 1326 | ||
1322 | par->vram_virt = dma_alloc_coherent(NULL, | 1327 | par->vram_virt = dma_alloc_coherent(NULL, |
1323 | par->vram_size, | 1328 | par->vram_size, |
1324 | (resource_size_t *) &par->vram_phys, | 1329 | (resource_size_t *) &par->vram_phys, |
1325 | GFP_KERNEL | GFP_DMA); | 1330 | GFP_KERNEL | GFP_DMA); |
1326 | if (!par->vram_virt) { | 1331 | if (!par->vram_virt) { |
1327 | dev_err(&device->dev, | 1332 | dev_err(&device->dev, |
1328 | "GLCD: kmalloc for frame buffer failed\n"); | 1333 | "GLCD: kmalloc for frame buffer failed\n"); |
1329 | ret = -EINVAL; | 1334 | ret = -EINVAL; |
1330 | goto err_release_fb; | 1335 | goto err_release_fb; |
1331 | } | 1336 | } |
1332 | 1337 | ||
1333 | da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; | 1338 | da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; |
1334 | da8xx_fb_fix.smem_start = par->vram_phys; | 1339 | da8xx_fb_fix.smem_start = par->vram_phys; |
1335 | da8xx_fb_fix.smem_len = par->vram_size; | 1340 | da8xx_fb_fix.smem_len = par->vram_size; |
1336 | da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; | 1341 | da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; |
1337 | 1342 | ||
1338 | par->dma_start = par->vram_phys; | 1343 | par->dma_start = par->vram_phys; |
1339 | par->dma_end = par->dma_start + lcdc_info->height * | 1344 | par->dma_end = par->dma_start + lcdc_info->height * |
1340 | da8xx_fb_fix.line_length - 1; | 1345 | da8xx_fb_fix.line_length - 1; |
1341 | 1346 | ||
1342 | /* allocate palette buffer */ | 1347 | /* allocate palette buffer */ |
1343 | par->v_palette_base = dma_alloc_coherent(NULL, | 1348 | par->v_palette_base = dma_alloc_coherent(NULL, |
1344 | PALETTE_SIZE, | 1349 | PALETTE_SIZE, |
1345 | (resource_size_t *) | 1350 | (resource_size_t *) |
1346 | &par->p_palette_base, | 1351 | &par->p_palette_base, |
1347 | GFP_KERNEL | GFP_DMA); | 1352 | GFP_KERNEL | GFP_DMA); |
1348 | if (!par->v_palette_base) { | 1353 | if (!par->v_palette_base) { |
1349 | dev_err(&device->dev, | 1354 | dev_err(&device->dev, |
1350 | "GLCD: kmalloc for palette buffer failed\n"); | 1355 | "GLCD: kmalloc for palette buffer failed\n"); |
1351 | ret = -EINVAL; | 1356 | ret = -EINVAL; |
1352 | goto err_release_fb_mem; | 1357 | goto err_release_fb_mem; |
1353 | } | 1358 | } |
1354 | memset(par->v_palette_base, 0, PALETTE_SIZE); | 1359 | memset(par->v_palette_base, 0, PALETTE_SIZE); |
1355 | 1360 | ||
1356 | par->irq = platform_get_irq(device, 0); | 1361 | par->irq = platform_get_irq(device, 0); |
1357 | if (par->irq < 0) { | 1362 | if (par->irq < 0) { |
1358 | ret = -ENOENT; | 1363 | ret = -ENOENT; |
1359 | goto err_release_pl_mem; | 1364 | goto err_release_pl_mem; |
1360 | } | 1365 | } |
1361 | 1366 | ||
1362 | /* Initialize par */ | 1367 | /* Initialize par */ |
1363 | da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; | 1368 | da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; |
1364 | 1369 | ||
1365 | da8xx_fb_var.xres = lcdc_info->width; | 1370 | da8xx_fb_var.xres = lcdc_info->width; |
1366 | da8xx_fb_var.xres_virtual = lcdc_info->width; | 1371 | da8xx_fb_var.xres_virtual = lcdc_info->width; |
1367 | 1372 | ||
1368 | da8xx_fb_var.yres = lcdc_info->height; | 1373 | da8xx_fb_var.yres = lcdc_info->height; |
1369 | da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS; | 1374 | da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS; |
1370 | 1375 | ||
1371 | da8xx_fb_var.grayscale = | 1376 | da8xx_fb_var.grayscale = |
1372 | lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; | 1377 | lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; |
1373 | da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; | 1378 | da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; |
1374 | 1379 | ||
1375 | da8xx_fb_var.hsync_len = lcdc_info->hsw; | 1380 | da8xx_fb_var.hsync_len = lcdc_info->hsw; |
1376 | da8xx_fb_var.vsync_len = lcdc_info->vsw; | 1381 | da8xx_fb_var.vsync_len = lcdc_info->vsw; |
1377 | 1382 | ||
1378 | da8xx_fb_var.right_margin = lcdc_info->hfp; | 1383 | da8xx_fb_var.right_margin = lcdc_info->hfp; |
1379 | da8xx_fb_var.left_margin = lcdc_info->hbp; | 1384 | da8xx_fb_var.left_margin = lcdc_info->hbp; |
1380 | da8xx_fb_var.lower_margin = lcdc_info->vfp; | 1385 | da8xx_fb_var.lower_margin = lcdc_info->vfp; |
1381 | da8xx_fb_var.upper_margin = lcdc_info->vbp; | 1386 | da8xx_fb_var.upper_margin = lcdc_info->vbp; |
1382 | 1387 | ||
1383 | /* Initialize fbinfo */ | 1388 | /* Initialize fbinfo */ |
1384 | da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; | 1389 | da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; |
1385 | da8xx_fb_info->fix = da8xx_fb_fix; | 1390 | da8xx_fb_info->fix = da8xx_fb_fix; |
1386 | da8xx_fb_info->var = da8xx_fb_var; | 1391 | da8xx_fb_info->var = da8xx_fb_var; |
1387 | da8xx_fb_info->fbops = &da8xx_fb_ops; | 1392 | da8xx_fb_info->fbops = &da8xx_fb_ops; |
1388 | da8xx_fb_info->pseudo_palette = par->pseudo_palette; | 1393 | da8xx_fb_info->pseudo_palette = par->pseudo_palette; |
1389 | da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? | 1394 | da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? |
1390 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 1395 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
1391 | 1396 | ||
1392 | ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); | 1397 | ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); |
1393 | if (ret) | 1398 | if (ret) |
1394 | goto err_release_pl_mem; | 1399 | goto err_release_pl_mem; |
1395 | da8xx_fb_info->cmap.len = par->palette_sz; | 1400 | da8xx_fb_info->cmap.len = par->palette_sz; |
1396 | 1401 | ||
1397 | /* initialize var_screeninfo */ | 1402 | /* initialize var_screeninfo */ |
1398 | da8xx_fb_var.activate = FB_ACTIVATE_FORCE; | 1403 | da8xx_fb_var.activate = FB_ACTIVATE_FORCE; |
1399 | fb_set_var(da8xx_fb_info, &da8xx_fb_var); | 1404 | fb_set_var(da8xx_fb_info, &da8xx_fb_var); |
1400 | 1405 | ||
1401 | dev_set_drvdata(&device->dev, da8xx_fb_info); | 1406 | dev_set_drvdata(&device->dev, da8xx_fb_info); |
1402 | 1407 | ||
1403 | /* initialize the vsync wait queue */ | 1408 | /* initialize the vsync wait queue */ |
1404 | init_waitqueue_head(&par->vsync_wait); | 1409 | init_waitqueue_head(&par->vsync_wait); |
1405 | par->vsync_timeout = HZ / 5; | 1410 | par->vsync_timeout = HZ / 5; |
1406 | par->which_dma_channel_done = -1; | 1411 | par->which_dma_channel_done = -1; |
1407 | spin_lock_init(&par->lock_for_chan_update); | 1412 | spin_lock_init(&par->lock_for_chan_update); |
1408 | 1413 | ||
1409 | /* Register the Frame Buffer */ | 1414 | /* Register the Frame Buffer */ |
1410 | if (register_framebuffer(da8xx_fb_info) < 0) { | 1415 | if (register_framebuffer(da8xx_fb_info) < 0) { |
1411 | dev_err(&device->dev, | 1416 | dev_err(&device->dev, |
1412 | "GLCD: Frame Buffer Registration Failed!\n"); | 1417 | "GLCD: Frame Buffer Registration Failed!\n"); |
1413 | ret = -EINVAL; | 1418 | ret = -EINVAL; |
1414 | goto err_dealloc_cmap; | 1419 | goto err_dealloc_cmap; |
1415 | } | 1420 | } |
1416 | 1421 | ||
1417 | #ifdef CONFIG_CPU_FREQ | 1422 | #ifdef CONFIG_CPU_FREQ |
1418 | ret = lcd_da8xx_cpufreq_register(par); | 1423 | ret = lcd_da8xx_cpufreq_register(par); |
1419 | if (ret) { | 1424 | if (ret) { |
1420 | dev_err(&device->dev, "failed to register cpufreq\n"); | 1425 | dev_err(&device->dev, "failed to register cpufreq\n"); |
1421 | goto err_cpu_freq; | 1426 | goto err_cpu_freq; |
1422 | } | 1427 | } |
1423 | #endif | 1428 | #endif |
1424 | 1429 | ||
1425 | if (lcd_revision == LCD_VERSION_1) | 1430 | if (lcd_revision == LCD_VERSION_1) |
1426 | lcdc_irq_handler = lcdc_irq_handler_rev01; | 1431 | lcdc_irq_handler = lcdc_irq_handler_rev01; |
1427 | else | 1432 | else |
1428 | lcdc_irq_handler = lcdc_irq_handler_rev02; | 1433 | lcdc_irq_handler = lcdc_irq_handler_rev02; |
1429 | 1434 | ||
1430 | ret = request_irq(par->irq, lcdc_irq_handler, 0, | 1435 | ret = request_irq(par->irq, lcdc_irq_handler, 0, |
1431 | DRIVER_NAME, par); | 1436 | DRIVER_NAME, par); |
1432 | if (ret) | 1437 | if (ret) |
1433 | goto irq_freq; | 1438 | goto irq_freq; |
1434 | return 0; | 1439 | return 0; |
1435 | 1440 | ||
1436 | irq_freq: | 1441 | irq_freq: |
1437 | #ifdef CONFIG_CPU_FREQ | 1442 | #ifdef CONFIG_CPU_FREQ |
1438 | lcd_da8xx_cpufreq_deregister(par); | 1443 | lcd_da8xx_cpufreq_deregister(par); |
1439 | err_cpu_freq: | 1444 | err_cpu_freq: |
1440 | #endif | 1445 | #endif |
1441 | unregister_framebuffer(da8xx_fb_info); | 1446 | unregister_framebuffer(da8xx_fb_info); |
1442 | 1447 | ||
1443 | err_dealloc_cmap: | 1448 | err_dealloc_cmap: |
1444 | fb_dealloc_cmap(&da8xx_fb_info->cmap); | 1449 | fb_dealloc_cmap(&da8xx_fb_info->cmap); |
1445 | 1450 | ||
1446 | err_release_pl_mem: | 1451 | err_release_pl_mem: |
1447 | dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, | 1452 | dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, |
1448 | par->p_palette_base); | 1453 | par->p_palette_base); |
1449 | 1454 | ||
1450 | err_release_fb_mem: | 1455 | err_release_fb_mem: |
1451 | dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys); | 1456 | dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys); |
1452 | 1457 | ||
1453 | err_release_fb: | 1458 | err_release_fb: |
1454 | framebuffer_release(da8xx_fb_info); | 1459 | framebuffer_release(da8xx_fb_info); |
1455 | 1460 | ||
1456 | err_clk_disable: | 1461 | err_clk_disable: |
1457 | clk_disable(fb_clk); | 1462 | clk_disable(fb_clk); |
1458 | 1463 | ||
1459 | err_clk_put2: | 1464 | err_clk_put2: |
1460 | clk_put(fb_clk); | 1465 | clk_put(fb_clk); |
1461 | 1466 | ||
1462 | err_clk_get1: | 1467 | err_clk_get1: |
1463 | clk_disable(fb_l4ick); | 1468 | clk_disable(fb_l4ick); |
1464 | 1469 | ||
1465 | err_clk_put1: | 1470 | err_clk_put1: |
1466 | clk_put(fb_l4ick); | 1471 | clk_put(fb_l4ick); |
1467 | 1472 | ||
1468 | err_clk_get0: | 1473 | err_clk_get0: |
1469 | clk_disable(fb_l3ick); | 1474 | clk_disable(fb_l3ick); |
1470 | 1475 | ||
1471 | err_clk_put0: | 1476 | err_clk_put0: |
1472 | clk_put(fb_l3ick); | 1477 | clk_put(fb_l3ick); |
1473 | 1478 | ||
1474 | err_ioremap: | 1479 | err_ioremap: |
1475 | iounmap((void __iomem *)da8xx_fb_reg_base); | 1480 | iounmap((void __iomem *)da8xx_fb_reg_base); |
1476 | 1481 | ||
1477 | err_request_mem: | 1482 | err_request_mem: |
1478 | release_mem_region(lcdc_regs->start, len); | 1483 | release_mem_region(lcdc_regs->start, len); |
1479 | 1484 | ||
1480 | return ret; | 1485 | return ret; |
1481 | } | 1486 | } |
1482 | 1487 | ||
1483 | #ifdef CONFIG_PM | 1488 | #ifdef CONFIG_PM |
1484 | static int fb_suspend(struct platform_device *dev, pm_message_t state) | 1489 | static int fb_suspend(struct platform_device *dev, pm_message_t state) |
1485 | { | 1490 | { |
1486 | struct fb_info *info = platform_get_drvdata(dev); | 1491 | struct fb_info *info = platform_get_drvdata(dev); |
1487 | struct da8xx_fb_par *par = info->par; | 1492 | struct da8xx_fb_par *par = info->par; |
1488 | unsigned long timeo = jiffies + msecs_to_jiffies(5000); | 1493 | unsigned long timeo = jiffies + msecs_to_jiffies(5000); |
1489 | u32 stat; | 1494 | u32 stat; |
1490 | 1495 | ||
1491 | console_lock(); | 1496 | console_lock(); |
1492 | if (par->panel_power_ctrl) | 1497 | if (par->panel_power_ctrl) |
1493 | par->panel_power_ctrl(0); | 1498 | par->panel_power_ctrl(0); |
1494 | 1499 | ||
1495 | fb_set_suspend(info, 1); | 1500 | fb_set_suspend(info, 1); |
1496 | lcd_disable_raster(); | 1501 | lcd_disable_raster(); |
1497 | 1502 | ||
1498 | /* Wait for the current frame to complete */ | 1503 | /* Wait for the current frame to complete */ |
1499 | do { | 1504 | do { |
1500 | if (lcd_revision == LCD_VERSION_1) | 1505 | if (lcd_revision == LCD_VERSION_1) |
1501 | stat = lcdc_read(LCD_STAT_REG); | 1506 | stat = lcdc_read(LCD_STAT_REG); |
1502 | else | 1507 | else |
1503 | stat = lcdc_read(LCD_MASKED_STAT_REG); | 1508 | stat = lcdc_read(LCD_MASKED_STAT_REG); |
1504 | cpu_relax(); | 1509 | cpu_relax(); |
1505 | } while (!(stat & BIT(0)) && time_before(jiffies, timeo)); | 1510 | } while (!(stat & BIT(0)) && time_before(jiffies, timeo)); |
1506 | 1511 | ||
1507 | if (lcd_revision == LCD_VERSION_1) | 1512 | if (lcd_revision == LCD_VERSION_1) |
1508 | lcdc_write(stat, LCD_STAT_REG); | 1513 | lcdc_write(stat, LCD_STAT_REG); |
1509 | else | 1514 | else |
1510 | lcdc_write(stat, LCD_MASKED_STAT_REG); | 1515 | lcdc_write(stat, LCD_MASKED_STAT_REG); |
1511 | 1516 | ||
1512 | if (time_after_eq(jiffies, timeo)) { | 1517 | if (time_after_eq(jiffies, timeo)) { |
1513 | dev_err(&dev->dev, "controller timed out\n"); | 1518 | dev_err(&dev->dev, "controller timed out\n"); |
1514 | return -ETIMEDOUT; | 1519 | return -ETIMEDOUT; |
1515 | } | 1520 | } |
1516 | 1521 | ||
1517 | clk_disable(par->lcdc_clk); | 1522 | clk_disable(par->lcdc_clk); |
1518 | console_unlock(); | 1523 | console_unlock(); |
1519 | 1524 | ||
1520 | return 0; | 1525 | return 0; |
1521 | } | 1526 | } |
1522 | static int fb_resume(struct platform_device *dev) | 1527 | static int fb_resume(struct platform_device *dev) |
1523 | { | 1528 | { |
1524 | struct fb_info *info = platform_get_drvdata(dev); | 1529 | struct fb_info *info = platform_get_drvdata(dev); |
1525 | struct da8xx_fb_par *par = info->par; | 1530 | struct da8xx_fb_par *par = info->par; |
1526 | 1531 | ||
1527 | console_lock(); | 1532 | console_lock(); |
1528 | if (par->panel_power_ctrl) | 1533 | if (par->panel_power_ctrl) |
1529 | par->panel_power_ctrl(1); | 1534 | par->panel_power_ctrl(1); |
1530 | 1535 | ||
1531 | clk_enable(par->lcdc_clk); | 1536 | clk_enable(par->lcdc_clk); |
1532 | 1537 | ||
1533 | lcd_enable_raster(); | 1538 | lcd_enable_raster(); |
1534 | 1539 | ||
1535 | if (par->panel_power_ctrl) | 1540 | if (par->panel_power_ctrl) |
1536 | par->panel_power_ctrl(1); | 1541 | par->panel_power_ctrl(1); |
1537 | 1542 | ||
1538 | fb_set_suspend(info, 0); | 1543 | fb_set_suspend(info, 0); |
1539 | console_unlock(); | 1544 | console_unlock(); |
1540 | 1545 | ||
1541 | return 0; | 1546 | return 0; |
1542 | } | 1547 | } |
1543 | #else | 1548 | #else |
1544 | #define fb_suspend NULL | 1549 | #define fb_suspend NULL |
1545 | #define fb_resume NULL | 1550 | #define fb_resume NULL |
1546 | #endif | 1551 | #endif |
1547 | 1552 | ||
1548 | static struct platform_driver da8xx_fb_driver = { | 1553 | static struct platform_driver da8xx_fb_driver = { |
1549 | .probe = fb_probe, | 1554 | .probe = fb_probe, |
1550 | .remove = __devexit_p(fb_remove), | 1555 | .remove = __devexit_p(fb_remove), |
1551 | .suspend = fb_suspend, | 1556 | .suspend = fb_suspend, |
1552 | .resume = fb_resume, | 1557 | .resume = fb_resume, |
1553 | .driver = { | 1558 | .driver = { |
1554 | .name = DRIVER_NAME, | 1559 | .name = DRIVER_NAME, |
1555 | .owner = THIS_MODULE, | 1560 | .owner = THIS_MODULE, |
1556 | }, | 1561 | }, |
1557 | }; | 1562 | }; |
1558 | 1563 | ||
1559 | static int __init da8xx_fb_init(void) | 1564 | static int __init da8xx_fb_init(void) |
1560 | { | 1565 | { |
1561 | return platform_driver_register(&da8xx_fb_driver); | 1566 | return platform_driver_register(&da8xx_fb_driver); |
1562 | } | 1567 | } |
1563 | 1568 | ||
1564 | static void __exit da8xx_fb_cleanup(void) | 1569 | static void __exit da8xx_fb_cleanup(void) |
1565 | { | 1570 | { |
1566 | platform_driver_unregister(&da8xx_fb_driver); | 1571 | platform_driver_unregister(&da8xx_fb_driver); |
1567 | } | 1572 | } |
1568 | 1573 | ||
1569 | module_init(da8xx_fb_init); | 1574 | module_init(da8xx_fb_init); |
1570 | module_exit(da8xx_fb_cleanup); | 1575 | module_exit(da8xx_fb_cleanup); |
1571 | 1576 | ||
1572 | MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); | 1577 | MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); |
1573 | MODULE_AUTHOR("Texas Instruments"); | 1578 | MODULE_AUTHOR("Texas Instruments"); |
1574 | MODULE_LICENSE("GPL"); | 1579 | MODULE_LICENSE("GPL"); |
1575 | 1580 |