Intel FB: cleanup and misc interlaced mode support
cover Intel FB: cleanup and misc interlaced mode support
Hi,
I'll attach 4 patches for Intel FB (i830+) here:
1/4 - whitespace, bracket and other clean-ups (rather long)
working with kernel-style brackets instead of:
----------------
voidfunction_name (int arg) {
----------------
is a bit easier. I think it would be best to apply it in the beginning of the "patch period" to avoid potential conflicts.
2/4 - obvious changes and corrections
3/4 - the chip adds two halflines automatically in interlaced mode,
we have to force the number of lines to be even
4/4 - allow odd- and even-field-first in interlaced modes, and
proper sync to vertical retrace. It enables video players (got it working with MPlayer currently) to play perfect field-synced stream to RGB-connected (VGA output) TV set.
This patch adds #define FB_VMODE_ODD_FLD_FIRST 4 in include/linux/fb.h, to be able to force odd field first (analog broadcast PAL and some PAL DVD discs use it) instead of even field (bottom) first, as used by NTSC, DV PAL, some PAL DVDs etc. Interlaced-only thing.
This change need a coresponding change in fbset and probably in media players which want to set video mode themselves, I will do the fbset part and maybe MPlayer's if the fb.h patch is ok.
All four patches change only files in drivers/video/intelfb/, except patch 4/4 which also adds FB_VMODE_ODD_FLD_FIRST in include/linux/fb.h.
Tested on i915G in 1440x576 50 Hz (I) with PAL TV.
Signature · 1 line
Krzysztof Halasa
PATCH 1/4 Intel FB: whitespace, bracket and other clean-ups
Intel FB: whitespace, bracket and other clean-ups
drivers/video/intelfb/intelfb.h +6 -6
@@ -231,8 +231,8 @@ struct intelfb_hwstate {struct intelfb_heap_data {u32 physical;u8 __iomem *virtual; -u32 offset;// in GATT pages -u32 size;// in bytes +u32 offset;/* in GATT pages */ +u32 size;/* in bytes */ };#ifdef CONFIG_FB_INTEL_I2C
@@ -270,9 +270,9 @@ struct intelfb_info {struct intelfb_hwstate save_state;/* agpgart structs */ -struct agp_memory *gtt_fb_mem;// use all stolen memory or vram -struct agp_memory *gtt_ring_mem;// ring buffer -struct agp_memory *gtt_cursor_mem;// hw cursor +struct agp_memory *gtt_fb_mem;/* use all stolen memory or vram */ +struct agp_memory *gtt_ring_mem;/* ring buffer */ +struct agp_memory *gtt_cursor_mem;/* hw cursor */ /* use a gart reserved fb mem */ u8 fbmem_gart;
@@ -346,7 +346,7 @@ struct intelfb_info {/* driver registered */ int registered; - +/* index into plls */ int pll_index;
drivers/video/intelfb/intelfb_i2c.c +33 -27
113 lines not on this page · raw message
drivers/video/intelfb/intelfbdrv.c +73 -105
456 lines not on this page · raw message
drivers/video/intelfb/intelfbhw.c +83 -107
486 lines not on this page · raw message
drivers/video/intelfb/intelfbhw.h +7 -7
@@ -83,7 +83,7 @@*/ #define RING_MIN_FREE 64 -#define IPEHR 0x2088 +#define IPEHR 0x2088#define INSTDONE 0x2090#define PRI_RING_EMPTY 1
@@ -128,9 +128,9 @@#define GPIOA 0x5010#define GPIOB 0x5014 -#define GPIOC 0x5018 // this may be external DDC on i830 -#define GPIOD 0x501C // this is DVO DDC -#define GPIOE 0x5020 // this is DVO i2C +#define GPIOC 0x5018/* this may be external DDC on i830 */ +#define GPIOD 0x501C/* this is DVO DDC */ +#define GPIOE 0x5020/* this is DVO i2C */ #define GPIOF 0x5024/* PLL registers */
@@ -269,8 +269,8 @@#define PORT_ENABLE (1 << 31)#define PORT_PIPE_SELECT_SHIFT 30#define PORT_TV_FLAGS_MASK 0xFF -#define PORT_TV_FLAGS 0xC4 // ripped from my BIOS -// to understand and correct +#define PORT_TV_FLAGS 0xC4/* ripped from my BIOS +to understand and correct */ #define DVOA_SRCDIM 0x61124#define DVOB_SRCDIM 0x61144
@@ -369,7 +369,7 @@#define DISPPLANE_8BPP (0x2<<26)#define DISPPLANE_15_16BPP (0x4<<26)#define DISPPLANE_16BPP (0x5<<26) -#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) +#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)#define DISPPLANE_32BPP (0x7<<26)#define DISPPLANE_STEREO_ENABLE (1<<25)#define DISPPLANE_STEREO_DISABLE 0
PATCH 2/4 Intel FB: obvious changes and corrections
In reply to Krzysztof HalasaIntel FB: obvious changes and corrections
drivers/video/intelfb/intelfb.h +4 -1
@@ -355,7 +355,10 @@ struct intelfb_info {struct intelfb_output_rec output[MAX_OUTPUTS ]; }; -#define IS_I9XX (dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM)) +#define IS_I9XX (dinfo) (((dinfo)->chipset == INTEL_915G) || \ + ((dinfo)->chipset == INTEL_915GM) || \ + ((dinfo)->chipset == INTEL_945G) || \ + ((dinfo)->chipset==INTEL_945GM))#ifndef FBIO_WAITFORVSYNC #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
drivers/video/intelfb/intelfbhw.c +6 -8
@@ -434,14 +434,14 @@ void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp) { + u32 palette_reg = (dinfo->pipe == PIPE_A) ? +PALETTE_A :PALETTE_B ; +#if VERBOSE >0 DBG_MSG ("intelfbhw_setcolreg: %d: (%d, %d, %d)\n" , regno, red, green, blue);#endif -u32 palette_reg = (dinfo->pipe ==PIPE_A ) ? -PALETTE_A :PALETTE_B ; - OUTREG(palette_reg + (regno << 2), (red << PALETTE_8_RED_SHIFT) | (green << PALETTE_8_GREEN_SHIFT) |
@@ -1305,8 +1305,8 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo, count =0 ; do { - tmp_val[count%3] = INREG(0x70000); - if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2])) + tmp_val[count % 3] = INREG(PIPEA_DSL); + if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1] == tmp_val[2])) break; count++; udelay(1);
@@ -2004,7 +2004,6 @@ intelfbhw_enable_irq(struct intelfb_info *dinfo, int reenable) {void intelfbhw_disable_irq (struct intelfb_info *dinfo) { -u16 tmp;if (test_and_clear_bit (0 , &dinfo->irq_flags)) {if (dinfo->vsync.pan_display) {
@@ -2016,8 +2015,7 @@ intelfbhw_disable_irq(struct intelfb_info *dinfo) {OUTREG16 (IMR ,0xffff );OUTREG16 (IER ,0x0 ); - tmp =INREG16 (IIR ); -OUTREG16 (IIR , tmp); +OUTREG16 (IIR ,INREG16 (IIR ));/* clear IRQ requests */ spin_unlock_irq (&dinfo->int_lock);free_irq (dinfo->pdev->irq, dinfo);
drivers/video/intelfb/intelfbhw.h +3 -1
@@ -93,7 +93,7 @@#define IIR 0x20A4#define IMR 0x20A8#define VSYNC_PIPE_A_INTERRUPT (1 << 7) -#define PIPE_A_EVENT_INTERRUPT (1 << 4) +#define PIPE_A_EVENT_INTERRUPT (1 << 6)#define VSYNC_PIPE_B_INTERRUPT (1 << 5)#define PIPE_B_EVENT_INTERRUPT (1 << 4)#define HOST_PORT_EVENT_INTERRUPT (1 << 3)
@@ -276,6 +276,8 @@#define DVOB_SRCDIM 0x61144#define DVOC_SRCDIM 0x61164 +#define PIPEA_DSL 0x70000 +#define PIPEB_DSL 0x71000#define PIPEACONF 0x70008#define PIPEBCONF 0x71008#define PIPECONF_ENABLE (1 << 31)
PATCH 3/4 Intel FB: force even line count in interlaced mode
In reply to Krzysztof HalasaIntel FB: the chip adds two halflines automatically in interlaced mode, force even line count for the right timings.
drivers/video/intelfb/intelfbhw.c +15 -0
@@ -317,6 +317,14 @@ int intelfbhw_validate_mode(struct intelfb_info *dinfo, var->yres, VACTIVE_MASK + 1);return 1 ; } +if (var->xres <4 ) { +WRN_MSG ("X resolution too small (%d vs 4).\n" , var->xres); +return 1 ; + } +if (var->yres <4 ) { +WRN_MSG ("Y resolution too small (%d vs 4).\n" , var->yres); +return 1 ; + }/* Check for doublescan modes. */ if (var->vmode &FB_VMODE_DOUBLE ) {
@@ -324,6 +332,11 @@ int intelfbhw_validate_mode(struct intelfb_info *dinfo,return 1 ; } +if ((var->vmode &FB_VMODE_INTERLACED ) && (var->yres &1 )) { +WRN_MSG ("Odd number of lines in interlaced mode\n" ); +return 1 ; + } +/* Check if clock is OK. */ tmp =1000000000 / var->pixclock;if (tmp <MIN_CLOCK ) {
@@ -1127,6 +1140,8 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo, hblank_end); vactive = var->yres; +if (var->vmode &FB_VMODE_INTERLACED ) + vactive--;/* the chip adds 2 halflines automatically */ vsync_start = vactive + var->lower_margin; vsync_end = vsync_start + var->vsync_len; vtotal = vsync_end + var->upper_margin;
PATCH 4/4 Intel FB: more interlaced mode support
In reply to Krzysztof HalasaIntel FB: allow odd- and even-field-first in interlaced modes, and proper sync to vertical retrace
drivers/video/intelfb/intelfbhw.c +52 -39
@@ -376,7 +376,7 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) dinfo->vsync.pan_offset = offset;if ((var->activate &FB_ACTIVATE_VBL ) && - !intelfbhw_enable_irq (dinfo,0 )) + !intelfbhw_enable_irq (dinfo)) dinfo->vsync.pan_display =1 ;else { dinfo->vsync.pan_display =0 ;
@@ -1240,7 +1240,7 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo,u32 tmp;const u32 *dpll, *fp0, *fp1, *pipe_conf;const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss; -u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg; +u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg, pipe_stat_reg;u32 hsync_reg, htotal_reg, hblank_reg;u32 vsync_reg, vtotal_reg, vblank_reg;u32 src_size_reg;
@@ -1281,6 +1281,7 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo, fp0_reg =FPB0 ; fp1_reg =FPB1 ; pipe_conf_reg =PIPEBCONF ; + pipe_stat_reg =PIPEBSTAT ; hsync_reg =HSYNC_B ; htotal_reg =HTOTAL_B ; hblank_reg =HBLANK_B ;
@@ -1304,6 +1305,7 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo, fp0_reg =FPA0 ; fp1_reg =FPA1 ; pipe_conf_reg =PIPEACONF ; + pipe_stat_reg =PIPEASTAT ; hsync_reg =HSYNC_A ; htotal_reg =HTOTAL_A ; hblank_reg =HBLANK_A ;
@@ -1390,6 +1392,17 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo,OUTREG (vtotal_reg, *vt);OUTREG (src_size_reg, *ss); +switch (dinfo->info->var.vmode & (FB_VMODE_INTERLACED | +FB_VMODE_ODD_FLD_FIRST )) { +case FB_VMODE_INTERLACED |FB_VMODE_ODD_FLD_FIRST : +OUTREG (pipe_stat_reg,0xFFFF |PIPESTAT_FLD_EVT_ODD_EN ); +break ; +case FB_VMODE_INTERLACED :/* even lines first */ +OUTREG (pipe_stat_reg,0xFFFF |PIPESTAT_FLD_EVT_EVEN_EN ); +break ; +default :/* non-interlaced */ +OUTREG (pipe_stat_reg,0xFFFF );/* clear all status bits only */ + }/* Enable pipe */ OUTREG (pipe_conf_reg, *pipe_conf |PIPECONF_ENABLE );
@@ -1955,71 +1968,72 @@ void intelfbhw_cursor_reset(struct intelfb_info *dinfo) } } -static irqreturn_t -intelfbhw_irq (int irq,void *dev_id) { -int handled =0 ; +static irqreturn_t intelfbhw_irq (int irq,void *dev_id) +{u16 tmp;struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;spin_lock (&dinfo->int_lock); tmp =INREG16 (IIR ); - tmp &=VSYNC_PIPE_A_INTERRUPT ; +if (dinfo->info->var.vmode &FB_VMODE_INTERLACED ) + tmp &=PIPE_A_EVENT_INTERRUPT ; +else + tmp &=VSYNC_PIPE_A_INTERRUPT ;/* non-interlaced */ if (tmp ==0 ) {spin_unlock (&dinfo->int_lock); -return IRQ_RETVAL (handled); +return IRQ_RETVAL (0 );/* not us */ } -OUTREG16 (IIR , tmp); +/* clear status bits 0-15 ASAP and don't touch bits 16-31 */ +OUTREG (PIPEASTAT ,INREG (PIPEASTAT )); -if (tmp &VSYNC_PIPE_A_INTERRUPT ) { - dinfo->vsync.count++; -if (dinfo->vsync.pan_display) { - dinfo->vsync.pan_display =0 ; -OUTREG (DSPABASE , dinfo->vsync.pan_offset); - } -wake_up_interruptible (&dinfo->vsync.wait); - handled =1 ; +OUTREG16 (IIR , tmp); +if (dinfo->vsync.pan_display) { + dinfo->vsync.pan_display =0 ; +OUTREG (DSPABASE , dinfo->vsync.pan_offset); } + dinfo->vsync.count++; +wake_up_interruptible (&dinfo->vsync.wait); +spin_unlock (&dinfo->int_lock); -return IRQ_RETVAL (handled); +return IRQ_RETVAL (1 ); } -int -intelfbhw_enable_irq (struct intelfb_info *dinfo,int reenable) { - +int intelfbhw_enable_irq (struct intelfb_info *dinfo) +{ +u16 tmp;if (!test_and_set_bit (0 , &dinfo->irq_flags)) {if (request_irq (dinfo->pdev->irq, intelfbhw_irq,IRQF_SHARED , -"intelfb" , dinfo)) { +"intelfb" , dinfo)) {clear_bit (0 , &dinfo->irq_flags);return -EINVAL ; }spin_lock_irq (&dinfo->int_lock); -OUTREG16 (HWSTAM ,0xfffe ); -OUTREG16 (IMR ,0x0 ); -OUTREG16 (IER ,VSYNC_PIPE_A_INTERRUPT ); -spin_unlock_irq (&dinfo->int_lock); - }else if (reenable) { -u16 ier; - +OUTREG16 (HWSTAM ,0xfffe );/* i830 DRM uses ffff */ +OUTREG16 (IMR ,0 ); + }else spin_lock_irq (&dinfo->int_lock); - ier =INREG16 (IER ); -if ((ier &VSYNC_PIPE_A_INTERRUPT )) { -DBG_MSG ("someone disabled the IRQ [%08X]\n" , ier); -OUTREG (IER ,VSYNC_PIPE_A_INTERRUPT ); - } -spin_unlock_irq (&dinfo->int_lock); + +if (dinfo->info->var.vmode &FB_VMODE_INTERLACED ) + tmp =PIPE_A_EVENT_INTERRUPT ; +else + tmp =VSYNC_PIPE_A_INTERRUPT ;/* non-interlaced */ +if (tmp !=INREG16 (IER )) { +DBG_MSG ("changing IER to 0x%X\n" , tmp); +OUTREG16 (IER , tmp); } + +spin_unlock_irq (&dinfo->int_lock);return 0 ; } -void -intelfbhw_disable_irq (struct intelfb_info *dinfo) { - +void intelfbhw_disable_irq (struct intelfb_info *dinfo) +{if (test_and_clear_bit (0 , &dinfo->irq_flags)) {if (dinfo->vsync.pan_display) { dinfo->vsync.pan_display =0 ;
@@ -2051,7 +2065,7 @@ int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe)return -ENODEV ; } - ret =intelfbhw_enable_irq (dinfo,0 ); + ret =intelfbhw_enable_irq (dinfo);if (ret)return ret;
@@ -2061,7 +2075,6 @@ int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe)if (ret <0 )return ret;if (ret ==0 ) { -intelfbhw_enable_irq (dinfo,1 );DBG_MSG ("wait_for_vsync timed out!\n" );return -ETIMEDOUT ; }
drivers/video/intelfb/intelfbhw.h +29 -1
@@ -280,6 +280,9 @@#define PIPEB_DSL 0x71000#define PIPEACONF 0x70008#define PIPEBCONF 0x71008 +#define PIPEASTAT 0x70024/* bits 0-15 are "write 1 to clear" */ +#define PIPEBSTAT 0x71024 +#define PIPECONF_ENABLE (1 << 31)#define PIPECONF_DISABLE 0#define PIPECONF_DOUBLE_WIDE (1 << 30)
@@ -293,6 +296,31 @@#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)#define PIPECONF_INTERLACE_MASK (7 << 21) +/* enable bits, write 1 to enable */ +#define PIPESTAT_FIFO_UNDERRUN (1 << 31) +#define PIPESTAT_CRC_ERROR_EN (1 << 29) +#define PIPESTAT_CRC_DONE_EN (1 << 28) +#define PIPESTAT_HOTPLUG_EN (1 << 26) +#define PIPESTAT_VERTICAL_SYNC_EN (1 << 25) +#define PIPESTAT_DISPLINE_COMP_EN (1 << 24) +#define PIPESTAT_FLD_EVT_ODD_EN (1 << 21) +#define PIPESTAT_FLD_EVT_EVEN_EN (1 << 20) +#define PIPESTAT_TV_HOTPLUG_EN (1 << 18) +#define PIPESTAT_VBLANK_EN (1 << 17) +#define PIPESTAT_OVL_UPDATE_EN (1 << 16) +/* status bits, write 1 to clear */ +#define PIPESTAT_HOTPLUG_STATE (1 << 15) +#define PIPESTAT_CRC_ERROR (1 << 13) +#define PIPESTAT_CRC_DONE (1 << 12) +#define PIPESTAT_HOTPLUG (1 << 10) +#define PIPESTAT_VSYNC (1 << 9) +#define PIPESTAT_DISPLINE_COMP (1 << 8) +#define PIPESTAT_FLD_EVT_ODD (1 << 5) +#define PIPESTAT_FLD_EVT_EVEN (1 << 4) +#define PIPESTAT_TV_HOTPLUG (1 << 2) +#define PIPESTAT_VBLANK (1 << 1) +#define PIPESTAT_OVL_UPDATE (1 << 0) +#define DISPARB 0x70030#define DISPARB_AEND_MASK 0x1ff#define DISPARB_AEND_SHIFT 0
@@ -573,7 +601,7 @@ extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,extern void intelfbhw_cursor_load (struct intelfb_info *dinfo,int width,int height,u8 *data);extern void intelfbhw_cursor_reset (struct intelfb_info *dinfo); -extern int intelfbhw_enable_irq (struct intelfb_info *dinfo,int reenable); +extern int intelfbhw_enable_irq (struct intelfb_info *dinfo);extern void intelfbhw_disable_irq (struct intelfb_info *dinfo);extern int intelfbhw_wait_for_vsync (struct intelfb_info *dinfo,u32 pipe);
include/linux/fb.h +1 -0
@@ -206,6 +206,7 @@ struct fb_bitfield {#define FB_VMODE_NONINTERLACED 0/* non interlaced */ #define FB_VMODE_INTERLACED 1/* interlaced */ #define FB_VMODE_DOUBLE 2/* double scan */ +#define FB_VMODE_ODD_FLD_FIRST 4/* interlaced: top line first */ #define FB_VMODE_MASK 255#define FB_VMODE_YWRAP 256/* ywrap instead of panning */