blob: 7b1b0d8d27a7539f3e028a7c530f9c6a723ae983 [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/*
Lynn Lei0cdc07e2017-08-01 17:20:38 +020036 * Private structure
37 */
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +053038struct 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 },
Yifeng Li6053d3a2019-04-01 17:46:59 +0200533 { /* 1024 x 768 16Bpp 60Hz */
534 1024, 768, 16, 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 0x0F, 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 },
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530592 { /* mode#5: 1024 x 768 24Bpp 60Hz */
593 1024, 768, 24, 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, 0x30, 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#4: 1024 x 768 32Bpp 60Hz */
652 1024, 768, 32, 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, 0x3B, 0x0D, 0x09, 0x02,
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, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
701 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
702 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
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 },
710 { /* mode#6: 320 x 240 16Bpp 60Hz */
711 320, 240, 16, 60,
712 /* Init_MISC */
713 0xEB,
714 { /* Init_SR0_SR4 */
715 0x03, 0x01, 0x0F, 0x03, 0x0E,
716 },
717 { /* Init_SR10_SR24 */
718 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
719 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0xC4, 0x32, 0x02, 0x01, 0x01,
721 },
722 { /* Init_SR30_SR75 */
723 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
724 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
725 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
726 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
727 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
728 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
729 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
730 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
731 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
732 },
733 { /* Init_SR80_SR93 */
734 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
735 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
736 0x00, 0x00, 0x00, 0x00,
737 },
738 { /* Init_SRA0_SRAF */
739 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
740 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
741 },
742 { /* Init_GR00_GR08 */
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
744 0xFF,
745 },
746 { /* Init_AR00_AR14 */
747 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
748 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
749 0x41, 0x00, 0x0F, 0x00, 0x00,
750 },
751 { /* Init_CR00_CR18 */
752 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
753 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
755 0xFF,
756 },
757 { /* Init_CR30_CR4D */
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
759 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
760 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
761 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
762 },
763 { /* Init_CR90_CRA7 */
764 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
765 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
766 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
767 },
768 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530769
Sudip Mukherjeee09df482015-06-17 16:54:47 +0530770 { /* mode#8: 320 x 240 32Bpp 60Hz */
771 320, 240, 32, 60,
772 /* Init_MISC */
773 0xEB,
774 { /* Init_SR0_SR4 */
775 0x03, 0x01, 0x0F, 0x03, 0x0E,
776 },
777 { /* Init_SR10_SR24 */
778 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
779 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
780 0xC4, 0x32, 0x02, 0x01, 0x01,
781 },
782 { /* Init_SR30_SR75 */
783 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
784 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
785 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
786 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
787 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
788 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
789 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
790 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
791 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
792 },
793 { /* Init_SR80_SR93 */
794 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
795 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
796 0x00, 0x00, 0x00, 0x00,
797 },
798 { /* Init_SRA0_SRAF */
799 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
800 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
801 },
802 { /* Init_GR00_GR08 */
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
804 0xFF,
805 },
806 { /* Init_AR00_AR14 */
807 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
808 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
809 0x41, 0x00, 0x0F, 0x00, 0x00,
810 },
811 { /* Init_CR00_CR18 */
812 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
813 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
815 0xFF,
816 },
817 { /* Init_CR30_CR4D */
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
819 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
820 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
821 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
822 },
823 { /* Init_CR90_CRA7 */
824 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
825 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
826 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
827 },
828 },
Sudip Mukherjeedac7c1b2015-06-17 16:54:46 +0530829};
830
Max Perepelitsyn11862b32015-02-03 14:44:28 +0600831static struct screen_info smtc_scr_info;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530832
Sudip Mukherjeec65434e2015-03-08 23:10:09 +0530833static char *mode_option;
834
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530835/* process command line options, get vga parameter */
Sudip Mukherjee71ce7622015-03-08 23:10:11 +0530836static void __init sm7xx_vga_setup(char *options)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530837{
838 int i;
839
840 if (!options || !*options)
Sudip Mukherjee71ce7622015-03-08 23:10:11 +0530841 return;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530842
843 smtc_scr_info.lfb_width = 0;
844 smtc_scr_info.lfb_height = 0;
845 smtc_scr_info.lfb_depth = 0;
846
Lynn Leied10eab2017-08-01 17:20:38 +0200847 pr_debug("%s = %s\n", __func__, options);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530848
849 for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
850 if (strstr(options, vesa_mode_table[i].index)) {
851 smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width;
852 smtc_scr_info.lfb_height =
853 vesa_mode_table[i].lfb_height;
854 smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth;
Sudip Mukherjee71ce7622015-03-08 23:10:11 +0530855 return;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530856 }
857 }
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530858}
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530859
Lynn Lei14293212017-08-01 17:20:38 +0200860static void sm712_setpalette(int regno, unsigned int red, unsigned int green,
861 unsigned int blue, struct fb_info *info)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530862{
863 /* set bit 5:4 = 01 (write LCD RAM only) */
864 smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
865
866 smtc_mmiowb(regno, dac_reg);
867 smtc_mmiowb(red >> 10, dac_val);
868 smtc_mmiowb(green >> 10, dac_val);
869 smtc_mmiowb(blue >> 10, dac_val);
870}
871
872/* chan_to_field
873 *
874 * convert a colour value into a field position
875 *
876 * from pxafb.c
877 */
878
879static inline unsigned int chan_to_field(unsigned int chan,
880 struct fb_bitfield *bf)
881{
882 chan &= 0xffff;
883 chan >>= 16 - bf->length;
884 return chan << bf->offset;
885}
886
887static int smtc_blank(int blank_mode, struct fb_info *info)
888{
Yifeng Lif627caf2019-04-01 17:46:59 +0200889 struct smtcfb_info *sfb = info->par;
890
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530891 /* clear DPMS setting */
892 switch (blank_mode) {
893 case FB_BLANK_UNBLANK:
894 /* Screen On: HSync: On, VSync : On */
Yifeng Lif627caf2019-04-01 17:46:59 +0200895
896 switch (sfb->chip_id) {
897 case 0x710:
898 case 0x712:
899 smtc_seqw(0x6a, 0x16);
900 smtc_seqw(0x6b, 0x02);
Yifeng Li9dc20112019-04-02 17:14:10 +0200901 break;
Yifeng Lif627caf2019-04-01 17:46:59 +0200902 case 0x720:
903 smtc_seqw(0x6a, 0x0d);
904 smtc_seqw(0x6b, 0x02);
905 break;
906 }
907
908 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530909 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530910 smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
911 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530912 smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
Yifeng Lif627caf2019-04-01 17:46:59 +0200913 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530914 break;
915 case FB_BLANK_NORMAL:
916 /* Screen Off: HSync: On, VSync : On Soft blank */
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530917 smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
918 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
Yifeng Lif627caf2019-04-01 17:46:59 +0200919 smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
920 smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
921 smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
922 smtc_seqw(0x6a, 0x16);
923 smtc_seqw(0x6b, 0x02);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530924 break;
925 case FB_BLANK_VSYNC_SUSPEND:
926 /* Screen On: HSync: On, VSync : Off */
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530927 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
928 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
Yifeng Lif627caf2019-04-01 17:46:59 +0200929 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
930 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
931 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
932 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
933 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530934 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
Yifeng Lif627caf2019-04-01 17:46:59 +0200935 smtc_seqw(0x6a, 0x0c);
936 smtc_seqw(0x6b, 0x02);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530937 break;
938 case FB_BLANK_HSYNC_SUSPEND:
939 /* Screen On: HSync: Off, VSync : On */
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530940 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
941 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
Yifeng Lif627caf2019-04-01 17:46:59 +0200942 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
943 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
944 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
945 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
946 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530947 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
Yifeng Lif627caf2019-04-01 17:46:59 +0200948 smtc_seqw(0x6a, 0x0c);
949 smtc_seqw(0x6b, 0x02);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530950 break;
951 case FB_BLANK_POWERDOWN:
952 /* Screen On: HSync: Off, VSync : Off */
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530953 smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
954 smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
Yifeng Lif627caf2019-04-01 17:46:59 +0200955 smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
956 smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
957 smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
958 smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
959 smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530960 smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
Yifeng Lif627caf2019-04-01 17:46:59 +0200961 smtc_seqw(0x6a, 0x0c);
962 smtc_seqw(0x6b, 0x02);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530963 break;
964 default:
965 return -EINVAL;
966 }
967
968 return 0;
969}
970
Lynn Lei14293212017-08-01 17:20:38 +0200971static int smtc_setcolreg(unsigned int regno, unsigned int red,
972 unsigned int green, unsigned int blue,
973 unsigned int trans, struct fb_info *info)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530974{
975 struct smtcfb_info *sfb;
976 u32 val;
977
978 sfb = info->par;
979
980 if (regno > 255)
981 return 1;
982
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +0530983 switch (sfb->fb->fix.visual) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +0530984 case FB_VISUAL_DIRECTCOLOR:
985 case FB_VISUAL_TRUECOLOR:
986 /*
987 * 16/32 bit true-colour, use pseudo-palette for 16 base color
988 */
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530989 if (regno >= 16)
990 break;
991 if (sfb->fb->var.bits_per_pixel == 16) {
992 u32 *pal = sfb->fb->pseudo_palette;
Sudip Mukherjeea1f6da62015-01-19 13:41:03 +0530993
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530994 val = chan_to_field(red, &sfb->fb->var.red);
995 val |= chan_to_field(green, &sfb->fb->var.green);
996 val |= chan_to_field(blue, &sfb->fb->var.blue);
Sudip Mukherjee87bf7922015-07-15 13:59:45 +0530997 pal[regno] = pal_rgb(red, green, blue, val);
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +0530998 } else {
999 u32 *pal = sfb->fb->pseudo_palette;
Sudip Mukherjeea1f6da62015-01-19 13:41:03 +05301000
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301001 val = chan_to_field(red, &sfb->fb->var.red);
1002 val |= chan_to_field(green, &sfb->fb->var.green);
1003 val |= chan_to_field(blue, &sfb->fb->var.blue);
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301004 pal[regno] = big_swap(val);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301005 }
1006 break;
1007
1008 case FB_VISUAL_PSEUDOCOLOR:
1009 /* color depth 8 bit */
1010 sm712_setpalette(regno, red, green, blue, info);
1011 break;
1012
1013 default:
1014 return 1; /* unknown type */
1015 }
1016
1017 return 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301018}
1019
Sudip Mukherjeef5daff32015-06-17 16:54:44 +05301020static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
1021 size_t count, loff_t *ppos)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301022{
1023 unsigned long p = *ppos;
1024
1025 u32 *buffer, *dst;
1026 u32 __iomem *src;
1027 int c, i, cnt = 0, err = 0;
1028 unsigned long total_size;
1029
1030 if (!info || !info->screen_base)
1031 return -ENODEV;
1032
1033 if (info->state != FBINFO_STATE_RUNNING)
1034 return -EPERM;
1035
1036 total_size = info->screen_size;
1037
1038 if (total_size == 0)
1039 total_size = info->fix.smem_len;
1040
1041 if (p >= total_size)
1042 return 0;
1043
1044 if (count >= total_size)
1045 count = total_size;
1046
1047 if (count + p > total_size)
1048 count = total_size - p;
1049
1050 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
1051 if (!buffer)
1052 return -ENOMEM;
1053
Sudip Mukherjee3e4b5592015-06-17 16:54:43 +05301054 src = (u32 __iomem *)(info->screen_base + p);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301055
1056 if (info->fbops->fb_sync)
1057 info->fbops->fb_sync(info);
1058
1059 while (count) {
1060 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1061 dst = buffer;
1062 for (i = c >> 2; i--;) {
1063 *dst = fb_readl(src++);
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301064 *dst = big_swap(*dst);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301065 dst++;
1066 }
1067 if (c & 3) {
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301068 u8 *dst8 = (u8 *)dst;
1069 u8 __iomem *src8 = (u8 __iomem *)src;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301070
1071 for (i = c & 3; i--;) {
1072 if (i & 1) {
1073 *dst8++ = fb_readb(++src8);
1074 } else {
1075 *dst8++ = fb_readb(--src8);
1076 src8 += 2;
1077 }
1078 }
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301079 src = (u32 __iomem *)src8;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301080 }
1081
1082 if (copy_to_user(buf, buffer, c)) {
1083 err = -EFAULT;
1084 break;
1085 }
1086 *ppos += c;
1087 buf += c;
1088 cnt += c;
1089 count -= c;
1090 }
1091
1092 kfree(buffer);
1093
1094 return (err) ? err : cnt;
1095}
1096
Sudip Mukherjeef5daff32015-06-17 16:54:44 +05301097static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
1098 size_t count, loff_t *ppos)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301099{
1100 unsigned long p = *ppos;
1101
1102 u32 *buffer, *src;
1103 u32 __iomem *dst;
1104 int c, i, cnt = 0, err = 0;
1105 unsigned long total_size;
1106
1107 if (!info || !info->screen_base)
1108 return -ENODEV;
1109
1110 if (info->state != FBINFO_STATE_RUNNING)
1111 return -EPERM;
1112
1113 total_size = info->screen_size;
1114
1115 if (total_size == 0)
1116 total_size = info->fix.smem_len;
1117
1118 if (p > total_size)
1119 return -EFBIG;
1120
1121 if (count > total_size) {
1122 err = -EFBIG;
1123 count = total_size;
1124 }
1125
1126 if (count + p > total_size) {
1127 if (!err)
1128 err = -ENOSPC;
1129
1130 count = total_size - p;
1131 }
1132
1133 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
1134 if (!buffer)
1135 return -ENOMEM;
1136
Sudip Mukherjee3e4b5592015-06-17 16:54:43 +05301137 dst = (u32 __iomem *)(info->screen_base + p);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301138
1139 if (info->fbops->fb_sync)
1140 info->fbops->fb_sync(info);
1141
1142 while (count) {
1143 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
1144 src = buffer;
1145
1146 if (copy_from_user(src, buf, c)) {
1147 err = -EFAULT;
1148 break;
1149 }
1150
1151 for (i = c >> 2; i--;) {
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301152 fb_writel(big_swap(*src), dst++);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301153 src++;
1154 }
1155 if (c & 3) {
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301156 u8 *src8 = (u8 *)src;
1157 u8 __iomem *dst8 = (u8 __iomem *)dst;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301158
1159 for (i = c & 3; i--;) {
1160 if (i & 1) {
1161 fb_writeb(*src8++, ++dst8);
1162 } else {
1163 fb_writeb(*src8++, --dst8);
1164 dst8 += 2;
1165 }
1166 }
Sudip Mukherjee53f54a42015-01-19 13:41:04 +05301167 dst = (u32 __iomem *)dst8;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301168 }
1169
1170 *ppos += c;
1171 buf += c;
1172 cnt += c;
1173 count -= c;
1174 }
1175
1176 kfree(buffer);
1177
1178 return (cnt) ? cnt : err;
1179}
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301180
1181static void sm7xx_set_timing(struct smtcfb_info *sfb)
1182{
1183 int i = 0, j = 0;
Sudip Mukherjeec4d50762015-02-03 20:23:34 +05301184 u32 m_nscreenstride;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301185
1186 dev_dbg(&sfb->pdev->dev,
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301187 "sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
1188 sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301189
Sudip Mukherjee7caf4632015-06-17 16:54:41 +05301190 for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301191 if (vgamode[j].mmsizex != sfb->width ||
1192 vgamode[j].mmsizey != sfb->height ||
1193 vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
1194 vgamode[j].hz != sfb->hz)
1195 continue;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301196
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301197 dev_dbg(&sfb->pdev->dev,
1198 "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
1199 vgamode[j].mmsizex, vgamode[j].mmsizey,
1200 vgamode[j].bpp, vgamode[j].hz);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301201
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301202 dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301203
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301204 smtc_mmiowb(0x0, 0x3c6);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301205
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301206 smtc_seqw(0, 0x1);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301207
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301208 smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301209
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301210 /* init SEQ register SR00 - SR04 */
1211 for (i = 0; i < SIZE_SR00_SR04; i++)
1212 smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301213
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301214 /* init SEQ register SR10 - SR24 */
1215 for (i = 0; i < SIZE_SR10_SR24; i++)
1216 smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301217
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301218 /* init SEQ register SR30 - SR75 */
1219 for (i = 0; i < SIZE_SR30_SR75; i++)
Yifeng Li54811152019-04-01 17:46:58 +02001220 if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
Yifeng Lidcf90702019-04-01 17:46:58 +02001221 (i + 0x30) != 0x6a && (i + 0x30) != 0x6b &&
1222 (i + 0x30) != 0x70 && (i + 0x30) != 0x71 &&
1223 (i + 0x30) != 0x74 && (i + 0x30) != 0x75)
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301224 smtc_seqw(i + 0x30,
1225 vgamode[j].init_sr30_sr75[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301226
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301227 /* init SEQ register SR80 - SR93 */
1228 for (i = 0; i < SIZE_SR80_SR93; i++)
1229 smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301230
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301231 /* init SEQ register SRA0 - SRAF */
1232 for (i = 0; i < SIZE_SRA0_SRAF; i++)
1233 smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301234
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301235 /* init Graphic register GR00 - GR08 */
1236 for (i = 0; i < SIZE_GR00_GR08; i++)
1237 smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301238
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301239 /* init Attribute register AR00 - AR14 */
1240 for (i = 0; i < SIZE_AR00_AR14; i++)
1241 smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301242
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301243 /* init CRTC register CR00 - CR18 */
1244 for (i = 0; i < SIZE_CR00_CR18; i++)
1245 smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301246
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301247 /* init CRTC register CR30 - CR4D */
Yifeng Li80690532019-04-01 17:46:58 +02001248 for (i = 0; i < SIZE_CR30_CR4D; i++) {
1249 if ((i + 0x30) >= 0x3B && (i + 0x30) <= 0x3F)
1250 /* side-effect, don't write to CR3B-CR3F */
1251 continue;
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301252 smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
Yifeng Li80690532019-04-01 17:46:58 +02001253 }
Sudip Mukherjee36fa82a2015-06-17 16:54:45 +05301254
1255 /* init CRTC register CR90 - CRA7 */
1256 for (i = 0; i < SIZE_CR90_CRA7; i++)
1257 smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301258 }
1259 smtc_mmiowb(0x67, 0x3c2);
1260
1261 /* set VPR registers */
1262 writel(0x0, sfb->vp_regs + 0x0C);
1263 writel(0x0, sfb->vp_regs + 0x40);
1264
1265 /* set data width */
Sudip Mukherjeef5daff32015-06-17 16:54:44 +05301266 m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301267 switch (sfb->fb->var.bits_per_pixel) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301268 case 8:
1269 writel(0x0, sfb->vp_regs + 0x0);
1270 break;
1271 case 16:
1272 writel(0x00020000, sfb->vp_regs + 0x0);
1273 break;
1274 case 24:
1275 writel(0x00040000, sfb->vp_regs + 0x0);
1276 break;
1277 case 32:
1278 writel(0x00030000, sfb->vp_regs + 0x0);
1279 break;
1280 }
Sudip Mukherjee3e4b5592015-06-17 16:54:43 +05301281 writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301282 sfb->vp_regs + 0x10);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301283}
1284
1285static void smtc_set_timing(struct smtcfb_info *sfb)
1286{
1287 switch (sfb->chip_id) {
1288 case 0x710:
1289 case 0x712:
1290 case 0x720:
1291 sm7xx_set_timing(sfb);
1292 break;
1293 }
1294}
1295
1296static void smtcfb_setmode(struct smtcfb_info *sfb)
1297{
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301298 switch (sfb->fb->var.bits_per_pixel) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301299 case 32:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301300 sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
1301 sfb->fb->fix.line_length = sfb->fb->var.xres * 4;
1302 sfb->fb->var.red.length = 8;
1303 sfb->fb->var.green.length = 8;
1304 sfb->fb->var.blue.length = 8;
1305 sfb->fb->var.red.offset = 16;
1306 sfb->fb->var.green.offset = 8;
1307 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301308 break;
1309 case 24:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301310 sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
1311 sfb->fb->fix.line_length = sfb->fb->var.xres * 3;
1312 sfb->fb->var.red.length = 8;
1313 sfb->fb->var.green.length = 8;
1314 sfb->fb->var.blue.length = 8;
1315 sfb->fb->var.red.offset = 16;
1316 sfb->fb->var.green.offset = 8;
1317 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301318 break;
1319 case 8:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301320 sfb->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
1321 sfb->fb->fix.line_length = sfb->fb->var.xres;
1322 sfb->fb->var.red.length = 3;
1323 sfb->fb->var.green.length = 3;
1324 sfb->fb->var.blue.length = 2;
1325 sfb->fb->var.red.offset = 5;
1326 sfb->fb->var.green.offset = 2;
1327 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301328 break;
1329 case 16:
1330 default:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301331 sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
1332 sfb->fb->fix.line_length = sfb->fb->var.xres * 2;
1333 sfb->fb->var.red.length = 5;
1334 sfb->fb->var.green.length = 6;
1335 sfb->fb->var.blue.length = 5;
1336 sfb->fb->var.red.offset = 11;
1337 sfb->fb->var.green.offset = 5;
1338 sfb->fb->var.blue.offset = 0;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301339 break;
1340 }
1341
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301342 sfb->width = sfb->fb->var.xres;
1343 sfb->height = sfb->fb->var.yres;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301344 sfb->hz = 60;
1345 smtc_set_timing(sfb);
1346}
1347
1348static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1349{
1350 /* sanity checks */
1351 if (var->xres_virtual < var->xres)
1352 var->xres_virtual = var->xres;
1353
1354 if (var->yres_virtual < var->yres)
1355 var->yres_virtual = var->yres;
1356
1357 /* set valid default bpp */
1358 if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) &&
1359 (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
1360 var->bits_per_pixel = 16;
1361
1362 return 0;
1363}
1364
1365static int smtc_set_par(struct fb_info *info)
1366{
1367 smtcfb_setmode(info->par);
1368
1369 return 0;
1370}
1371
1372static struct fb_ops smtcfb_ops = {
1373 .owner = THIS_MODULE,
1374 .fb_check_var = smtc_check_var,
1375 .fb_set_par = smtc_set_par,
1376 .fb_setcolreg = smtc_setcolreg,
1377 .fb_blank = smtc_blank,
1378 .fb_fillrect = cfb_fillrect,
1379 .fb_imageblit = cfb_imageblit,
1380 .fb_copyarea = cfb_copyarea,
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301381 .fb_read = smtcfb_read,
1382 .fb_write = smtcfb_write,
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301383};
1384
1385/*
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301386 * Unmap in the memory mapped IO registers
1387 */
1388
1389static void smtc_unmap_mmio(struct smtcfb_info *sfb)
1390{
Sudip Mukherjee74121892015-02-03 20:23:33 +05301391 if (sfb && smtc_regbaseaddress)
1392 smtc_regbaseaddress = NULL;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301393}
1394
1395/*
1396 * Map in the screen memory
1397 */
1398
1399static int smtc_map_smem(struct smtcfb_info *sfb,
Sudip Mukherjeef049a522015-01-19 13:41:06 +05301400 struct pci_dev *pdev, u_long smem_len)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301401{
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301402 sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301403
Yifeng Li9e0e5992019-04-01 17:46:59 +02001404 if (sfb->chip_id == 0x720)
1405 /* on SM720, the framebuffer starts at the 1 MB offset */
1406 sfb->fb->fix.smem_start += 0x00200000;
1407
1408 /* XXX: is it safe for SM720 on Big-Endian? */
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301409 if (sfb->fb->var.bits_per_pixel == 32)
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301410 sfb->fb->fix.smem_start += big_addr;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301411
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301412 sfb->fb->fix.smem_len = smem_len;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301413
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301414 sfb->fb->screen_base = sfb->lfb;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301415
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301416 if (!sfb->fb->screen_base) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301417 dev_err(&pdev->dev,
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301418 "%s: unable to map screen memory\n", sfb->fb->fix.id);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301419 return -ENOMEM;
1420 }
1421
1422 return 0;
1423}
1424
1425/*
1426 * Unmap in the screen memory
1427 *
1428 */
1429static void smtc_unmap_smem(struct smtcfb_info *sfb)
1430{
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301431 if (sfb && sfb->fb->screen_base) {
1432 iounmap(sfb->fb->screen_base);
1433 sfb->fb->screen_base = NULL;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301434 }
1435}
1436
1437/*
1438 * We need to wake up the device and make sure its in linear memory mode.
1439 */
1440static inline void sm7xx_init_hw(void)
1441{
1442 outb_p(0x18, 0x3c4);
1443 outb_p(0x11, 0x3c5);
1444}
1445
Yifeng Li9e0e5992019-04-01 17:46:59 +02001446static u_long sm7xx_vram_probe(struct smtcfb_info *sfb)
1447{
1448 u8 vram;
1449
1450 switch (sfb->chip_id) {
1451 case 0x710:
1452 case 0x712:
1453 /*
1454 * Assume SM712 graphics chip has 4MB VRAM.
1455 *
1456 * FIXME: SM712 can have 2MB VRAM, which is used on earlier
1457 * laptops, such as IBM Thinkpad 240X. This driver would
1458 * probably crash on those machines. If anyone gets one of
1459 * those and is willing to help, run "git blame" and send me
1460 * an E-mail.
1461 */
1462 return 0x00400000;
1463 case 0x720:
1464 outb_p(0x76, 0x3c4);
1465 vram = inb_p(0x3c5) >> 6;
1466
1467 if (vram == 0x00)
1468 return 0x00800000; /* 8 MB */
1469 else if (vram == 0x01)
1470 return 0x01000000; /* 16 MB */
1471 else if (vram == 0x02)
1472 return 0x00400000; /* illegal, fallback to 4 MB */
1473 else if (vram == 0x03)
1474 return 0x00400000; /* 4 MB */
1475 }
1476 return 0; /* unknown hardware */
1477}
1478
Yifeng Li4ed7d2c2019-04-01 17:46:59 +02001479static void sm7xx_resolution_probe(struct smtcfb_info *sfb)
1480{
1481 /* get mode parameter from smtc_scr_info */
1482 if (smtc_scr_info.lfb_width != 0) {
1483 sfb->fb->var.xres = smtc_scr_info.lfb_width;
1484 sfb->fb->var.yres = smtc_scr_info.lfb_height;
1485 sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
1486 goto final;
1487 }
1488
1489 /*
1490 * No parameter, default resolution is 1024x768-16.
1491 *
1492 * FIXME: earlier laptops, such as IBM Thinkpad 240X, has a 800x600
1493 * panel, also see the comments about Thinkpad 240X above.
1494 */
1495 sfb->fb->var.xres = SCREEN_X_RES;
1496 sfb->fb->var.yres = SCREEN_Y_RES_PC;
1497 sfb->fb->var.bits_per_pixel = SCREEN_BPP;
1498
1499#ifdef CONFIG_MIPS
1500 /*
1501 * Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
1502 * target platform of this driver, but nearly all old x86 laptops have
1503 * 1024x768. Lighting 768 panels using 600's timings would partially
1504 * garble the display, so we don't want that. But it's not possible to
1505 * distinguish them reliably.
1506 *
1507 * So we change the default to 768, but keep 600 as-is on MIPS.
1508 */
1509 sfb->fb->var.yres = SCREEN_Y_RES_NETBOOK;
1510#endif
1511
1512final:
1513 big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
1514}
1515
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301516static int smtcfb_pci_probe(struct pci_dev *pdev,
Sudip Mukherjeef049a522015-01-19 13:41:06 +05301517 const struct pci_device_id *ent)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301518{
1519 struct smtcfb_info *sfb;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301520 struct fb_info *info;
Yifeng Li9e0e5992019-04-01 17:46:59 +02001521 u_long smem_size;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301522 int err;
1523 unsigned long mmio_base;
1524
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301525 dev_info(&pdev->dev, "Silicon Motion display driver.\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301526
1527 err = pci_enable_device(pdev); /* enable SMTC chip */
1528 if (err)
1529 return err;
1530
Sudip Mukherjeef30a7462015-03-28 14:33:40 +05301531 err = pci_request_region(pdev, 0, "sm7xxfb");
1532 if (err < 0) {
1533 dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
1534 goto failed_regions;
1535 }
1536
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301537 sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
1538
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301539 info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
1540 if (!info) {
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301541 err = -ENOMEM;
1542 goto failed_free;
1543 }
1544
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301545 sfb = info->par;
1546 sfb->fb = info;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301547 sfb->chip_id = ent->device;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301548 sfb->pdev = pdev;
1549 info->flags = FBINFO_FLAG_DEFAULT;
1550 info->fbops = &smtcfb_ops;
1551 info->fix = smtcfb_fix;
1552 info->var = smtcfb_var;
1553 info->pseudo_palette = sfb->colreg;
1554 info->par = sfb;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301555
1556 pci_set_drvdata(pdev, sfb);
1557
1558 sm7xx_init_hw();
1559
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301560 /* Map address and memory detection */
1561 mmio_base = pci_resource_start(pdev, 0);
1562 pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
1563
Yifeng Li9e0e5992019-04-01 17:46:59 +02001564 smem_size = sm7xx_vram_probe(sfb);
1565 dev_info(&pdev->dev, "%lu MiB of VRAM detected.\n",
1566 smem_size / 1048576);
1567
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301568 switch (sfb->chip_id) {
1569 case 0x710:
1570 case 0x712:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301571 sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
1572 sfb->fb->fix.mmio_len = 0x00400000;
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301573 sfb->lfb = ioremap(mmio_base, mmio_addr);
Sudip Mukherjee4a012d32015-07-07 13:44:34 +05301574 if (!sfb->lfb) {
1575 dev_err(&pdev->dev,
1576 "%s: unable to map memory mapped IO!\n",
1577 sfb->fb->fix.id);
1578 err = -ENOMEM;
1579 goto failed_fb;
1580 }
1581
Sudip Mukherjee74121892015-02-03 20:23:33 +05301582 sfb->mmio = (smtc_regbaseaddress =
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301583 sfb->lfb + 0x00700000);
1584 sfb->dp_regs = sfb->lfb + 0x00408000;
1585 sfb->vp_regs = sfb->lfb + 0x0040c000;
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301586 if (sfb->fb->var.bits_per_pixel == 32) {
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301587 sfb->lfb += big_addr;
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301588 dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301589 }
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301590
1591 /* set MCLK = 14.31818 * (0x16 / 0x2) */
1592 smtc_seqw(0x6a, 0x16);
1593 smtc_seqw(0x6b, 0x02);
1594 smtc_seqw(0x62, 0x3e);
1595 /* enable PCI burst */
1596 smtc_seqw(0x17, 0x20);
1597 /* enable word swap */
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301598 if (sfb->fb->var.bits_per_pixel == 32)
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301599 seqw17();
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301600 break;
1601 case 0x720:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301602 sfb->fb->fix.mmio_start = mmio_base;
1603 sfb->fb->fix.mmio_len = 0x00200000;
Yifeng Li9e0e5992019-04-01 17:46:59 +02001604 sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301605 sfb->lfb = sfb->dp_regs + 0x00200000;
Sudip Mukherjee74121892015-02-03 20:23:33 +05301606 sfb->mmio = (smtc_regbaseaddress =
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301607 sfb->dp_regs + 0x000c0000);
1608 sfb->vp_regs = sfb->dp_regs + 0x800;
1609
1610 smtc_seqw(0x62, 0xff);
1611 smtc_seqw(0x6a, 0x0d);
1612 smtc_seqw(0x6b, 0x02);
1613 break;
1614 default:
1615 dev_err(&pdev->dev,
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301616 "No valid Silicon Motion display chip was detected!\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301617
1618 goto failed_fb;
1619 }
1620
Yifeng Li4ed7d2c2019-04-01 17:46:59 +02001621 /* probe and decide resolution */
1622 sm7xx_resolution_probe(sfb);
1623
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301624 /* can support 32 bpp */
Lynn Lei5bbee782017-08-01 17:20:38 +02001625 if (sfb->fb->var.bits_per_pixel == 15)
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301626 sfb->fb->var.bits_per_pixel = 16;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301627
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301628 sfb->fb->var.xres_virtual = sfb->fb->var.xres;
1629 sfb->fb->var.yres_virtual = sfb->fb->var.yres;
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301630 err = smtc_map_smem(sfb, pdev, smem_size);
1631 if (err)
1632 goto failed;
1633
Yifeng Liec1587d2019-04-01 17:46:59 +02001634 /*
1635 * The screen would be temporarily garbled when sm712fb takes over
1636 * vesafb or VGA text mode. Zero the framebuffer.
1637 */
1638 memset_io(sfb->lfb, 0, sfb->fb->fix.smem_len);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301639
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301640 err = register_framebuffer(info);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301641 if (err < 0)
1642 goto failed;
1643
1644 dev_info(&pdev->dev,
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301645 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301646 sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
1647 sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301648
1649 return 0;
1650
1651failed:
Sudip Mukherjeec32305b2015-06-17 16:54:42 +05301652 dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301653
1654 smtc_unmap_smem(sfb);
1655 smtc_unmap_mmio(sfb);
1656failed_fb:
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301657 framebuffer_release(info);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301658
1659failed_free:
Sudip Mukherjeef30a7462015-03-28 14:33:40 +05301660 pci_release_region(pdev, 0);
1661
1662failed_regions:
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301663 pci_disable_device(pdev);
1664
1665 return err;
1666}
1667
1668/*
1669 * 0x710 (LynxEM)
1670 * 0x712 (LynxEM+)
1671 * 0x720 (Lynx3DM, Lynx3DM+)
1672 */
1673static const struct pci_device_id smtcfb_pci_table[] = {
1674 { PCI_DEVICE(0x126f, 0x710), },
1675 { PCI_DEVICE(0x126f, 0x712), },
1676 { PCI_DEVICE(0x126f, 0x720), },
1677 {0,}
1678};
1679
Sudip Mukherjee855fe6ea2015-03-24 16:22:24 +05301680MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
1681
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301682static void smtcfb_pci_remove(struct pci_dev *pdev)
1683{
1684 struct smtcfb_info *sfb;
1685
1686 sfb = pci_get_drvdata(pdev);
1687 smtc_unmap_smem(sfb);
1688 smtc_unmap_mmio(sfb);
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301689 unregister_framebuffer(sfb->fb);
1690 framebuffer_release(sfb->fb);
Sudip Mukherjeef30a7462015-03-28 14:33:40 +05301691 pci_release_region(pdev, 0);
Sudip Mukherjeef83e7752015-03-28 14:33:41 +05301692 pci_disable_device(pdev);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301693}
1694
Arnd Bergmann24ed78d2015-11-20 22:48:36 +01001695static int __maybe_unused smtcfb_pci_suspend(struct device *device)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301696{
1697 struct pci_dev *pdev = to_pci_dev(device);
1698 struct smtcfb_info *sfb;
1699
1700 sfb = pci_get_drvdata(pdev);
1701
1702 /* set the hw in sleep mode use external clock and self memory refresh
1703 * so that we can turn off internal PLLs later on
1704 */
1705 smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
1706 smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
1707
1708 console_lock();
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301709 fb_set_suspend(sfb->fb, 1);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301710 console_unlock();
1711
1712 /* additionally turn off all function blocks including internal PLLs */
1713 smtc_seqw(0x21, 0xff);
1714
1715 return 0;
1716}
1717
Arnd Bergmann24ed78d2015-11-20 22:48:36 +01001718static int __maybe_unused smtcfb_pci_resume(struct device *device)
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301719{
1720 struct pci_dev *pdev = to_pci_dev(device);
1721 struct smtcfb_info *sfb;
1722
1723 sfb = pci_get_drvdata(pdev);
1724
1725 /* reinit hardware */
1726 sm7xx_init_hw();
1727 switch (sfb->chip_id) {
1728 case 0x710:
1729 case 0x712:
1730 /* set MCLK = 14.31818 * (0x16 / 0x2) */
1731 smtc_seqw(0x6a, 0x16);
1732 smtc_seqw(0x6b, 0x02);
1733 smtc_seqw(0x62, 0x3e);
1734 /* enable PCI burst */
1735 smtc_seqw(0x17, 0x20);
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301736 if (sfb->fb->var.bits_per_pixel == 32)
Sudip Mukherjee87bf7922015-07-15 13:59:45 +05301737 seqw17();
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301738 break;
1739 case 0x720:
1740 smtc_seqw(0x62, 0xff);
1741 smtc_seqw(0x6a, 0x0d);
1742 smtc_seqw(0x6b, 0x02);
1743 break;
1744 }
1745
1746 smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
1747 smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
1748
1749 smtcfb_setmode(sfb);
1750
1751 console_lock();
Sudip Mukherjeecd14ad82015-04-23 19:08:16 +05301752 fb_set_suspend(sfb->fb, 0);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301753 console_unlock();
1754
1755 return 0;
1756}
1757
1758static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301759
1760static struct pci_driver smtcfb_driver = {
1761 .name = "smtcfb",
1762 .id_table = smtcfb_pci_table,
1763 .probe = smtcfb_pci_probe,
1764 .remove = smtcfb_pci_remove,
Arnd Bergmann24ed78d2015-11-20 22:48:36 +01001765 .driver.pm = &sm7xx_pm_ops,
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301766};
1767
Sudip Mukherjeec65434e2015-03-08 23:10:09 +05301768static int __init sm712fb_init(void)
1769{
Sudip Mukherjeec65434e2015-03-08 23:10:09 +05301770 char *option = NULL;
1771
1772 if (fb_get_options("sm712fb", &option))
1773 return -ENODEV;
1774 if (option && *option)
1775 mode_option = option;
Sudip Mukherjeec65434e2015-03-08 23:10:09 +05301776 sm7xx_vga_setup(mode_option);
1777
1778 return pci_register_driver(&smtcfb_driver);
1779}
1780
1781module_init(sm712fb_init);
1782
1783static void __exit sm712fb_exit(void)
1784{
1785 pci_unregister_driver(&smtcfb_driver);
1786}
1787
1788module_exit(sm712fb_exit);
Sudip Mukherjeea8e8f892015-01-19 13:41:00 +05301789
1790MODULE_AUTHOR("Siliconmotion ");
1791MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
1792MODULE_LICENSE("GPL");