aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaud Patard (Rtp <arnaud.patard@rtp-net.org>2006-12-08 05:40:23 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:29:05 -0500
commit357b819dda03e642f9c2d737596ad6cdc0022c00 (patch)
tree0d4639e901e07bc04ee9800fd6d2a636b0f02429
parentc25623f5540694ba70af272170d67f1411be97b1 (diff)
[PATCH] s3c2410fb: Add support for STN displays
This patch adds support for stn displays on the s3c2410 arm SoC. The LCD type is choosen by a new field in the s3c2410fb_mach_info structure and its value is the value of the PNRMODE bits. This worth to be noted as a value of 0 means that you configure a 4 bit dual scan stn display. Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org> Cc: "Antonino A. Daplas" <adaplas@pol.net> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Ben Dooks <ben-linux@fluff.org> Acked-by: James Simmons <jsimmons@infradead.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/video/s3c2410fb.c213
-rw-r--r--include/asm-arm/arch-s3c2410/fb.h3
2 files changed, 173 insertions, 43 deletions
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 59407343cc73..ccef56d0c157 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -131,7 +131,7 @@ static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
131 saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8; 131 saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
132 saddr2>>= 1; 132 saddr2>>= 1;
133 133
134 saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres); 134 saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff);
135 135
136 dprintk("LCDSADDR1 = 0x%08lx\n", saddr1); 136 dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
137 dprintk("LCDSADDR2 = 0x%08lx\n", saddr2); 137 dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
@@ -199,28 +199,86 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
199 var->bits_per_pixel = fbi->mach_info->bpp.min; 199 var->bits_per_pixel = fbi->mach_info->bpp.min;
200 200
201 /* set r/g/b positions */ 201 /* set r/g/b positions */
202 switch (var->bits_per_pixel) {
203 case 1:
204 case 2:
205 case 4:
206 var->red.offset = 0;
207 var->red.length = var->bits_per_pixel;
208 var->green = var->red;
209 var->blue = var->red;
210 var->transp.offset = 0;
211 var->transp.length = 0;
212 break;
213 case 8:
214 if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) {
215 /* 8 bpp 332 */
216 var->red.length = 3;
217 var->red.offset = 5;
218 var->green.length = 3;
219 var->green.offset = 2;
220 var->blue.length = 2;
221 var->blue.offset = 0;
222 var->transp.length = 0;
223 } else {
224 var->red.offset = 0;
225 var->red.length = var->bits_per_pixel;
226 var->green = var->red;
227 var->blue = var->red;
228 var->transp.offset = 0;
229 var->transp.length = 0;
230 }
231 break;
232 case 12:
233 /* 12 bpp 444 */
234 var->red.length = 4;
235 var->red.offset = 8;
236 var->green.length = 4;
237 var->green.offset = 4;
238 var->blue.length = 4;
239 var->blue.offset = 0;
240 var->transp.length = 0;
241 break;
242
243 default:
244 case 16:
245 if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) {
246 /* 16 bpp, 565 format */
247 var->red.offset = 11;
248 var->green.offset = 5;
249 var->blue.offset = 0;
250 var->red.length = 5;
251 var->green.length = 6;
252 var->blue.length = 5;
253 var->transp.length = 0;
254 } else {
255 /* 16 bpp, 5551 format */
256 var->red.offset = 11;
257 var->green.offset = 6;
258 var->blue.offset = 1;
259 var->red.length = 5;
260 var->green.length = 5;
261 var->blue.length = 5;
262 var->transp.length = 0;
263 }
264 break;
265 case 24:
266 /* 24 bpp 888 */
267 var->red.length = 8;
268 var->red.offset = 16;
269 var->green.length = 8;
270 var->green.offset = 8;
271 var->blue.length = 8;
272 var->blue.offset = 0;
273 var->transp.length = 0;
274 break;
202 275
203 if (var->bits_per_pixel == 16) {
204 var->red.offset = 11;
205 var->green.offset = 5;
206 var->blue.offset = 0;
207 var->red.length = 5;
208 var->green.length = 6;
209 var->blue.length = 5;
210 var->transp.length = 0;
211 } else {
212 var->red.length = var->bits_per_pixel;
213 var->red.offset = 0;
214 var->green.length = var->bits_per_pixel;
215 var->green.offset = 0;
216 var->blue.length = var->bits_per_pixel;
217 var->blue.offset = 0;
218 var->transp.length = 0;
219 }
220 276
277 }
221 return 0; 278 return 0;
222} 279}
223 280
281
224/* s3c2410fb_activate_var 282/* s3c2410fb_activate_var
225 * 283 *
226 * activate (set) the controller from the given framebuffer 284 * activate (set) the controller from the given framebuffer
@@ -230,29 +288,61 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
230static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, 288static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
231 struct fb_var_screeninfo *var) 289 struct fb_var_screeninfo *var)
232{ 290{
291 int hs;
292
233 fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; 293 fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
294 fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT;
234 295
235 dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres); 296 dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres);
236 dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres); 297 dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres);
237 dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel); 298 dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel);
238 299
239 switch (var->bits_per_pixel) { 300 fbi->regs.lcdcon1 |= fbi->mach_info->type;
240 case 1: 301
241 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; 302 if (fbi->mach_info->type == S3C2410_LCDCON1_TFT)
242 break; 303 switch (var->bits_per_pixel) {
243 case 2: 304 case 1:
244 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; 305 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
245 break; 306 break;
246 case 4: 307 case 2:
247 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; 308 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
248 break; 309 break;
249 case 8: 310 case 4:
250 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; 311 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
251 break; 312 break;
252 case 16: 313 case 8:
253 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; 314 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
254 break; 315 break;
255 } 316 case 16:
317 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
318 break;
319
320 default:
321 /* invalid pixel depth */
322 dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
323 }
324 else
325 switch (var->bits_per_pixel) {
326 case 1:
327 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP;
328 break;
329 case 2:
330 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY;
331 break;
332 case 4:
333 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY;
334 break;
335 case 8:
336 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP;
337 break;
338 case 12:
339 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP;
340 break;
341
342 default:
343 /* invalid pixel depth */
344 dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel);
345 }
256 346
257 /* check to see if we need to update sync/borders */ 347 /* check to see if we need to update sync/borders */
258 348
@@ -283,15 +373,44 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
283 fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff); 373 fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
284 fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1); 374 fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1);
285 375
376 switch(fbi->mach_info->type) {
377 case S3C2410_LCDCON1_DSCAN4:
378 case S3C2410_LCDCON1_STN8:
379 hs = var->xres / 8;
380 break;
381 case S3C2410_LCDCON1_STN4:
382 hs = var->xres / 4;
383 break;
384 default:
385 case S3C2410_LCDCON1_TFT:
386 hs = var->xres;
387 break;
388
389 }
390
391 /* Special cases : STN color displays */
392 if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \
393 || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) {
394 hs = hs * 3;
395 }
396
397
286 fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff); 398 fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
287 fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1); 399 fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(hs - 1);
288 400
289 if (var->pixclock > 0) { 401 if (var->pixclock > 0) {
290 int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); 402 int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
291 403
292 clkdiv = (clkdiv / 2) -1; 404 if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) {
293 if (clkdiv < 0) 405 clkdiv = (clkdiv / 2) -1;
294 clkdiv = 0; 406 if (clkdiv < 0)
407 clkdiv = 0;
408 }
409 else {
410 clkdiv = (clkdiv / 2);
411 if (clkdiv < 2)
412 clkdiv = 2;
413 }
295 414
296 fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff); 415 fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
297 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv); 416 fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv);
@@ -329,10 +448,18 @@ static int s3c2410fb_set_par(struct fb_info *info)
329 struct s3c2410fb_info *fbi = info->par; 448 struct s3c2410fb_info *fbi = info->par;
330 struct fb_var_screeninfo *var = &info->var; 449 struct fb_var_screeninfo *var = &info->var;
331 450
332 if (var->bits_per_pixel == 16) 451 switch (var->bits_per_pixel)
333 fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; 452 {
334 else 453 case 16:
335 fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; 454 fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
455 break;
456 case 1:
457 fbi->fb->fix.visual = FB_VISUAL_MONO01;
458 break;
459 default:
460 fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
461 break;
462 }
336 463
337 fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8; 464 fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8;
338 465
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
index 90894214cace..93a58e7862b0 100644
--- a/include/asm-arm/arch-s3c2410/fb.h
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -31,6 +31,9 @@ struct s3c2410fb_hw {
31struct s3c2410fb_mach_info { 31struct s3c2410fb_mach_info {
32 unsigned char fixed_syncs; /* do not update sync/border */ 32 unsigned char fixed_syncs; /* do not update sync/border */
33 33
34 /* LCD types */
35 int type;
36
34 /* Screen size */ 37 /* Screen size */
35 int width; 38 int width;
36 int height; 39 int height;