Commit 6ede5d29 authored by Jorge Zapata's avatar Jorge Zapata

Fix the inverted field hw bug on vid0 plane

This fixes the bug found on 1.3 hw revision. Basically the bug is found when
the video out is in interlaced mode, vid0 picks up the inverted field order
(even when should be odd and vice versa), to avoid that we use the ping-pong
feature of the vid0 plane to swap the order on every interrupt.
parent b7d345ab
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
*/ */
#define DEBUG #define DEBUG
/* TODO we should replace this VID0FIX define with a way to get the chip
* revision
*/
#define VID0FIX
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -259,130 +263,26 @@ static const struct fb_videomode dmfb_modedb[] = { ...@@ -259,130 +263,26 @@ static const struct fb_videomode dmfb_modedb[] = {
/*============================================================================* /*============================================================================*
* VENC interface * * VENC interface *
*============================================================================*/ *============================================================================*/
/* Find the mode that matches exactly this var */ /* slow down the VCLK to 27MHZ from
static int dm_venc_find_mode(const struct fb_var_screeninfo *var) * 74MHZ */
static inline void slow_down_vclk(void)
{ {
unsigned int i; /* set DCLKPTN works as the clock enable for ENC
* clock. */
outl(VENC_DCKCTL_DCKEC, VENC_DCLKCTL);
/* only check the mode that has the same displayable size */ /* DCLK pattern. The specified bit pattern is output in
for (i = 0; i < ARRAY_SIZE(dmfb_modedb); i++) { * resolution of ENC clock units.*/
if (var->xres == dmfb_modedb[i].xres && outl(0x01, VENC_DCLKPTN0);
var->yres == dmfb_modedb[i].yres &&
var->vmode == dmfb_modedb[i].vmode)
return i;
}
return -EINVAL;
}
/** /* select MXI mode. Use 27 MHz (from MXI27)
* Checks if a mode is a HD mode * (DAC clock = 27 MHz).VPBE/Video encoder clock
* @return 0 if mode is SD, 1 if mode is HD * is enabled*/
*/ outl(VPSS_CLKCTL_ENABLE_VPBE_CLK, VPSS_CLKCTL);
static int dm_venc_mode_is_hd(struct fb_videomode *mode)
{
if (!strcmp(mode->name, "576i") || !strcmp(mode->name, "480i"))
return 0;
else
return 1;
} }
/** /**
* Set the timings from a mode * Enables de digital output on venc
*/
static void dm_venc_mode_set(struct dm_info *dm, const struct fb_videomode *mode,
const struct dm_extended_mode *extmode)
{
dispc_reg_out(VENC_HSPLS, mode->hsync_len);
dispc_reg_out(VENC_VSPLS, mode->vsync_len);
dispc_reg_out(VENC_HINT, mode->xres + mode->left_margin +
mode->right_margin);
dispc_reg_out(VENC_HSTART, mode->left_margin);
dispc_reg_out(VENC_HVALID, mode->xres);
dispc_reg_out(VENC_VINT, mode->yres + mode->upper_margin +
mode->lower_margin);
dispc_reg_out(VENC_VSTART, mode->upper_margin);
dispc_reg_out(VENC_VVALID, mode->vmode == FB_VMODE_INTERLACED ? mode->yres / 2 : mode->yres);
/* TODO check vmode (interlaced / progressive)*/
/* set the window field / frame mode */
dispc_reg_out(VENC_YCCCTL, 0x0);
dispc_reg_out(VENC_VSTARTA, extmode->vstarta);
dispc_reg_out(OSD_BASEPX, extmode->basex);
dispc_reg_out(OSD_BASEPY, extmode->basey);
}
/* Select the output on the venc mode. This outputs are only
* available on standard moed timings, both SD or HD.
* DACSEL.DAnS CMPNT.MRGB DAC Output
* 0 - CVBS
* 1 - S-Video Y
* 2 - S-Video C
* 3 0 Y
* 1 G
* 4 0 Pb
* 1 B
* 5 0 Pr
* 1 R
*/ */
int dm_venc_set_state(struct output_device *od)
{
struct dm_info *dm = (struct dm_info *)class_get_devdata(&od->class_dev);
unsigned long state = od->request_state;
/* TODO check that the output is in standard mode */
switch (state)
{
case DAVINCIFB_OUT_COMPOSITE:
dispc_reg_out(VENC_DACSEL, 0x0);
break;
case DAVINCIFB_OUT_COMPONENT:
/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr */
dispc_reg_out(VENC_DACSEL, 0x543);
break;
case DAVINCIFB_OUT_SVIDEO:
/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C */
dispc_reg_out(VENC_DACSEL, 0x210);
break;
case DAVINCIFB_OUT_RGB:
/* TODO handle rgb */
printk("rgb!\n");
break;
default:
return -EINVAL;
}
dm->output_sel = state;
return 0;
}
/* Returns the current output mode selcted */
int dm_venc_get_status(struct output_device *od)
{
struct dm_info *dm = (struct dm_info *)class_get_devdata(&od->class_dev);
return dm->output_sel;
}
struct output_properties dm_venc_props = {
.set_state = &dm_venc_set_state,
.get_status = &dm_venc_get_status,
};
#if 0
static int dm_vout_probe(struct dm_info *info)
{
int ret;
dm->output = video_output_register("venc", dm->dev, dm, &dm_venc_props);
if (!dm->output)
return -EINVAL;
return 0;
}
#endif
/*============================================================================*
* Mode definitions *
*============================================================================*/
static void enable_digital_output(bool on) static void enable_digital_output(bool on)
{ {
if (on) { if (on) {
...@@ -497,23 +397,192 @@ static void enable_digital_output(bool on) ...@@ -497,23 +397,192 @@ static void enable_digital_output(bool on)
} }
} }
/* slow down the VCLK to 27MHZ from /* Find the mode that matches exactly this var */
* 74MHZ */ static int dm_venc_find_mode(const struct fb_var_screeninfo *var)
static inline void slow_down_vclk(void)
{ {
/* set DCLKPTN works as the clock enable for ENC unsigned int i;
* clock. */
outl(VENC_DCKCTL_DCKEC, VENC_DCLKCTL);
/* DCLK pattern. The specified bit pattern is output in /* only check the mode that has the same displayable size */
* resolution of ENC clock units.*/ for (i = 0; i < ARRAY_SIZE(dmfb_modedb); i++) {
outl(0x01, VENC_DCLKPTN0); if (var->xres == dmfb_modedb[i].xres &&
var->yres == dmfb_modedb[i].yres &&
var->vmode == dmfb_modedb[i].vmode)
return i;
}
return -EINVAL;
}
/* select MXI mode. Use 27 MHz (from MXI27) /**
* (DAC clock = 27 MHz).VPBE/Video encoder clock * Checks if a mode is a HD mode
* is enabled*/ * @return 0 if mode is SD, 1 if mode is HD
outl(VPSS_CLKCTL_ENABLE_VPBE_CLK, VPSS_CLKCTL); */
static int dm_venc_mode_is_hd(struct fb_videomode *mode)
{
if (!strcmp(mode->name, "576i") || !strcmp(mode->name, "480i"))
return 0;
else
return 1;
} }
/**
* Set the timmings of the VENC
*/
static void dm_venc_timmings_set(struct dm_info *dm, const struct fb_videomode *mode, const struct dm_extended_mode *extmode)
{
dispc_reg_out(VENC_HSPLS, mode->hsync_len);
dispc_reg_out(VENC_VSPLS, mode->vsync_len);
dispc_reg_out(VENC_HINT, mode->xres + mode->left_margin +
mode->right_margin);
dispc_reg_out(VENC_HSTART, mode->left_margin);
dispc_reg_out(VENC_HVALID, mode->xres);
dispc_reg_out(VENC_VINT, mode->yres + mode->upper_margin +
mode->lower_margin);
dispc_reg_out(VENC_VSTART, mode->upper_margin);
dispc_reg_out(VENC_VVALID, mode->vmode == FB_VMODE_INTERLACED ? mode->yres / 2 : mode->yres);
/* TODO check vmode (interlaced / progressive)*/
/* set the window field / frame mode */
dispc_reg_out(VENC_YCCCTL, 0x0);
dispc_reg_out(VENC_VSTARTA, extmode->vstarta);
dispc_reg_out(OSD_BASEPX, extmode->basex);
dispc_reg_out(OSD_BASEPY, extmode->basey);
}
/**
* Set the venc mode
*/
static void dm_venc_mode_set(struct dm_info *dm, const struct fb_videomode *mode,
const struct dm_extended_mode *extmode)
{
/* shutdown previous mode */
dispc_reg_out(VENC_VMOD, 0);
enable_digital_output(false);
/* set the timmings */
dm_venc_timmings_set(dm, mode, extmode);
/* for standard modes */
if (!strcmp(mode->name, "480i")) {
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and NTSC */
dispc_reg_out(VENC_VMOD, 0x1003);
}
else if (!strcmp(mode->name, "576i")) {
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and PAL */
dispc_reg_out(VENC_VMOD, 0x1043);
}
/* for non standard modes */
else {
printk("Setting mode %s\n", mode->name);
enable_digital_output(true);
#ifdef CONFIG_THS8200
if (!strcmp(mode->name, "480p")) {
/* slow down the vclk as 27MHZ */
slow_down_vclk();
ths8200_set_480p_mode();
dispc_reg_merge(PINMUX0, 0, PINMUX0_LFLDEN);
/* Enable all VENC, non-standard timing mode,
* master timing, HD, progressive */
dispc_reg_out(VENC_VMOD,
(VENC_VMOD_VENC | VENC_VMOD_VMD | VENC_VMOD_HDMD));
}
else if (!strcmp(mode->name, "720p")) {
ths8200_set_720p_mode();
dispc_reg_merge(PINMUX0, 0, PINMUX0_LFLDEN);
/* Enable all VENC, non-standard timing mode,
* master timing, HD, progressive */
dispc_reg_out(VENC_VMOD,
(VENC_VMOD_VENC | VENC_VMOD_VMD | VENC_VMOD_HDMD));
}
else if (!strcmp(mode->name, "1080i")) {
ths8200_set_1080i_mode();
dispc_reg_merge(PINMUX0, PINMUX0_LFLDEN, PINMUX0_LFLDEN);
/* Enable all VENC, non-standard timing mode,
* master timing, HD, interlaced */
dispc_reg_out(VENC_VMOD,
(VENC_VMOD_VENC | VENC_VMOD_VMD |
VENC_VMOD_HDMD | VENC_VMOD_NSIT));
}
#endif
}
}
/* Select the output on the venc mode. This outputs are only
* available on standard moed timings, both SD or HD.
* DACSEL.DAnS CMPNT.MRGB DAC Output
* 0 - CVBS
* 1 - S-Video Y
* 2 - S-Video C
* 3 0 Y
* 1 G
* 4 0 Pb
* 1 B
* 5 0 Pr
* 1 R
*/
int dm_venc_set_state(struct output_device *od)
{
struct dm_info *dm = (struct dm_info *)class_get_devdata(&od->class_dev);
unsigned long state = od->request_state;
/* TODO check that the output is in standard mode */
switch (state)
{
case DAVINCIFB_OUT_COMPOSITE:
dispc_reg_out(VENC_DACSEL, 0x0);
break;
case DAVINCIFB_OUT_COMPONENT:
/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr */
dispc_reg_out(VENC_DACSEL, 0x543);
break;
case DAVINCIFB_OUT_SVIDEO:
/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C */
dispc_reg_out(VENC_DACSEL, 0x210);
break;
case DAVINCIFB_OUT_RGB:
/* TODO handle rgb */
printk("rgb!\n");
break;
default:
return -EINVAL;
}
dm->output_sel = state;
return 0;
}
/* Returns the current output mode selcted */
int dm_venc_get_status(struct output_device *od)
{
struct dm_info *dm = (struct dm_info *)class_get_devdata(&od->class_dev);
return dm->output_sel;
}
struct output_properties dm_venc_props = {
.set_state = &dm_venc_set_state,
.get_status = &dm_venc_get_status,
};
#if 0
static int dm_vout_probe(struct dm_info *info)
{
int ret;
dm->output = video_output_register("venc", dm->dev, dm, &dm_venc_props);
if (!dm->output)
return -EINVAL;
return 0;
}
#endif
/*============================================================================*
* Mode definitions *
*============================================================================*/
#if 0 #if 0
static void davincifb_480p_component_config(int on) static void davincifb_480p_component_config(int on)
{ {
...@@ -694,9 +763,12 @@ static int davincifb_set_attr_blend(struct dm_win_info *w, ...@@ -694,9 +763,12 @@ static int davincifb_set_attr_blend(struct dm_win_info *w,
/* Interlaced = Frame mode, Non-interlaced = Field mode */ /* Interlaced = Frame mode, Non-interlaced = Field mode */
static void set_interlaced(struct dm_win_info *w, unsigned int on) static void set_interlaced(struct dm_win_info *w, unsigned int on)
{ {
/* TODO remove DAVINCIFB_WIN_VID0, DAVINCIFB_WIN_OSD0, etc */ struct device *dev = w->dm->dev;
on = (on == 0) ? 0 : ~0; on = (on == 0) ? 0 : ~0;
dev_dbg(dev, "Setting window interlaced %s %c\n", dm_win_names[w->win], on ? 'I' : 'P');
if (is_win(w, DAVINCIFB_WIN_VID0)) if (is_win(w, DAVINCIFB_WIN_VID0))
dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_VFF0); dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_VFF0);
else if (is_win(w, DAVINCIFB_WIN_VID1)) else if (is_win(w, DAVINCIFB_WIN_VID1))
...@@ -771,8 +843,26 @@ static void set_sdram_params(const struct dm_win_info *w, u32 addr, u32 line_len ...@@ -771,8 +843,26 @@ static void set_sdram_params(const struct dm_win_info *w, u32 addr, u32 line_len
line_length = line_length / 32; line_length = line_length / 32;
if (is_win(w, DAVINCIFB_WIN_VID0)) { if (is_win(w, DAVINCIFB_WIN_VID0)) {
#ifndef VID0FIX
dispc_reg_out(OSD_VIDWIN0ADR, addr); dispc_reg_out(OSD_VIDWIN0ADR, addr);
dispc_reg_out(OSD_VIDWIN0OFST, line_length); dispc_reg_out(OSD_VIDWIN0OFST, line_length);
#else
struct dm_info *dm = w->dm;
/* BUG */
if (dmfb_modedb[w->dm->curr_mode].vmode == FB_VMODE_INTERLACED) {
u32 length = line_length * 32;
dispc_reg_out(OSD_VIDWIN0ADR, addr - length);
dispc_reg_out(OSD_VIDWIN0OFST, line_length);
dispc_reg_out(OSD_PPVWIN0AD, addr + length);
dispc_reg_merge(OSD_VIDWINMD, OSD_VIDWINMD_VFF0, OSD_VIDWINMD_VFF0);
dispc_reg_merge(OSD_MISCCT, OSD_MISCCT_PPRV, OSD_MISCCT_PPRV);
}
else {
dispc_reg_out(OSD_VIDWIN0ADR, addr);
dispc_reg_out(OSD_VIDWIN0OFST, line_length);
dispc_reg_merge(OSD_MISCCT, 0, OSD_MISCCT_PPRV);
}
#endif
} else if (is_win(w, DAVINCIFB_WIN_VID1)) { } else if (is_win(w, DAVINCIFB_WIN_VID1)) {
dispc_reg_out(OSD_VIDWIN1ADR, addr); dispc_reg_out(OSD_VIDWIN1ADR, addr);
dispc_reg_out(OSD_VIDWIN1OFST, line_length); dispc_reg_out(OSD_VIDWIN1OFST, line_length);
...@@ -1012,7 +1102,7 @@ static void set_win_position(const struct dm_win_info *w, u32 xp, u32 yp, u32 xl ...@@ -1012,7 +1102,7 @@ static void set_win_position(const struct dm_win_info *w, u32 xp, u32 yp, u32 xl
int i = 0; int i = 0;
struct device *dev = w->dm->dev; struct device *dev = w->dm->dev;
dev_dbg(dev, "Setting window position %u %u %u %u\n", xp, yp, xl, yl); dev_dbg(dev, "Setting window position %s %u %u %u %u\n", dm_win_names[w->win], xp, yp, xl, yl);
if (is_win(w, DAVINCIFB_WIN_VID0)) { if (is_win(w, DAVINCIFB_WIN_VID0)) {
i = 0; i = 0;
} else if (is_win(w, DAVINCIFB_WIN_VID1)) { } else if (is_win(w, DAVINCIFB_WIN_VID1)) {
...@@ -1072,6 +1162,28 @@ static int dm_win_transp_enable(struct dm_win_info *w, ...@@ -1072,6 +1162,28 @@ static int dm_win_transp_enable(struct dm_win_info *w,
return 0; return 0;
} }
/**
* Sets a window mode
*
*/
static void dm_win_mode_set(struct dm_win_info *w, struct fb_var_screeninfo *v)
{
u32 start = 0, offset = 0;
int interlaced = v->vmode == FB_VMODE_INTERLACED ? 1 : 0;
/* Memory offsets */
w->info.fix.line_length = v->xres_virtual * v->bits_per_pixel / 8;
offset = v->yoffset * w->info.fix.line_length + v->xoffset * v->bits_per_pixel / 8;
start = (u32) w->fb_base_phys + offset;
set_sdram_params(w, start, w->info.fix.line_length);
/* set interlaced mode */
set_interlaced(w, interlaced);
/* set window position and size */
set_win_position(w, w->x, w->y, v->xres, v->yres / (interlaced + 1));
set_win_mode(w);
dm_win_clear(w);
}
/* Initialize the fb_info structure with common values and values that wont /* Initialize the fb_info structure with common values and values that wont
* change if var changes * change if var changes
*/ */
...@@ -1347,10 +1459,15 @@ static int davincifb_check_var(struct fb_var_screeninfo *var, ...@@ -1347,10 +1459,15 @@ static int davincifb_check_var(struct fb_var_screeninfo *var,
printk("%s mode = %s\n", dm_win_names[w->win], dmfb_modedb[mode].name); printk("%s mode = %s\n", dm_win_names[w->win], dmfb_modedb[mode].name);
} }
else { else {
printk("%s invalid mode\n", dm_win_names[w->win]); printk("%s Setting a specific mode\n", dm_win_names[w->win]);
} }
dev_dbg(dev, "Trying to set <%d>%dx%d<%d>@%dbpp\n", v.xres_virtual, v.xres, v.yres, dev_dbg(dev, "Trying to set <%d>%dx%d<%d>@%dbpp\n", v.xres_virtual, v.xres, v.yres,
v.yres_virtual, v.bits_per_pixel); v.yres_virtual, v.bits_per_pixel);
/* always force VENC interlaced mode */
if (w->dm->curr_mode >= 0 && (!is_win(w, DAVINCIFB_WIN_VID0))) {
v.vmode = dmfb_modedb[w->dm->curr_mode].vmode;
}
/* virtual size < display size */ /* virtual size < display size */
if (v.xres_virtual < v.xres || v.yres_virtual < v.yres) { if (v.xres_virtual < v.xres || v.yres_virtual < v.yres) {
dev_dbg(dev, "Virtual size > displayed size\n"); dev_dbg(dev, "Virtual size > displayed size\n");
...@@ -1384,8 +1501,8 @@ static int davincifb_check_var(struct fb_var_screeninfo *var, ...@@ -1384,8 +1501,8 @@ static int davincifb_check_var(struct fb_var_screeninfo *var,
line_length = v.xres_virtual * v.bits_per_pixel / 8; line_length = v.xres_virtual * v.bits_per_pixel / 8;
dev_dbg(dev, "<%d>%dx%d<%d>@%dbpp\n", v.xres_virtual, v.xres, v.yres, dev_dbg(dev, "<%d>%dx%d<%d>@%dbpp-%c\n", v.xres_virtual, v.xres, v.yres,
v.yres_virtual, v.bits_per_pixel); v.yres_virtual, v.bits_per_pixel, v.vmode == FB_VMODE_INTERLACED ? 'I' : 'P');
/* Rules 4, 5 */ /* Rules 4, 5 */
if (line_length % 32) { if (line_length % 32) {
...@@ -1502,26 +1619,13 @@ static int davincifb_set_par(struct fb_info *info) ...@@ -1502,26 +1619,13 @@ static int davincifb_set_par(struct fb_info *info)
{ {
struct dm_win_info *w = (struct dm_win_info *)info->par; struct dm_win_info *w = (struct dm_win_info *)info->par;
struct fb_var_screeninfo *v = &info->var; struct fb_var_screeninfo *v = &info->var;
u32 start = 0, offset = 0;
int mode; int mode;
int interlaced;
int i; int i;
/* Memory offsets */ if (!is_win(w, DAVINCIFB_WIN_VID0)) {
info->fix.line_length = v->xres_virtual * v->bits_per_pixel / 8; dm_win_mode_set(w, v);
offset = v->yoffset * info->fix.line_length + v->xoffset * v->bits_per_pixel / 8;
start = (u32) w->fb_base_phys + offset;
set_sdram_params(w, start, info->fix.line_length);
interlaced = v->vmode == FB_VMODE_INTERLACED ? 1 : 0;
set_win_position(w, w->x, w->y, v->xres, v->yres / (interlaced + 1));
set_win_mode(w);
dm_win_clear(w);
if (!is_win(w, DAVINCIFB_WIN_VID0))
return 0; return 0;
}
/* we are going to change the mode */ /* we are going to change the mode */
mode = dm_venc_find_mode(v); mode = dm_venc_find_mode(v);
if (mode == w->dm->curr_mode) { if (mode == w->dm->curr_mode) {
...@@ -1533,75 +1637,18 @@ static int davincifb_set_par(struct fb_info *info) ...@@ -1533,75 +1637,18 @@ static int davincifb_set_par(struct fb_info *info)
printk("errorrrr\n"); printk("errorrrr\n");
return 0; return 0;
} }
/* shutdown previous mode */ dm_venc_mode_set(w->dm, &dmfb_modedb[mode], &dm_extended_modedb[mode]);
dispc_reg_out(VENC_VMOD, 0);
enable_digital_output(false);
/* for standard modes */
if (!strcmp(dmfb_modedb[mode].name, "480i")) {
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and NTSC */
dispc_reg_out(VENC_VMOD, 0x1003);
}
else if (!strcmp(dmfb_modedb[mode].name, "576i")) {
/* Enable all DACs */
dispc_reg_out(VENC_DACTST, 0);
/* Set REC656 Mode */
dispc_reg_out(VENC_YCCCTL, 0x1);
/* Enable output mode and PAL */
dispc_reg_out(VENC_VMOD, 0x1043);
}
/* for non standard modes */
else {
printk("Setting mode %s\n", dmfb_modedb[mode].name);
enable_digital_output(true);
#ifdef CONFIG_THS8200
if (!strcmp(dmfb_modedb[mode].name, "480p")) {
/* slow down the vclk as 27MHZ */
slow_down_vclk();
ths8200_set_480p_mode();
dispc_reg_merge(PINMUX0, 0, PINMUX0_LFLDEN);
/* Enable all VENC, non-standard timing mode,
* master timing, HD, progressive */
dispc_reg_out(VENC_VMOD,
(VENC_VMOD_VENC | VENC_VMOD_VMD | VENC_VMOD_HDMD));
}
else if (!strcmp(dmfb_modedb[mode].name, "720p")) {
ths8200_set_720p_mode();
dispc_reg_merge(PINMUX0, 0, PINMUX0_LFLDEN);
/* Enable all VENC, non-standard timing mode,
* master timing, HD, progressive */
dispc_reg_out(VENC_VMOD,
(VENC_VMOD_VENC | VENC_VMOD_VMD | VENC_VMOD_HDMD));
}
else if (!strcmp(dmfb_modedb[mode].name, "1080i")) {
ths8200_set_1080i_mode();
dispc_reg_merge(PINMUX0, PINMUX0_LFLDEN, PINMUX0_LFLDEN);
/* Enable all VENC, non-standard timing mode,
* master timing, HD, interlaced */
dispc_reg_out(VENC_VMOD,
(VENC_VMOD_VENC | VENC_VMOD_VMD |
VENC_VMOD_HDMD | VENC_VMOD_NSIT));
}
else
return -EINVAL;
#endif
}
w->dm->curr_mode = mode; w->dm->curr_mode = mode;
interlaced = dmfb_modedb[mode].vmode == FB_VMODE_INTERLACED ? 1 : 0; dm_win_mode_set(w, v);
/* different interlaced mode, update all other planes */
for (i = 0; i < DAVINCIFB_WINDOWS; i++) { for (i = 0; i < DAVINCIFB_WINDOWS; i++) {
struct dm_win_info *w_tmp = w->dm->windows[i]; struct dm_win_info *w_tmp = w->dm->windows[i];
if (!w_tmp) if (!w_tmp || w_tmp == w)
continue; continue;
/* set interlaced mode on all windows */ w_tmp->info.var.vmode = dmfb_modedb[mode].vmode;
set_interlaced(w_tmp, interlaced); dm_win_mode_set(w_tmp, &w_tmp->info.var);
/* set window position and size */
set_win_position(w_tmp, w_tmp->x, w_tmp->y, w_tmp->info.var.xres, w_tmp->info.var.yres / (interlaced + 1));
} }
dm_venc_mode_set(w->dm, &dmfb_modedb[mode], &dm_extended_modedb[mode]);
return 0; return 0;
} }
...@@ -1615,7 +1662,6 @@ static int davincifb_ioctl(struct fb_info *info, unsigned int cmd, ...@@ -1615,7 +1662,6 @@ static int davincifb_ioctl(struct fb_info *info, unsigned int cmd,
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
struct fb_fillrect rect; struct fb_fillrect rect;
struct zoom_params zoom; struct zoom_params zoom;
long std = 0;
unsigned int enable = 0; unsigned int enable = 0;
unsigned int pos = 0; unsigned int pos = 0;
unsigned int color = 0; unsigned int color = 0;
...@@ -1886,6 +1932,18 @@ static irqreturn_t davincifb_isr(int irq, void *arg) ...@@ -1886,6 +1932,18 @@ static irqreturn_t davincifb_isr(int irq, void *arg)
struct dm_info *dm = (struct dm_info *)arg; struct dm_info *dm = (struct dm_info *)arg;
int win; int win;
#ifdef VID0FIX
win = dm->windows[DAVINCIFB_WIN_VID0];
if ((win) && (dmfb_modedb[dm->curr_mode].vmode == FB_VMODE_INTERLACED)) {
int fld;
int curr_fld;
curr_fld = (dispc_reg_in(OSD_MISCCT) & OSD_MISCCT_PPSW) >> 2;
fld = ((dispc_reg_in(VENC_VSTAT) & 0x00000010) >> 4);
if (fld != curr_fld)
dispc_reg_merge(OSD_MISCCT, fld << 2, OSD_MISCCT_PPSW);
}
#else
if ((dispc_reg_in(VENC_VSTAT) & 0x00000010) == 0x10) { if ((dispc_reg_in(VENC_VSTAT) & 0x00000010) == 0x10) {
for (win = 0; win < DAVINCIFB_WINDOWS; win++) for (win = 0; win < DAVINCIFB_WINDOWS; win++)
{ {
...@@ -1903,7 +1961,9 @@ static irqreturn_t davincifb_isr(int irq, void *arg) ...@@ -1903,7 +1961,9 @@ static irqreturn_t davincifb_isr(int irq, void *arg)
} }
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} else { }
#endif
else {
++dm->vsync_cnt; ++dm->vsync_cnt;
wake_up_interruptible(&dm->vsync_wait); wake_up_interruptible(&dm->vsync_wait);
return IRQ_HANDLED; return IRQ_HANDLED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment