169 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			169 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * quick tool to set LCD timings for Wiz
							 | 
						||
| 
								 | 
							
								 * (c) notaz, 2009
							 | 
						||
| 
								 | 
							
								 * code dedicated to public domain.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * HTOTAL:    X VTOTAL:  341
							 | 
						||
| 
								 | 
							
								 * HSWIDTH:   1 VSWIDTH:   0
							 | 
						||
| 
								 | 
							
								 * HASTART:  37 VASTART:  17
							 | 
						||
| 
								 | 
							
								 * HAEND:   277 VAEND:   337
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * 120Hz
							 | 
						||
| 
								 | 
							
								 * pcd  8, 447: + 594us
							 | 
						||
| 
								 | 
							
								 * pcd  9, 397: +  36us
							 | 
						||
| 
								 | 
							
								 * pcd 10, 357: - 523us
							 | 
						||
| 
								 | 
							
								 * pcd 11, 325: +1153us
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * 'lcd_timings=397,1,37,277,341,0,17,337;clkdiv0=9'
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								#include "pollux_dpc_set.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * set LCD timings based on preformated string (see usage() below for params).
							 | 
						||
| 
								 | 
							
								 * returns 0 on success.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								int pollux_dpc_set(volatile unsigned short *memregs, const char *str)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int timings[8], have_timings = 0;
							 | 
						||
| 
								 | 
							
									int pcd = 0, have_pcd = 0;
							 | 
						||
| 
								 | 
							
									const char *p;
							 | 
						||
| 
								 | 
							
									int i, ret;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (str == NULL)
							 | 
						||
| 
								 | 
							
										return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									p = str;
							 | 
						||
| 
								 | 
							
									while (1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (strncmp(p, "lcd_timings=", 12) == 0)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											int c;
							 | 
						||
| 
								 | 
							
											p += 12;
							 | 
						||
| 
								 | 
							
											ret = sscanf(p, "%d,%d,%d,%d,%d,%d,%d,%d",
							 | 
						||
| 
								 | 
							
												&timings[0], &timings[1], &timings[2], &timings[3],
							 | 
						||
| 
								 | 
							
												&timings[4], &timings[5], &timings[6], &timings[7]);
							 | 
						||
| 
								 | 
							
											if (ret != 8)
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											/* skip seven commas */
							 | 
						||
| 
								 | 
							
											for (c = 0; c < 7 && *p != 0; p++)
							 | 
						||
| 
								 | 
							
												if (*p == ',')
							 | 
						||
| 
								 | 
							
														c++;
							 | 
						||
| 
								 | 
							
											if (c != 7)
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											/* skip last number */
							 | 
						||
| 
								 | 
							
											while ('0' <= *p && *p <= '9')
							 | 
						||
| 
								 | 
							
												p++;
							 | 
						||
| 
								 | 
							
											have_timings = 1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else if (strncmp(p, "clkdiv0=", 8) == 0)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											char *ep;
							 | 
						||
| 
								 | 
							
											p += 8;
							 | 
						||
| 
								 | 
							
											pcd = strtoul(p, &ep, 10);
							 | 
						||
| 
								 | 
							
											if (p == ep)
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											p = ep;
							 | 
						||
| 
								 | 
							
											have_pcd = 1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										while (*p == ';' || *p == ' ')
							 | 
						||
| 
								 | 
							
											p++;
							 | 
						||
| 
								 | 
							
										if (*p == 0)
							 | 
						||
| 
								 | 
							
											goto parse_done;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									fprintf(stderr, "dpc_set parser: error at '%s'\n", p);
							 | 
						||
| 
								 | 
							
									return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								parse_done:
							 | 
						||
| 
								 | 
							
									/* some validation */
							 | 
						||
| 
								 | 
							
									if (have_timings)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (i = 0; i < 8; i++)
							 | 
						||
| 
								 | 
							
											if (timings[i] & ~0xffff) {
							 | 
						||
| 
								 | 
							
												fprintf(stderr, "dpc_set: invalid timing %d: %d\n", i, timings[i]);
							 | 
						||
| 
								 | 
							
												return -1;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (have_pcd)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ((pcd - 1) & ~0x3f) {
							 | 
						||
| 
								 | 
							
											fprintf(stderr, "dpc_set: invalid clkdiv0: %d\n", pcd);
							 | 
						||
| 
								 | 
							
											return -1;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* write */
							 | 
						||
| 
								 | 
							
									if (have_timings)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (i = 0; i < 8; i++)
							 | 
						||
| 
								 | 
							
											memregs[(0x307c>>1) + i] = timings[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (have_pcd)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int tmp;
							 | 
						||
| 
								 | 
							
										pcd = (pcd - 1) & 0x3f;
							 | 
						||
| 
								 | 
							
										tmp = memregs[0x31c4>>1];
							 | 
						||
| 
								 | 
							
										memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BINARY
							 | 
						||
| 
								 | 
							
								#include <sys/types.h>
							 | 
						||
| 
								 | 
							
								#include <sys/stat.h>
							 | 
						||
| 
								 | 
							
								#include <fcntl.h>
							 | 
						||
| 
								 | 
							
								#include <sys/mman.h>
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void usage(const char *binary)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									printf("usage:\n%s <set_str[;set_str[;...]]>\n"
							 | 
						||
| 
								 | 
							
										"set_str:\n"
							 | 
						||
| 
								 | 
							
										"  lcd_timings=<htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend>\n"
							 | 
						||
| 
								 | 
							
										"  clkdiv0=<divider>\n", binary);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int main(int argc, char *argv[])
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									volatile unsigned short *memregs;
							 | 
						||
| 
								 | 
							
									int ret, memdev;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (argc != 2) {
							 | 
						||
| 
								 | 
							
										usage(argv[0]);
							 | 
						||
| 
								 | 
							
										return 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memdev = open("/dev/mem", O_RDWR);
							 | 
						||
| 
								 | 
							
									if (memdev == -1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										perror("open(/dev/mem) failed");
							 | 
						||
| 
								 | 
							
										return 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memregs	= mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
							 | 
						||
| 
								 | 
							
									if (memregs == MAP_FAILED)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										perror("mmap(memregs) failed");
							 | 
						||
| 
								 | 
							
										close(memdev);
							 | 
						||
| 
								 | 
							
										return 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ret = pollux_dpc_set(memregs, argv[1]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									munmap((void *)memregs, 0x10000);
							 | 
						||
| 
								 | 
							
									close(memdev);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 |