blob: 73cb4ffff3c5910f5dfb8b41f5e40f2849803459 [file] [log] [blame]
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301/*
2 * Silicon Motion SM7XX frame buffer device
3 *
4 * Copyright (C) 2006 Silicon Motion Technology Corp.
5 * Authors: Ge Wang, gewang@siliconmotion.com
6 * Boyod boyod.yang@siliconmotion.com.cn
7 *
8 * Copyright (C) 2009 Lemote, Inc.
9 * Author: Wu Zhangjin, wuzhangjin@gmail.com
10 *
11 * Copyright (C) 2011 Igalia, S.L.
12 * Author: Javier M. Mellid <jmunhoz@igalia.com>
13 *
14 * This file is subject to the terms and conditions of the GNU General Public
15 * License. See the file COPYING in the main directory of this archive for
16 * more details.
17 *
18 * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
19 */
20
21#include <linux/io.h>
22#include <linux/fb.h>
23#include <linux/pci.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/uaccess.h>
27#include <linux/module.h>
28#include <linux/console.h>
29#include <linux/screen_info.h>
30
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053031#include <linux/pm.h>
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053032
Sudip Mukherjee1461d662015-08-07 18:31:13 +053033#include "sm712.h"
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053034
35/*
36* Private structure
37*/
38struct smtcfb_info {
39 struct pci_dev *pdev;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +053040 struct fb_info *fb;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053041 u16 chip_id;
42 u8 chip_rev_id;
43
44 void __iomem *lfb; /* linear frame buffer */
45 void __iomem *dp_regs; /* drawing processor control regs */
46 void __iomem *vp_regs; /* video processor control regs */
47 void __iomem *cp_regs; /* capture processor control regs */
48 void __iomem *mmio; /* memory map IO port */
49
50 u_int width;
51 u_int height;
52 u_int hz;
53
54 u32 colreg[17];
55};
56
Sudip Mukherjee74121892015-02-03 20:23:33 +053057void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053058
Julia Lawallca9384c2016-09-11 17:17:20 +020059static const struct fb_var_screeninfo smtcfb_var = {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053060 .xres = 1024,
61 .yres = 600,
62 .xres_virtual = 1024,
63 .yres_virtual = 600,
64 .bits_per_pixel = 16,
65 .red = {16, 8, 0},
66 .green = {8, 8, 0},
67 .blue = {0, 8, 0},
68 .activate = FB_ACTIVATE_NOW,
69 .height = -1,
70 .width = -1,
71 .vmode = FB_VMODE_NONINTERLACED,
72 .nonstd = 0,
73 .accel_flags = FB_ACCELF_TEXT,
74};
75
76static struct fb_fix_screeninfo smtcfb_fix = {
77 .id = "smXXXfb",
78 .type = FB_TYPE_PACKED_PIXELS,
79 .visual = FB_VISUAL_TRUECOLOR,
80 .line_length = 800 * 3,
81 .accel = FB_ACCEL_SMI_LYNX,
82 .type_aux = 0,
83 .xpanstep = 0,
84 .ypanstep = 0,
85 .ywrapstep = 0,
86};
87
88struct vesa_mode {
89 char index[6];
90 u16 lfb_width;
91 u16 lfb_height;
92 u16 lfb_depth;
93};
94
Sudip Mukherjee9d91928c2015-06-17 16:54:40 +053095static const struct vesa_mode vesa_mode_table[] = {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053096 {"0x301", 640, 480, 8},
97 {"0x303", 800, 600, 8},
98 {"0x305", 1024, 768, 8},
99 {"0x307", 1280, 1024, 8},
100
101 {"0x311", 640, 480, 16},
102 {"0x314", 800, 600, 16},
103 {"0x317", 1024, 768, 16},
104 {"0x31A", 1280, 1024, 16},
105
106 {"0x312", 640, 480, 24},
107 {"0x315", 800, 600, 24},
108 {"0x318", 1024, 768, 24},
109 {"0x31B", 1280, 1024, 24},
110};
111
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530112/**********************************************************************
113 SM712 Mode table.
114 **********************************************************************/
Sudip Mukherjee8efba0e2015-06-17 16:54:48 +0530115static const struct modeinit vgamode[] = {
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530116 {
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530117 /* mode#0: 640 x 480 16Bpp 60Hz */
118 640, 480, 16, 60,
119 /* Init_MISC */
120 0xE3,
121 { /* Init_SR0_SR4 */
122 0x03, 0x01, 0x0F, 0x00, 0x0E,
123 },
124 { /* Init_SR10_SR24 */
125 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
126 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0xC4, 0x30, 0x02, 0x01, 0x01,
128 },
129 { /* Init_SR30_SR75 */
130 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
131 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
132 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
133 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
134 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
135 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
136 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
137 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
138 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
139 },
140 { /* Init_SR80_SR93 */
141 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
142 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
143 0x00, 0x00, 0x00, 0x00,
144 },
145 { /* Init_SRA0_SRAF */
146 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
147 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
148 },
149 { /* Init_GR00_GR08 */
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
151 0xFF,
152 },
153 { /* Init_AR00_AR14 */
154 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
155 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
156 0x41, 0x00, 0x0F, 0x00, 0x00,
157 },
158 { /* Init_CR00_CR18 */
159 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
160 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
162 0xFF,
163 },
164 { /* Init_CR30_CR4D */
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
166 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
167 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
168 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
169 },
170 { /* Init_CR90_CRA7 */
171 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
172 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
173 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
174 },
175 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530176 {
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530177 /* mode#1: 640 x 480 24Bpp 60Hz */
178 640, 480, 24, 60,
179 /* Init_MISC */
180 0xE3,
181 { /* Init_SR0_SR4 */
182 0x03, 0x01, 0x0F, 0x00, 0x0E,
183 },
184 { /* Init_SR10_SR24 */
185 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
186 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0xC4, 0x30, 0x02, 0x01, 0x01,
188 },
189 { /* Init_SR30_SR75 */
190 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
191 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
192 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
193 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
194 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
195 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
196 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
197 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
198 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
199 },
200 { /* Init_SR80_SR93 */
201 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
202 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
203 0x00, 0x00, 0x00, 0x00,
204 },
205 { /* Init_SRA0_SRAF */
206 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
207 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
208 },
209 { /* Init_GR00_GR08 */
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
211 0xFF,
212 },
213 { /* Init_AR00_AR14 */
214 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
215 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
216 0x41, 0x00, 0x0F, 0x00, 0x00,
217 },
218 { /* Init_CR00_CR18 */
219 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
220 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
222 0xFF,
223 },
224 { /* Init_CR30_CR4D */
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
226 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
227 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
228 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
229 },
230 { /* Init_CR90_CRA7 */
231 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
232 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
233 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
234 },
235 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530236 {
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530237 /* mode#0: 640 x 480 32Bpp 60Hz */
238 640, 480, 32, 60,
239 /* Init_MISC */
240 0xE3,
241 { /* Init_SR0_SR4 */
242 0x03, 0x01, 0x0F, 0x00, 0x0E,
243 },
244 { /* Init_SR10_SR24 */
245 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
246 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0xC4, 0x30, 0x02, 0x01, 0x01,
248 },
249 { /* Init_SR30_SR75 */
250 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
251 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
252 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
253 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
254 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
255 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
256 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
257 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
258 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
259 },
260 { /* Init_SR80_SR93 */
261 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
262 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
263 0x00, 0x00, 0x00, 0x00,
264 },
265 { /* Init_SRA0_SRAF */
266 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
267 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
268 },
269 { /* Init_GR00_GR08 */
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
271 0xFF,
272 },
273 { /* Init_AR00_AR14 */
274 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
275 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
276 0x41, 0x00, 0x0F, 0x00, 0x00,
277 },
278 { /* Init_CR00_CR18 */
279 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
280 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
282 0xFF,
283 },
284 { /* Init_CR30_CR4D */
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
286 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
287 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
288 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
289 },
290 { /* Init_CR90_CRA7 */
291 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
292 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
293 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
294 },
295 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530296
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530297 { /* mode#2: 800 x 600 16Bpp 60Hz */
298 800, 600, 16, 60,
299 /* Init_MISC */
300 0x2B,
301 { /* Init_SR0_SR4 */
302 0x03, 0x01, 0x0F, 0x03, 0x0E,
303 },
304 { /* Init_SR10_SR24 */
305 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
306 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0xC4, 0x30, 0x02, 0x01, 0x01,
308 },
309 { /* Init_SR30_SR75 */
310 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
311 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
312 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
313 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
314 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
315 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
316 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
317 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
318 0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
319 },
320 { /* Init_SR80_SR93 */
321 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
322 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
323 0x00, 0x00, 0x00, 0x00,
324 },
325 { /* Init_SRA0_SRAF */
326 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
327 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
328 },
329 { /* Init_GR00_GR08 */
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
331 0xFF,
332 },
333 { /* Init_AR00_AR14 */
334 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
335 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
336 0x41, 0x00, 0x0F, 0x00, 0x00,
337 },
338 { /* Init_CR00_CR18 */
339 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
340 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
342 0xFF,
343 },
344 { /* Init_CR30_CR4D */
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
346 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
347 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
348 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
349 },
350 { /* Init_CR90_CRA7 */
351 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
352 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
353 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
354 },
355 },
356 { /* mode#3: 800 x 600 24Bpp 60Hz */
357 800, 600, 24, 60,
358 0x2B,
359 { /* Init_SR0_SR4 */
360 0x03, 0x01, 0x0F, 0x03, 0x0E,
361 },
362 { /* Init_SR10_SR24 */
363 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
364 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0xC4, 0x30, 0x02, 0x01, 0x01,
366 },
367 { /* Init_SR30_SR75 */
368 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
369 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
370 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
371 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
372 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
373 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
374 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
375 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
376 0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
377 },
378 { /* Init_SR80_SR93 */
379 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
380 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
381 0x00, 0x00, 0x00, 0x00,
382 },
383 { /* Init_SRA0_SRAF */
384 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
385 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
386 },
387 { /* Init_GR00_GR08 */
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
389 0xFF,
390 },
391 { /* Init_AR00_AR14 */
392 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
393 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
394 0x41, 0x00, 0x0F, 0x00, 0x00,
395 },
396 { /* Init_CR00_CR18 */
397 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
398 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
400 0xFF,
401 },
402 { /* Init_CR30_CR4D */
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
404 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
405 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
406 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
407 },
408 { /* Init_CR90_CRA7 */
409 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
410 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
411 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
412 },
413 },
414 { /* mode#7: 800 x 600 32Bpp 60Hz */
415 800, 600, 32, 60,
416 /* Init_MISC */
417 0x2B,
418 { /* Init_SR0_SR4 */
419 0x03, 0x01, 0x0F, 0x03, 0x0E,
420 },
421 { /* Init_SR10_SR24 */
422 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
423 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0xC4, 0x30, 0x02, 0x01, 0x01,
425 },
426 { /* Init_SR30_SR75 */
427 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
428 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
429 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
430 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
431 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
432 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
433 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
434 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
435 0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
436 },
437 { /* Init_SR80_SR93 */
438 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
439 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
440 0x00, 0x00, 0x00, 0x00,
441 },
442 { /* Init_SRA0_SRAF */
443 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
444 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
445 },
446 { /* Init_GR00_GR08 */
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
448 0xFF,
449 },
450 { /* Init_AR00_AR14 */
451 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
452 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
453 0x41, 0x00, 0x0F, 0x00, 0x00,
454 },
455 { /* Init_CR00_CR18 */
456 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
457 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
459 0xFF,
460 },
461 { /* Init_CR30_CR4D */
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
463 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
464 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
465 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
466 },
467 { /* Init_CR90_CRA7 */
468 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
469 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
470 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
471 },
472 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530473 /* We use 1024x768 table to light 1024x600 panel for lemote */
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530474 { /* mode#4: 1024 x 600 16Bpp 60Hz */
475 1024, 600, 16, 60,
476 /* Init_MISC */
477 0xEB,
478 { /* Init_SR0_SR4 */
479 0x03, 0x01, 0x0F, 0x00, 0x0E,
480 },
481 { /* Init_SR10_SR24 */
482 0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
483 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0xC4, 0x30, 0x02, 0x00, 0x01,
485 },
486 { /* Init_SR30_SR75 */
487 0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
488 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
489 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
490 0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
491 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
492 0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
493 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
494 0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
495 0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
496 },
497 { /* Init_SR80_SR93 */
498 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
499 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
500 0x00, 0x00, 0x00, 0x00,
501 },
502 { /* Init_SRA0_SRAF */
503 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
504 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
505 },
506 { /* Init_GR00_GR08 */
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
508 0xFF,
509 },
510 { /* Init_AR00_AR14 */
511 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
512 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
513 0x41, 0x00, 0x0F, 0x00, 0x00,
514 },
515 { /* Init_CR00_CR18 */
516 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
517 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
519 0xFF,
520 },
521 { /* Init_CR30_CR4D */
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
523 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
524 0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
525 0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
526 },
527 { /* Init_CR90_CRA7 */
528 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
529 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
530 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
531 },
532 },
533 { /* mode#5: 1024 x 768 24Bpp 60Hz */
534 1024, 768, 24, 60,
535 /* Init_MISC */
536 0xEB,
537 { /* Init_SR0_SR4 */
538 0x03, 0x01, 0x0F, 0x03, 0x0E,
539 },
540 { /* Init_SR10_SR24 */
541 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
542 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0xC4, 0x30, 0x02, 0x01, 0x01,
544 },
545 { /* Init_SR30_SR75 */
546 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
547 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
548 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
549 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
550 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
551 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
552 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
553 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
554 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
555 },
556 { /* Init_SR80_SR93 */
557 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
558 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
559 0x00, 0x00, 0x00, 0x00,
560 },
561 { /* Init_SRA0_SRAF */
562 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
563 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
564 },
565 { /* Init_GR00_GR08 */
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
567 0xFF,
568 },
569 { /* Init_AR00_AR14 */
570 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
571 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
572 0x41, 0x00, 0x0F, 0x00, 0x00,
573 },
574 { /* Init_CR00_CR18 */
575 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
576 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
578 0xFF,
579 },
580 { /* Init_CR30_CR4D */
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
582 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
583 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
584 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
585 },
586 { /* Init_CR90_CRA7 */
587 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
588 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
589 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
590 },
591 },
592 { /* mode#4: 1024 x 768 32Bpp 60Hz */
593 1024, 768, 32, 60,
594 /* Init_MISC */
595 0xEB,
596 { /* Init_SR0_SR4 */
597 0x03, 0x01, 0x0F, 0x03, 0x0E,
598 },
599 { /* Init_SR10_SR24 */
600 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
601 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0xC4, 0x32, 0x02, 0x01, 0x01,
603 },
604 { /* Init_SR30_SR75 */
605 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
606 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
607 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
608 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
609 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
610 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
611 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
612 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
613 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
614 },
615 { /* Init_SR80_SR93 */
616 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
617 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
618 0x00, 0x00, 0x00, 0x00,
619 },
620 { /* Init_SRA0_SRAF */
621 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
622 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
623 },
624 { /* Init_GR00_GR08 */
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
626 0xFF,
627 },
628 { /* Init_AR00_AR14 */
629 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
630 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
631 0x41, 0x00, 0x0F, 0x00, 0x00,
632 },
633 { /* Init_CR00_CR18 */
634 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
635 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
637 0xFF,
638 },
639 { /* Init_CR30_CR4D */
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
641 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
642 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
643 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
644 },
645 { /* Init_CR90_CRA7 */
646 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
647 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
648 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
649 },
650 },
651 { /* mode#6: 320 x 240 16Bpp 60Hz */
652 320, 240, 16, 60,
653 /* Init_MISC */
654 0xEB,
655 { /* Init_SR0_SR4 */
656 0x03, 0x01, 0x0F, 0x03, 0x0E,
657 },
658 { /* Init_SR10_SR24 */
659 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
660 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0xC4, 0x32, 0x02, 0x01, 0x01,
662 },
663 { /* Init_SR30_SR75 */
664 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
665 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
666 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
667 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
668 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
669 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
670 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
671 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
672 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
673 },
674 { /* Init_SR80_SR93 */
675 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
676 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
677 0x00, 0x00, 0x00, 0x00,
678 },
679 { /* Init_SRA0_SRAF */
680 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
681 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
682 },
683 { /* Init_GR00_GR08 */
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
685 0xFF,
686 },
687 { /* Init_AR00_AR14 */
688 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
689 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
690 0x41, 0x00, 0x0F, 0x00, 0x00,
691 },
692 { /* Init_CR00_CR18 */
693 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
694 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
696 0xFF,
697 },
698 { /* Init_CR30_CR4D */
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
700 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
701 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
702 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
703 },
704 { /* Init_CR90_CRA7 */
705 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
706 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
707 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
708 },
709 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530710
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530711 { /* mode#8: 320 x 240 32Bpp 60Hz */
712 320, 240, 32, 60,
713 /* Init_MISC */
714 0xEB,
715 { /* Init_SR0_SR4 */
716 0x03, 0x01, 0x0F, 0x03, 0x0E,
717 },
718 { /* Init_SR10_SR24 */
719 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
720 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0xC4, 0x32, 0x02, 0x01, 0x01,
722 },
723 { /* Init_SR30_SR75 */
724 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
725 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
726 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
727 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
728 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
729 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
730 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
731 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
732 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
733 },
734 { /* Init_SR80_SR93 */
735 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
736 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
737 0x00, 0x00, 0x00, 0x00,
738 },
739 { /* Init_SRA0_SRAF */
740 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
741 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
742 },
743 { /* Init_GR00_GR08 */
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
745 0xFF,
746 },
747 { /* Init_AR00_AR14 */
748 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
749 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
750 0x41, 0x00, 0x0F, 0x00, 0x00,
751 },
752 { /* Init_CR00_CR18 */
753 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
754 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
756 0xFF,
757 },
758 { /* Init_CR30_CR4D */
759 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
760 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
761 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
762 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
763 },
764 { /* Init_CR90_CRA7 */
765 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
766 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
767 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
768 },
769 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530770};
771
Max Perepelitsyn11862b32015-02-03 14:44:28 +0600772static struct screen_info smtc_scr_info;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530773
Sudip Mukherjeec65434e2015-03-08 23:10:09 +0530774static char *mode_option;
775
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530776/* process command line options, get vga parameter */
Sudip Mukherjee71ce7622015-03-08 23:10:11 +0530777static void __init sm7xx_vga_setup(char *options)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530778{
779 int i;
780
781 if (!options || !*options)
Sudip Mukherjee71ce7622015-03-08 23:10:11 +0530782 return;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530783
784 smtc_scr_info.lfb_width = 0;
785 smtc_scr_info.lfb_height = 0;
786 smtc_scr_info.lfb_depth = 0;
787
788 pr_debug("sm7xx_vga_setup = %s\n", options);
789
790 for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
791 if (strstr(options, vesa_mode_table[i].index)) {
792 smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width;
793 smtc_scr_info.lfb_height =
794 vesa_mode_table[i].lfb_height;
795 smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth;
Sudip Mukherjee71ce7622015-03-08 23:10:11 +0530796 return;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530797 }
798 }
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530799}
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530800
801static void sm712_setpalette(int regno, unsigned red, unsigned green,
802 unsigned blue, struct fb_info *info)
803{
804 /* set bit 5:4 = 01 (write LCD RAM only) */
805 smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
806
807 smtc_mmiowb(regno, dac_reg);
808 smtc_mmiowb(red >> 10, dac_val);
809 smtc_mmiowb(green >> 10, dac_val);
810 smtc_mmiowb(blue >> 10, dac_val);
811}
812
813/* chan_to_field
814 *
815 * convert a colour value into a field position
816 *
817 * from pxafb.c
818 */
819
820static inline unsigned int chan_to_field(unsigned int chan,
821 struct fb_bitfield *bf)
822{
823 chan &= 0xffff;
824 chan >>= 16 - bf->length;
825 return chan << bf->offset;
826}
827
828static int smtc_blank(int blank_mode, struct fb_info *info)
829{
830 /* clear DPMS setting */
831 switch (blank_mode) {
832 case FB_BLANK_UNBLANK:
833 /* Screen On: HSync: On, VSync : On */
834 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
835 smtc_seqw(0x6a, 0x16);
836 smtc_seqw(0x6b, 0x02);
837 smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
838 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
839 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
840 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
841 smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
842 break;
843 case FB_BLANK_NORMAL:
844 /* Screen Off: HSync: On, VSync : On Soft blank */
845 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
846 smtc_seqw(0x6a, 0x16);
847 smtc_seqw(0x6b, 0x02);
848 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
849 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
850 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
851 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
852 break;
853 case FB_BLANK_VSYNC_SUSPEND:
854 /* Screen On: HSync: On, VSync : Off */
855 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
856 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
857 smtc_seqw(0x6a, 0x0c);
858 smtc_seqw(0x6b, 0x02);
859 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
860 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
861 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
862 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
863 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
864 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
865 break;
866 case FB_BLANK_HSYNC_SUSPEND:
867 /* Screen On: HSync: Off, VSync : On */
868 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
869 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
870 smtc_seqw(0x6a, 0x0c);
871 smtc_seqw(0x6b, 0x02);
872 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
873 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
874 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
875 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
876 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
877 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
878 break;
879 case FB_BLANK_POWERDOWN:
880 /* Screen On: HSync: Off, VSync : Off */
881 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
882 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
883 smtc_seqw(0x6a, 0x0c);
884 smtc_seqw(0x6b, 0x02);
885 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
886 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
887 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
888 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
889 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
890 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
891 break;
892 default:
893 return -EINVAL;
894 }
895
896 return 0;
897}
898
899static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
900 unsigned blue, unsigned trans, struct fb_info *info)
901{
902 struct smtcfb_info *sfb;
903 u32 val;
904
905 sfb = info->par;
906
907 if (regno > 255)
908 return 1;
909
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +0530910 switch (sfb->fb->fix.visual) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530911 case FB_VISUAL_DIRECTCOLOR:
912 case FB_VISUAL_TRUECOLOR:
913 /*
914 * 16/32 bit true-colour, use pseudo-palette for 16 base color
915 */
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530916 if (regno >= 16)
917 break;
918 if (sfb->fb->var.bits_per_pixel == 16) {
919 u32 *pal = sfb->fb->pseudo_palette;
Sudip Mukherjeea1f6da62015-01-19 13:41:03 +0530920
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530921 val = chan_to_field(red, &sfb->fb->var.red);
922 val |= chan_to_field(green, &sfb->fb->var.green);
923 val |= chan_to_field(blue, &sfb->fb->var.blue);
Sudip Mukherjee87bf7922015-07-15 13:59:45 +0530924 pal[regno] = pal_rgb(red, green, blue, val);
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530925 } else {
926 u32 *pal = sfb->fb->pseudo_palette;
Sudip Mukherjeea1f6da62015-01-19 13:41:03 +0530927
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530928 val = chan_to_field(red, &sfb->fb->var.red);
929 val |= chan_to_field(green, &sfb->fb->var.green);
930 val |= chan_to_field(blue, &sfb->fb->var.blue);
Sudip Mukherjee87bf7922015-07-15 13:59:45 +0530931 pal[regno] = big_swap(val);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530932 }
933 break;
934
935 case FB_VISUAL_PSEUDOCOLOR:
936 /* color depth 8 bit */
937 sm712_setpalette(regno, red, green, blue, info);
938 break;
939
940 default:
941 return 1; /* unknown type */
942 }
943
944 return 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530945}
946
Sudip Mukherjeef5daff32015-06-17 16:54:44 +0530947static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
948 size_t count, loff_t *ppos)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530949{
950 unsigned long p = *ppos;
951
952 u32 *buffer, *dst;
953 u32 __iomem *src;
954 int c, i, cnt = 0, err = 0;
955 unsigned long total_size;
956
957 if (!info || !info->screen_base)
958 return -ENODEV;
959
960 if (info->state != FBINFO_STATE_RUNNING)
961 return -EPERM;
962
963 total_size = info->screen_size;
964
965 if (total_size == 0)
966 total_size = info->fix.smem_len;
967
968 if (p >= total_size)
969 return 0;
970
971 if (count >= total_size)
972 count = total_size;
973
974 if (count + p > total_size)
975 count = total_size - p;
976
977 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
978 if (!buffer)
979 return -ENOMEM;
980
Sudip Mukherjee3e4b5592015-06-17 16:54:43 +0530981 src = (u32 __iomem *)(info->screen_base + p);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530982
983 if (info->fbops->fb_sync)
984 info->fbops->fb_sync(info);
985
986 while (count) {
987 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
988 dst = buffer;
989 for (i = c >> 2; i--;) {
990 *dst = fb_readl(src++);
Sudip Mukherjee87bf7922015-07-15 13:59:45 +0530991 *dst = big_swap(*dst);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530992 dst++;
993 }
994 if (c & 3) {
Sudip Mukherjee53f54a42015-01-19 13:41:04 +0530995 u8 *dst8 = (u8 *)dst;
996 u8 __iomem *src8 = (u8 __iomem *)src;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530997
998 for (i = c & 3; i--;) {
999 if (i & 1) {
1000 *dst8++ = fb_readb(++src8);
1001 } else {
1002 *dst8++ = fb_readb(--src8);
1003 src8 += 2;
1004 }
1005 }
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301006 src = (u32 __iomem *)src8;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301007 }
1008
1009 if (copy_to_user(buf, buffer, c)) {
1010 err = -EFAULT;
1011 break;
1012 }
1013 *ppos += c;
1014 buf += c;
1015 cnt += c;
1016 count -= c;
1017 }
1018
1019 kfree(buffer);
1020
1021 return (err) ? err : cnt;
1022}
1023
Sudip Mukherjeef5daff32015-06-17 16:54:44 +05301024static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
1025 size_t count, loff_t *ppos)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301026{
1027 unsigned long p = *ppos;
1028
1029 u32 *buffer, *src;
1030 u32 __iomem *dst;
1031 int c, i, cnt = 0, err = 0;
1032 unsigned long total_size;
1033
1034 if (!info || !info->screen_base)
1035 return -ENODEV;
1036
1037 if (info->state != FBINFO_STATE_RUNNING)
1038 return -EPERM;
1039
1040 total_size = info->screen_size;
1041
1042 if (total_size == 0)
1043 total_size = info->fix.smem_len;
1044
1045 if (p > total_size)
1046 return -EFBIG;
1047
1048 if (count > total_size) {
1049 err = -EFBIG;
1050 count = total_size;
1051 }
1052
1053 if (count + p > total_size) {
1054 if (!err)
1055 err = -ENOSPC;
1056
1057 count = total_size - p;
1058 }
1059
1060 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
1061 if (!buffer)
1062 return -ENOMEM;
1063
Sudip Mukherjee3e4b5592015-06-17 16:54:43 +05301064 dst = (u32 __iomem *)(info->screen_base + p);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301065
1066 if (info->fbops->fb_sync)
1067 info->fbops->fb_sync(info);
1068
1069 while (count) {
1070 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1071 src = buffer;
1072
1073 if (copy_from_user(src, buf, c)) {
1074 err = -EFAULT;
1075 break;
1076 }
1077
1078 for (i = c >> 2; i--;) {
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301079 fb_writel(big_swap(*src), dst++);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301080 src++;
1081 }
1082 if (c & 3) {
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301083 u8 *src8 = (u8 *)src;
1084 u8 __iomem *dst8 = (u8 __iomem *)dst;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301085
1086 for (i = c & 3; i--;) {
1087 if (i & 1) {
1088 fb_writeb(*src8++, ++dst8);
1089 } else {
1090 fb_writeb(*src8++, --dst8);
1091 dst8 += 2;
1092 }
1093 }
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301094 dst = (u32 __iomem *)dst8;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301095 }
1096
1097 *ppos += c;
1098 buf += c;
1099 cnt += c;
1100 count -= c;
1101 }
1102
1103 kfree(buffer);
1104
1105 return (cnt) ? cnt : err;
1106}
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301107
1108static void sm7xx_set_timing(struct smtcfb_info *sfb)
1109{
1110 int i = 0, j = 0;
Sudip Mukherjeec4d50762015-02-03 20:23:34 +05301111 u32 m_nscreenstride;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301112
1113 dev_dbg(&sfb->pdev->dev,
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301114 "sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
1115 sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301116
Sudip Mukherjee7caf4632015-06-17 16:54:41 +05301117 for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301118 if (vgamode[j].mmsizex != sfb->width ||
1119 vgamode[j].mmsizey != sfb->height ||
1120 vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
1121 vgamode[j].hz != sfb->hz)
1122 continue;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301123
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301124 dev_dbg(&sfb->pdev->dev,
1125 "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
1126 vgamode[j].mmsizex, vgamode[j].mmsizey,
1127 vgamode[j].bpp, vgamode[j].hz);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301128
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301129 dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301130
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301131 smtc_mmiowb(0x0, 0x3c6);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301132
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301133 smtc_seqw(0, 0x1);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301134
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301135 smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301136
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301137 /* init SEQ register SR00 - SR04 */
1138 for (i = 0; i < SIZE_SR00_SR04; i++)
1139 smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301140
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301141 /* init SEQ register SR10 - SR24 */
1142 for (i = 0; i < SIZE_SR10_SR24; i++)
1143 smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301144
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301145 /* init SEQ register SR30 - SR75 */
1146 for (i = 0; i < SIZE_SR30_SR75; i++)
1147 if ((i + 0x30) != 0x62 && (i + 0x30) != 0x6a &&
1148 (i + 0x30) != 0x6b)
1149 smtc_seqw(i + 0x30,
1150 vgamode[j].init_sr30_sr75[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301151
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301152 /* init SEQ register SR80 - SR93 */
1153 for (i = 0; i < SIZE_SR80_SR93; i++)
1154 smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301155
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301156 /* init SEQ register SRA0 - SRAF */
1157 for (i = 0; i < SIZE_SRA0_SRAF; i++)
1158 smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301159
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301160 /* init Graphic register GR00 - GR08 */
1161 for (i = 0; i < SIZE_GR00_GR08; i++)
1162 smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301163
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301164 /* init Attribute register AR00 - AR14 */
1165 for (i = 0; i < SIZE_AR00_AR14; i++)
1166 smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301167
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301168 /* init CRTC register CR00 - CR18 */
1169 for (i = 0; i < SIZE_CR00_CR18; i++)
1170 smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301171
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301172 /* init CRTC register CR30 - CR4D */
1173 for (i = 0; i < SIZE_CR30_CR4D; i++)
1174 smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
1175
1176 /* init CRTC register CR90 - CRA7 */
1177 for (i = 0; i < SIZE_CR90_CRA7; i++)
1178 smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301179 }
1180 smtc_mmiowb(0x67, 0x3c2);
1181
1182 /* set VPR registers */
1183 writel(0x0, sfb->vp_regs + 0x0C);
1184 writel(0x0, sfb->vp_regs + 0x40);
1185
1186 /* set data width */
Sudip Mukherjeef5daff32015-06-17 16:54:44 +05301187 m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301188 switch (sfb->fb->var.bits_per_pixel) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301189 case 8:
1190 writel(0x0, sfb->vp_regs + 0x0);
1191 break;
1192 case 16:
1193 writel(0x00020000, sfb->vp_regs + 0x0);
1194 break;
1195 case 24:
1196 writel(0x00040000, sfb->vp_regs + 0x0);
1197 break;
1198 case 32:
1199 writel(0x00030000, sfb->vp_regs + 0x0);
1200 break;
1201 }
Sudip Mukherjee3e4b5592015-06-17 16:54:43 +05301202 writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301203 sfb->vp_regs + 0x10);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301204}
1205
1206static void smtc_set_timing(struct smtcfb_info *sfb)
1207{
1208 switch (sfb->chip_id) {
1209 case 0x710:
1210 case 0x712:
1211 case 0x720:
1212 sm7xx_set_timing(sfb);
1213 break;
1214 }
1215}
1216
1217static void smtcfb_setmode(struct smtcfb_info *sfb)
1218{
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301219 switch (sfb->fb->var.bits_per_pixel) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301220 case 32:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301221 sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
1222 sfb->fb->fix.line_length = sfb->fb->var.xres * 4;
1223 sfb->fb->var.red.length = 8;
1224 sfb->fb->var.green.length = 8;
1225 sfb->fb->var.blue.length = 8;
1226 sfb->fb->var.red.offset = 16;
1227 sfb->fb->var.green.offset = 8;
1228 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301229 break;
1230 case 24:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301231 sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
1232 sfb->fb->fix.line_length = sfb->fb->var.xres * 3;
1233 sfb->fb->var.red.length = 8;
1234 sfb->fb->var.green.length = 8;
1235 sfb->fb->var.blue.length = 8;
1236 sfb->fb->var.red.offset = 16;
1237 sfb->fb->var.green.offset = 8;
1238 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301239 break;
1240 case 8:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301241 sfb->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
1242 sfb->fb->fix.line_length = sfb->fb->var.xres;
1243 sfb->fb->var.red.length = 3;
1244 sfb->fb->var.green.length = 3;
1245 sfb->fb->var.blue.length = 2;
1246 sfb->fb->var.red.offset = 5;
1247 sfb->fb->var.green.offset = 2;
1248 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301249 break;
1250 case 16:
1251 default:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301252 sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
1253 sfb->fb->fix.line_length = sfb->fb->var.xres * 2;
1254 sfb->fb->var.red.length = 5;
1255 sfb->fb->var.green.length = 6;
1256 sfb->fb->var.blue.length = 5;
1257 sfb->fb->var.red.offset = 11;
1258 sfb->fb->var.green.offset = 5;
1259 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301260 break;
1261 }
1262
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301263 sfb->width = sfb->fb->var.xres;
1264 sfb->height = sfb->fb->var.yres;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301265 sfb->hz = 60;
1266 smtc_set_timing(sfb);
1267}
1268
1269static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1270{
1271 /* sanity checks */
1272 if (var->xres_virtual < var->xres)
1273 var->xres_virtual = var->xres;
1274
1275 if (var->yres_virtual < var->yres)
1276 var->yres_virtual = var->yres;
1277
1278 /* set valid default bpp */
1279 if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) &&
1280 (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
1281 var->bits_per_pixel = 16;
1282
1283 return 0;
1284}
1285
1286static int smtc_set_par(struct fb_info *info)
1287{
1288 smtcfb_setmode(info->par);
1289
1290 return 0;
1291}
1292
1293static struct fb_ops smtcfb_ops = {
1294 .owner = THIS_MODULE,
1295 .fb_check_var = smtc_check_var,
1296 .fb_set_par = smtc_set_par,
1297 .fb_setcolreg = smtc_setcolreg,
1298 .fb_blank = smtc_blank,
1299 .fb_fillrect = cfb_fillrect,
1300 .fb_imageblit = cfb_imageblit,
1301 .fb_copyarea = cfb_copyarea,
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301302 .fb_read = smtcfb_read,
1303 .fb_write = smtcfb_write,
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301304};
1305
1306/*
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301307 * Unmap in the memory mapped IO registers
1308 */
1309
1310static void smtc_unmap_mmio(struct smtcfb_info *sfb)
1311{
Sudip Mukherjee74121892015-02-03 20:23:33 +05301312 if (sfb && smtc_regbaseaddress)
1313 smtc_regbaseaddress = NULL;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301314}
1315
1316/*
1317 * Map in the screen memory
1318 */
1319
1320static int smtc_map_smem(struct smtcfb_info *sfb,
Sudip Mukherjeef049a522015-01-19 13:41:06 +05301321 struct pci_dev *pdev, u_long smem_len)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301322{
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301323 sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301324
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301325 if (sfb->fb->var.bits_per_pixel == 32)
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301326 sfb->fb->fix.smem_start += big_addr;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301327
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301328 sfb->fb->fix.smem_len = smem_len;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301329
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301330 sfb->fb->screen_base = sfb->lfb;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301331
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301332 if (!sfb->fb->screen_base) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301333 dev_err(&pdev->dev,
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301334 "%s: unable to map screen memory\n", sfb->fb->fix.id);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301335 return -ENOMEM;
1336 }
1337
1338 return 0;
1339}
1340
1341/*
1342 * Unmap in the screen memory
1343 *
1344 */
1345static void smtc_unmap_smem(struct smtcfb_info *sfb)
1346{
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301347 if (sfb && sfb->fb->screen_base) {
1348 iounmap(sfb->fb->screen_base);
1349 sfb->fb->screen_base = NULL;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301350 }
1351}
1352
1353/*
1354 * We need to wake up the device and make sure its in linear memory mode.
1355 */
1356static inline void sm7xx_init_hw(void)
1357{
1358 outb_p(0x18, 0x3c4);
1359 outb_p(0x11, 0x3c5);
1360}
1361
1362static int smtcfb_pci_probe(struct pci_dev *pdev,
Sudip Mukherjeef049a522015-01-19 13:41:06 +05301363 const struct pci_device_id *ent)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301364{
1365 struct smtcfb_info *sfb;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301366 struct fb_info *info;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301367 u_long smem_size = 0x00800000; /* default 8MB */
1368 int err;
1369 unsigned long mmio_base;
1370
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301371 dev_info(&pdev->dev, "Silicon Motion display driver.\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301372
1373 err = pci_enable_device(pdev); /* enable SMTC chip */
1374 if (err)
1375 return err;
1376
Sudip Mukherjeef30a7462015-03-28 14:33:40 +05301377 err = pci_request_region(pdev, 0, "sm7xxfb");
1378 if (err < 0) {
1379 dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
1380 goto failed_regions;
1381 }
1382
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301383 sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
1384
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301385 info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
1386 if (!info) {
1387 dev_err(&pdev->dev, "framebuffer_alloc failed\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301388 err = -ENOMEM;
1389 goto failed_free;
1390 }
1391
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301392 sfb = info->par;
1393 sfb->fb = info;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301394 sfb->chip_id = ent->device;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301395 sfb->pdev = pdev;
1396 info->flags = FBINFO_FLAG_DEFAULT;
1397 info->fbops = &smtcfb_ops;
1398 info->fix = smtcfb_fix;
1399 info->var = smtcfb_var;
1400 info->pseudo_palette = sfb->colreg;
1401 info->par = sfb;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301402
1403 pci_set_drvdata(pdev, sfb);
1404
1405 sm7xx_init_hw();
1406
1407 /* get mode parameter from smtc_scr_info */
1408 if (smtc_scr_info.lfb_width != 0) {
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301409 sfb->fb->var.xres = smtc_scr_info.lfb_width;
1410 sfb->fb->var.yres = smtc_scr_info.lfb_height;
1411 sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301412 } else {
1413 /* default resolution 1024x600 16bit mode */
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301414 sfb->fb->var.xres = SCREEN_X_RES;
1415 sfb->fb->var.yres = SCREEN_Y_RES;
1416 sfb->fb->var.bits_per_pixel = SCREEN_BPP;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301417 }
1418
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301419 big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301420 /* Map address and memory detection */
1421 mmio_base = pci_resource_start(pdev, 0);
1422 pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
1423
1424 switch (sfb->chip_id) {
1425 case 0x710:
1426 case 0x712:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301427 sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
1428 sfb->fb->fix.mmio_len = 0x00400000;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301429 smem_size = SM712_VIDEOMEMORYSIZE;
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301430 sfb->lfb = ioremap(mmio_base, mmio_addr);
Sudip Mukherjee4a012d32015-07-07 13:44:34 +05301431 if (!sfb->lfb) {
1432 dev_err(&pdev->dev,
1433 "%s: unable to map memory mapped IO!\n",
1434 sfb->fb->fix.id);
1435 err = -ENOMEM;
1436 goto failed_fb;
1437 }
1438
Sudip Mukherjee74121892015-02-03 20:23:33 +05301439 sfb->mmio = (smtc_regbaseaddress =
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301440 sfb->lfb + 0x00700000);
1441 sfb->dp_regs = sfb->lfb + 0x00408000;
1442 sfb->vp_regs = sfb->lfb + 0x0040c000;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301443 if (sfb->fb->var.bits_per_pixel == 32) {
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301444 sfb->lfb += big_addr;
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301445 dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301446 }
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301447
1448 /* set MCLK = 14.31818 * (0x16 / 0x2) */
1449 smtc_seqw(0x6a, 0x16);
1450 smtc_seqw(0x6b, 0x02);
1451 smtc_seqw(0x62, 0x3e);
1452 /* enable PCI burst */
1453 smtc_seqw(0x17, 0x20);
1454 /* enable word swap */
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301455 if (sfb->fb->var.bits_per_pixel == 32)
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301456 seqw17();
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301457 break;
1458 case 0x720:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301459 sfb->fb->fix.mmio_start = mmio_base;
1460 sfb->fb->fix.mmio_len = 0x00200000;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301461 smem_size = SM722_VIDEOMEMORYSIZE;
1462 sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
1463 sfb->lfb = sfb->dp_regs + 0x00200000;
Sudip Mukherjee74121892015-02-03 20:23:33 +05301464 sfb->mmio = (smtc_regbaseaddress =
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301465 sfb->dp_regs + 0x000c0000);
1466 sfb->vp_regs = sfb->dp_regs + 0x800;
1467
1468 smtc_seqw(0x62, 0xff);
1469 smtc_seqw(0x6a, 0x0d);
1470 smtc_seqw(0x6b, 0x02);
1471 break;
1472 default:
1473 dev_err(&pdev->dev,
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301474 "No valid Silicon Motion display chip was detected!\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301475
1476 goto failed_fb;
1477 }
1478
1479 /* can support 32 bpp */
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301480 if (15 == sfb->fb->var.bits_per_pixel)
1481 sfb->fb->var.bits_per_pixel = 16;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301482
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301483 sfb->fb->var.xres_virtual = sfb->fb->var.xres;
1484 sfb->fb->var.yres_virtual = sfb->fb->var.yres;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301485 err = smtc_map_smem(sfb, pdev, smem_size);
1486 if (err)
1487 goto failed;
1488
1489 smtcfb_setmode(sfb);
1490
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301491 err = register_framebuffer(info);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301492 if (err < 0)
1493 goto failed;
1494
1495 dev_info(&pdev->dev,
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301496 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301497 sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
1498 sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301499
1500 return 0;
1501
1502failed:
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301503 dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301504
1505 smtc_unmap_smem(sfb);
1506 smtc_unmap_mmio(sfb);
1507failed_fb:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301508 framebuffer_release(info);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301509
1510failed_free:
Sudip Mukherjeef30a7462015-03-28 14:33:40 +05301511 pci_release_region(pdev, 0);
1512
1513failed_regions:
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301514 pci_disable_device(pdev);
1515
1516 return err;
1517}
1518
1519/*
1520 * 0x710 (LynxEM)
1521 * 0x712 (LynxEM+)
1522 * 0x720 (Lynx3DM, Lynx3DM+)
1523 */
1524static const struct pci_device_id smtcfb_pci_table[] = {
1525 { PCI_DEVICE(0x126f, 0x710), },
1526 { PCI_DEVICE(0x126f, 0x712), },
1527 { PCI_DEVICE(0x126f, 0x720), },
1528 {0,}
1529};
1530
Sudip Mukherjee855fe6ea2015-03-24 16:22:24 +05301531MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
1532
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301533static void smtcfb_pci_remove(struct pci_dev *pdev)
1534{
1535 struct smtcfb_info *sfb;
1536
1537 sfb = pci_get_drvdata(pdev);
1538 smtc_unmap_smem(sfb);
1539 smtc_unmap_mmio(sfb);
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301540 unregister_framebuffer(sfb->fb);
1541 framebuffer_release(sfb->fb);
Sudip Mukherjeef30a7462015-03-28 14:33:40 +05301542 pci_release_region(pdev, 0);
Sudip Mukherjeef83e7752015-03-28 14:33:41 +05301543 pci_disable_device(pdev);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301544}
1545
Arnd Bergmann24ed78d2015-11-20 22:48:36 +01001546static int __maybe_unused smtcfb_pci_suspend(struct device *device)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301547{
1548 struct pci_dev *pdev = to_pci_dev(device);
1549 struct smtcfb_info *sfb;
1550
1551 sfb = pci_get_drvdata(pdev);
1552
1553 /* set the hw in sleep mode use external clock and self memory refresh
1554 * so that we can turn off internal PLLs later on
1555 */
1556 smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
1557 smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
1558
1559 console_lock();
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301560 fb_set_suspend(sfb->fb, 1);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301561 console_unlock();
1562
1563 /* additionally turn off all function blocks including internal PLLs */
1564 smtc_seqw(0x21, 0xff);
1565
1566 return 0;
1567}
1568
Arnd Bergmann24ed78d2015-11-20 22:48:36 +01001569static int __maybe_unused smtcfb_pci_resume(struct device *device)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301570{
1571 struct pci_dev *pdev = to_pci_dev(device);
1572 struct smtcfb_info *sfb;
1573
1574 sfb = pci_get_drvdata(pdev);
1575
1576 /* reinit hardware */
1577 sm7xx_init_hw();
1578 switch (sfb->chip_id) {
1579 case 0x710:
1580 case 0x712:
1581 /* set MCLK = 14.31818 * (0x16 / 0x2) */
1582 smtc_seqw(0x6a, 0x16);
1583 smtc_seqw(0x6b, 0x02);
1584 smtc_seqw(0x62, 0x3e);
1585 /* enable PCI burst */
1586 smtc_seqw(0x17, 0x20);
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301587 if (sfb->fb->var.bits_per_pixel == 32)
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301588 seqw17();
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301589 break;
1590 case 0x720:
1591 smtc_seqw(0x62, 0xff);
1592 smtc_seqw(0x6a, 0x0d);
1593 smtc_seqw(0x6b, 0x02);
1594 break;
1595 }
1596
1597 smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
1598 smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
1599
1600 smtcfb_setmode(sfb);
1601
1602 console_lock();
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301603 fb_set_suspend(sfb->fb, 0);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301604 console_unlock();
1605
1606 return 0;
1607}
1608
1609static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301610
1611static struct pci_driver smtcfb_driver = {
1612 .name = "smtcfb",
1613 .id_table = smtcfb_pci_table,
1614 .probe = smtcfb_pci_probe,
1615 .remove = smtcfb_pci_remove,
Arnd Bergmann24ed78d2015-11-20 22:48:36 +01001616 .driver.pm = &sm7xx_pm_ops,
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301617};
1618
Sudip Mukherjeec65434e2015-03-08 23:10:09 +05301619static int __init sm712fb_init(void)
1620{
Sudip Mukherjeec65434e2015-03-08 23:10:09 +05301621 char *option = NULL;
1622
1623 if (fb_get_options("sm712fb", &option))
1624 return -ENODEV;
1625 if (option && *option)
1626 mode_option = option;
Sudip Mukherjeec65434e2015-03-08 23:10:09 +05301627 sm7xx_vga_setup(mode_option);
1628
1629 return pci_register_driver(&smtcfb_driver);
1630}
1631
1632module_init(sm712fb_init);
1633
1634static void __exit sm712fb_exit(void)
1635{
1636 pci_unregister_driver(&smtcfb_driver);
1637}
1638
1639module_exit(sm712fb_exit);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301640
1641MODULE_AUTHOR("Siliconmotion ");
1642MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
1643MODULE_LICENSE("GPL");