mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-10 16:58:31 +00:00
Support for SII9022 transmitter
EDID updates for EDID 1.3, HDMI and CEA data
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#define STD_TIMING_DESCRIPTIONS_START 0x26
|
||||
|
||||
#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
|
||||
#define DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START 0x80
|
||||
#define DETAILED_TIMING_DESCRIPTION_SIZE 18
|
||||
#define NO_DETAILED_TIMING_DESCRIPTIONS 4
|
||||
|
||||
@@ -101,8 +102,8 @@
|
||||
#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
|
||||
#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
|
||||
|
||||
#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
|
||||
#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
|
||||
#define H_SYNC_WIDTH COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
|
||||
#define H_SYNC_OFFSET COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
|
||||
|
||||
#define H_SIZE_LO (unsigned)block[ 12 ]
|
||||
#define V_SIZE_LO (unsigned)block[ 13 ]
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
* EDID parser
|
||||
*/
|
||||
|
||||
#undef DEBUG /* define this for verbose EDID parsing output */
|
||||
//#undef DEBUG /* define this for verbose EDID parsing output */
|
||||
#define DEBUG 1
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DPRINTK(fmt, args...) printk(fmt,## args)
|
||||
@@ -492,18 +493,25 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
|
||||
return num;
|
||||
}
|
||||
|
||||
static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
|
||||
static int get_std_timing(u8 edid_ver, u8 edid_rev, unsigned char *block, struct fb_videomode *mode)
|
||||
{
|
||||
int xres, yres = 0, refresh, ratio, i;
|
||||
|
||||
if( edid_ver < 1 || (edid_ver == 1 && edid_rev < 3 ) )
|
||||
xres = (block[0] + 31) * 8;
|
||||
else
|
||||
xres = (block[0] * 8) + 248; /* edid v1.3 */
|
||||
|
||||
if (xres <= 256)
|
||||
return 0;
|
||||
|
||||
ratio = (block[1] & 0xc0) >> 6;
|
||||
switch (ratio) {
|
||||
case 0:
|
||||
case 0: /* aspect ratio 16:10 in v1.3, ratio 1:1 prior to v1.3 */
|
||||
if( edid_ver < 1 || (edid_ver == 1 && edid_rev < 3 ) )
|
||||
yres = xres;
|
||||
else
|
||||
yres = (xres *10)/16;
|
||||
break;
|
||||
case 1:
|
||||
yres = (xres * 3)/4;
|
||||
@@ -531,13 +539,13 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_dst_timing(unsigned char *block,
|
||||
static int get_dst_timing(u8 edid_ver, u8 edid_rev, unsigned char *block,
|
||||
struct fb_videomode *mode)
|
||||
{
|
||||
int j, num = 0;
|
||||
|
||||
for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
|
||||
num += get_std_timing(block, &mode[num]);
|
||||
num += get_std_timing(edid_ver, edid_rev, block, &mode[num]);
|
||||
|
||||
return num;
|
||||
}
|
||||
@@ -573,13 +581,21 @@ static void get_detailed_timing(unsigned char *block,
|
||||
}
|
||||
mode->flag = FB_MODE_IS_DETAILED;
|
||||
|
||||
DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
|
||||
DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
|
||||
H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
|
||||
DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
|
||||
V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
|
||||
DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
|
||||
(VSYNC_POSITIVE) ? "+" : "-");
|
||||
DPRINTK(" \"%dx%d%s%d\" %d ",
|
||||
mode->xres, mode->yres, INTERLACED ? "i@" : "@", mode->refresh,
|
||||
PIXEL_CLOCK/1000000);
|
||||
DPRINTK("%d %d %d %d ",
|
||||
mode->xres,
|
||||
mode->xres + mode->right_margin,
|
||||
mode->xres + mode->right_margin + mode->hsync_len,
|
||||
mode->xres + mode->right_margin + mode->hsync_len + mode->left_margin );
|
||||
DPRINTK("%d %d %d %d ",
|
||||
mode->yres,
|
||||
mode->yres + mode->lower_margin,
|
||||
mode->yres + mode->lower_margin + mode->vsync_len,
|
||||
mode->yres + mode->lower_margin + mode->vsync_len + mode->upper_margin );
|
||||
DPRINTK("%shsync %svsync\n", (HSYNC_POSITIVE) ? "+" : "-",
|
||||
(VSYNC_POSITIVE) ? "+" : "-" );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,6 +615,9 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
|
||||
unsigned char *block;
|
||||
int num = 0, i, first = 1;
|
||||
|
||||
int offset = 0;
|
||||
u8 edid_ver = 0, edid_rev = 0;
|
||||
|
||||
mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
|
||||
if (mode == NULL)
|
||||
return NULL;
|
||||
@@ -611,6 +630,9 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
|
||||
|
||||
*dbsize = 0;
|
||||
|
||||
edid_ver = edid[EDID_STRUCT_VERSION];
|
||||
edid_rev = edid[EDID_STRUCT_REVISION];
|
||||
|
||||
DPRINTK(" Detailed Timings\n");
|
||||
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
|
||||
for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
|
||||
@@ -631,12 +653,43 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
|
||||
DPRINTK(" Standard Timings\n");
|
||||
block = edid + STD_TIMING_DESCRIPTIONS_START;
|
||||
for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
|
||||
num += get_std_timing(block, &mode[num]);
|
||||
num += get_std_timing(edid_ver, edid_rev, block, &mode[num]);
|
||||
|
||||
DPRINTK(" Detail Timings\n");
|
||||
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
|
||||
for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
|
||||
if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
|
||||
num += get_dst_timing(block + 5, &mode[num]);
|
||||
num += get_dst_timing(edid_ver, edid_rev, block + 5, &mode[num]);
|
||||
}
|
||||
|
||||
/* how many additional extension blocks available */
|
||||
if (edid[126] > 0 ) {
|
||||
if (edid[DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START] == 0x02) {
|
||||
/* This block is CEA extension */
|
||||
DPRINTK("----------------------------------------\n");
|
||||
DPRINTK(" EIA/CEA-861 Information\n");
|
||||
DPRINTK(" Revision number: %d\n",
|
||||
edid[DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START+1] );
|
||||
DPRINTK(" DTV underscan: %s\n",
|
||||
(edid[DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START+3] & 0x80 ) ?
|
||||
"Supported" : "Not supported");
|
||||
DPRINTK(" Basic audio: %s\n",
|
||||
(edid[DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START+3] & 0x40 ) ?
|
||||
"Supported" : "Not supported");
|
||||
|
||||
offset = edid[DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START + 2];
|
||||
if (offset > 0) {
|
||||
block = edid + DETAILED_TIMING_DESCRIPTIONS_BLOCK1_START + offset;
|
||||
|
||||
DPRINTK(" Detailed Timings\n");
|
||||
for (i = 0; i < 5; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
|
||||
if (!(block[0] == 0x00 && block[1] == 0x00)) {
|
||||
get_detailed_timing(block, &mode[num]);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Yikes, EDID data is totally useless */
|
||||
|
||||
@@ -264,12 +264,24 @@ static const struct fb_videomode modedb[] = {
|
||||
/* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */
|
||||
NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3,
|
||||
0, FB_VMODE_NONINTERLACED
|
||||
}, {
|
||||
/* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
|
||||
},
|
||||
{ /* 1280x720 @ 60 CEA-MODE 4 */
|
||||
"1280x720-16@60", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
|
||||
},
|
||||
{ /* 1280x720 @ 50 Hz CEA-MODE 19 */
|
||||
"1280x720-16@50", 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
|
||||
},
|
||||
{ /* 1280x768, 60Hz, 68.26MHz */
|
||||
"1280x768-16@60", 60, 1280, 768, 14650, 80, 48, 12, 3, 32, 7,
|
||||
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
|
||||
},
|
||||
{ /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
|
||||
NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5,
|
||||
0, FB_VMODE_INTERLACED
|
||||
}, {
|
||||
/* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
|
||||
},
|
||||
{ /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
|
||||
NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5,
|
||||
0, FB_VMODE_INTERLACED
|
||||
},
|
||||
@@ -402,19 +414,17 @@ const struct fb_videomode vesa_modes[] = {
|
||||
EXPORT_SYMBOL(vesa_modes);
|
||||
#endif /* CONFIG_FB_MODE_HELPERS */
|
||||
|
||||
static int my_atoi(const char *name)
|
||||
int fb_dump_mode( char *func_char, struct fb_videomode *mode)
|
||||
{
|
||||
int val = 0;
|
||||
printk( KERN_INFO "%s geometry %u %u %u\n",
|
||||
func_char, mode->xres, mode->yres, mode->pixclock);
|
||||
printk( KERN_INFO "%s timings %u %u %u %u %u %u %u\n",
|
||||
func_char, mode->pixclock, mode->left_margin, mode->right_margin,
|
||||
mode->upper_margin, mode->lower_margin, mode->hsync_len, mode->vsync_len );
|
||||
printk( KERN_INFO "%s flag %u sync %u vmode %u\n",
|
||||
func_char, mode->flag, mode->sync, mode->vmode );
|
||||
|
||||
for (;; name++) {
|
||||
switch (*name) {
|
||||
case '0' ... '9':
|
||||
val = 10*val+(*name-'0');
|
||||
break;
|
||||
default:
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,6 +535,9 @@ int fb_find_mode(struct fb_var_screeninfo *var,
|
||||
/* Did the user specify a video mode? */
|
||||
if (!mode_option)
|
||||
mode_option = fb_mode_option;
|
||||
|
||||
printk(KERN_INFO "mode_option=%s\n", mode_option);
|
||||
|
||||
if (mode_option) {
|
||||
const char *name = mode_option;
|
||||
unsigned int namelen = strlen(name);
|
||||
@@ -539,7 +552,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
|
||||
namelen = i;
|
||||
if (!refresh_specified && !bpp_specified &&
|
||||
!yres_specified) {
|
||||
refresh = my_atoi(&name[i+1]);
|
||||
refresh = simple_strtol(&name[i+1], NULL, 10);
|
||||
refresh_specified = 1;
|
||||
if (cvt || rb)
|
||||
cvt = 0;
|
||||
@@ -549,7 +562,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
|
||||
case '-':
|
||||
namelen = i;
|
||||
if (!bpp_specified && !yres_specified) {
|
||||
bpp = my_atoi(&name[i+1]);
|
||||
bpp = simple_strtol(&name[i+1], NULL, 10);
|
||||
bpp_specified = 1;
|
||||
if (cvt || rb)
|
||||
cvt = 0;
|
||||
@@ -558,7 +571,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
|
||||
break;
|
||||
case 'x':
|
||||
if (!yres_specified) {
|
||||
yres = my_atoi(&name[i+1]);
|
||||
yres = simple_strtol(&name[i+1], NULL, 10);
|
||||
yres_specified = 1;
|
||||
} else
|
||||
goto done;
|
||||
@@ -585,11 +598,12 @@ int fb_find_mode(struct fb_var_screeninfo *var,
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 0 && yres_specified) {
|
||||
xres = my_atoi(name);
|
||||
xres = simple_strtol(name, NULL, 10);
|
||||
res_specified = 1;
|
||||
}
|
||||
done:
|
||||
done:
|
||||
if (cvt) {
|
||||
struct fb_videomode cvt_mode;
|
||||
int ret;
|
||||
@@ -609,8 +623,8 @@ done:
|
||||
else
|
||||
cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
|
||||
|
||||
ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
|
||||
|
||||
ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
|
||||
|
||||
if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
|
||||
DPRINTK("modedb CVT: CVT mode ok\n");
|
||||
return 1;
|
||||
|
||||
@@ -38,6 +38,10 @@ config FB_MXC_CLAA_WVGA_SYNC_PANEL
|
||||
depends on FB_MXC_SYNC_PANEL
|
||||
tristate "CLAA WVGA Panel"
|
||||
|
||||
config FB_MXC_SII9022
|
||||
depends on FB_MXC_SYNC_PANEL
|
||||
tristate "SII9022A HDMI Interface Chip"
|
||||
|
||||
config FB_MXC_CH7026
|
||||
depends on FB_MXC_SYNC_PANEL
|
||||
tristate "Chrontel CH7026 VGA Interface Chip"
|
||||
|
||||
@@ -20,5 +20,6 @@ obj-$(CONFIG_FB_MXC_TVOUT_TVE) += tve.o
|
||||
obj-$(CONFIG_FB_MXC_LDB) += ldb.o
|
||||
obj-$(CONFIG_FB_MXC_CH7026) += mxcfb_ch7026.o
|
||||
#obj-$(CONFIG_FB_MODE_HELPERS) += mxc_edid.o
|
||||
obj-$(CONFIG_FB_MXC_SII9022) += mxcfb_sii9022.o
|
||||
obj-$(CONFIG_FB_MXC_EINK_PANEL) += mxc_epdc_fb.o
|
||||
obj-$(CONFIG_FB_MXC_ELCDIF_FB) += mxc_elcdif_fb.o
|
||||
|
||||
@@ -48,6 +48,24 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#if defined(CONFIG_MACH_MX51_EFIKAMX)
|
||||
|
||||
#include <../arch/arm/mach-mx5/mx51_efikamx.h>
|
||||
|
||||
#ifndef dev_dbg
|
||||
#define dev_dbg(dev, format, arg...) \
|
||||
dev_printk(KERN_INFO , dev , format , ## arg)
|
||||
#endif
|
||||
|
||||
extern int mxc_debug;
|
||||
extern int clock_auto;
|
||||
extern int extsync;
|
||||
extern int pixclk_limit;
|
||||
extern void mxcfb_adjust(struct fb_var_screeninfo *var );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Driver name
|
||||
*/
|
||||
@@ -147,6 +165,19 @@ static int mxcfb_set_fix(struct fb_info *info)
|
||||
fix->xpanstep = 1;
|
||||
fix->ypanstep = 1;
|
||||
|
||||
#if defined(CONFIG_MACH_MX51_EFIKAMX)
|
||||
if( clock_auto && extsync ) {
|
||||
if ( var->pixclock < pixclk_limit ) {
|
||||
printk(KERN_INFO "exceed pixel clock limit %d, auto adjust to 720p\n", pixclk_limit );
|
||||
fb_find_mode( var, info, "1280x720-24@60", NULL, 0, NULL, 0 );
|
||||
}
|
||||
var->sync |= FB_SYNC_EXT; /* x window need it otherwise refresh rate will become bigger than user specified */
|
||||
}
|
||||
/* skip mxc_sdc_fb.2 (overlay) configure */
|
||||
if ( ((struct mxcfb_info *)info->par)->ipu_ch != MEM_FG_SYNC)
|
||||
mxcfb_adjust( var );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1677,7 +1708,11 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
mxcfb_check_var(&fbi->var, fbi);
|
||||
|
||||
/* Default Y virtual size is 2x panel size */
|
||||
#if defined(CONFIG_MACH_MX51_EFIKAMX)
|
||||
fbi->var.yres_virtual = fbi->var.yres * 2;
|
||||
#else
|
||||
fbi->var.yres_virtual = fbi->var.yres * 3;
|
||||
#endif
|
||||
|
||||
mxcfb_set_fix(fbi);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user