diff options
author | Keith Packard <keithp@guitar.keithp.com> | 2006-11-19 00:40:46 -0800 |
---|---|---|
committer | Keith Packard <keithp@guitar.keithp.com> | 2006-11-19 00:40:46 -0800 |
commit | 28224af3d90a1a08d54a865dfaf20184330fe8a4 (patch) | |
tree | 6e4482eb9ab961e26efc2b43374339d41d311189 /src/i830_tv.c | |
parent | 816fc1a76a5ac738e41b172ba8f43137c1521328 (diff) |
Preliminary 945 TV output. Color key is broken. Fixed mode.
TV output is generating video with this patch, but the color burst
signal is incorrect somehow.
Diffstat (limited to 'src/i830_tv.c')
-rw-r--r-- | src/i830_tv.c | 176 |
1 files changed, 154 insertions, 22 deletions
diff --git a/src/i830_tv.c b/src/i830_tv.c index c597db53..f938d5cc 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -279,8 +279,74 @@ i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, /* Disable the encoder while we set up the pipe. */ OUTREG(TV_CTL, INREG(TV_CTL) & ~TV_ENC_ENABLE); + /* XXX match BIOS for now */ + OUTREG(ADPA, 0x40008C18); } +static const CARD32 h_luma[60] = { + 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140, + 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000, + 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160, + 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780, + 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50, + 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20, + 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0, + 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0, + 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020, + 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140, + 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20, + 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848, + 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900, + 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080, + 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060, +}; + +static const CARD32 h_chroma[60] = { + 0xB1403000, 0x2E203500, 0x35002E20, 0x3000B140, + 0x35A0B160, 0x2DC02E80, 0xB1403480, 0xB1603000, + 0x2EA03640, 0x34002D80, 0x3000B120, 0x36E0B160, + 0x2D202EF0, 0xB1203380, 0xB1603000, 0x2F303780, + 0x33002CC0, 0x3000B100, 0x3820B160, 0x2C802F50, + 0xB10032A0, 0xB1603000, 0x2F9038C0, 0x32202C20, + 0x3000B0E0, 0x3980B160, 0x2BC02FC0, 0xB0E031C0, + 0xB1603000, 0x2FF03A20, 0x31602B60, 0xB020B0C0, + 0x3AE0B160, 0x2B001810, 0xB0C03120, 0xB140B020, + 0x18283BA0, 0x30C02A80, 0xB020B0A0, 0x3C60B140, + 0x2A201838, 0xB0A03080, 0xB120B020, 0x18383D20, + 0x304029C0, 0xB040B080, 0x3DE0B100, 0x29601848, + 0xB0803000, 0xB100B040, 0x18483EC0, 0xB0402900, + 0xB040B060, 0x3F80B0C0, 0x28801858, 0xB060B080, + 0xB0A0B060, 0x18602820, 0xB0A02820, 0x0000B060, +}; + +static const CARD32 v_luma[43] = { + 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0, + 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540, + 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00, + 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000, + 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00, + 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40, + 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240, + 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00, + 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0, + 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840, + 0x28003100, 0x28002F00, 0x00003100, +}; + +static const CARD32 v_chroma[43] = { + 0x36403000, 0x2D002CC0, 0x30003640, 0x2D0036C0, + 0x35C02CC0, 0x37403000, 0x2C802D40, 0x30003540, + 0x2D8037C0, 0x34C02C40, 0x38403000, 0x2BC02E00, + 0x30003440, 0x2E2038C0, 0x34002B80, 0x39803000, + 0x2B402E40, 0x30003380, 0x2E603A00, 0x33402B00, + 0x3A803040, 0x2A802EA0, 0x30403300, 0x2EC03B40, + 0x32802A40, 0x3C003040, 0x2A002EC0, 0x30803240, + 0x2EC03C80, 0x320029C0, 0x3D403080, 0x29402F00, + 0x308031C0, 0x2F203DC0, 0x31802900, 0x3E8030C0, + 0x28802F40, 0x30C03140, 0x2F203F40, 0x31402840, + 0x28003100, 0x28002F00, 0x00003100, +}; + static void i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, DisplayModePtr pMode) @@ -293,6 +359,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, CARD32 hctl1, hctl2, hctl3; CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7; CARD32 scctl1, scctl2, scctl3; + int i; /* Need to actually choose or construct the appropriate * mode. For now, just set the first one in the list, with @@ -302,10 +369,6 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ]; type = i830_tv_detect_type(pScrn, output); - if (type == TV_TYPE_UNKNOWN) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Defaulting TV to SVIDEO\n"); - type = TV_TYPE_SVIDEO; - } hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) | (tv_mode->htotal << TV_HTOTAL_SHIFT); @@ -355,10 +418,13 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, case TV_TYPE_COMPONENT: tv_ctl |= TV_ENC_OUTPUT_COMPONENT; break; - default: case TV_TYPE_SVIDEO: tv_ctl |= TV_ENC_OUTPUT_SVIDEO; break; + default: + case TV_TYPE_UNKNOWN: + tv_ctl |= TV_ENC_OUTPUT_SVIDEO_COMPOSITE; + break; } tv_ctl |= tv_mode->oversample; if (tv_mode->progressive) @@ -366,11 +432,12 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, if (sc_mode->pal_burst) tv_ctl |= TV_PAL_BURST; - scctl1 = TV_SC_DDA1_EN | TV_SC_DDA1_EN; + scctl1 = TV_SC_DDA1_EN | TV_SC_DDA2_EN; if (sc_mode->dda3_size != 0) scctl1 |= TV_SC_DDA3_EN; scctl1 |= sc_mode->sc_reset; /* XXX: set the burst level */ + scctl1 |= 113 << TV_BURST_LEVEL_SHIFT; /* from BIOS */ scctl1 |= sc_mode->dda1_inc << TV_SCDDA1_INC_SHIFT; scctl2 = sc_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT | @@ -400,6 +467,28 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, OUTREG(TV_SC_CTL_1, scctl1); OUTREG(TV_SC_CTL_2, scctl2); OUTREG(TV_SC_CTL_3, scctl3); + /* XXX match BIOS */ + OUTREG(TV_CSC_Y, 0x0332012D); + OUTREG(TV_CSC_Y2, 0x07D30133); + OUTREG(TV_CSC_U, 0x076A0564); + OUTREG(TV_CSC_U2, 0x030D0200); + OUTREG(TV_CSC_V, 0x037A033D); + OUTREG(TV_CSC_V2, 0x06F60200); + OUTREG(TV_CLR_KNOBS, 0x00606000); + OUTREG(TV_CLR_LEVEL, 0x013C010A); + OUTREG(TV_WIN_POS, 0x00360024); + OUTREG(TV_WIN_SIZE, 0x02640198); + OUTREG(TV_FILTER_CTL_1, 0x8000085E); + OUTREG(TV_FILTER_CTL_2, 0x00017878); + OUTREG(TV_FILTER_CTL_3, 0x0000BC3C); + for (i = 0; i < 60; i++) + OUTREG(TV_H_LUMA_0 + (i <<2), h_luma[i]); + for (i = 0; i < 60; i++) + OUTREG(TV_H_CHROMA_0 + (i <<2), h_chroma[i]); + for (i = 0; i < 43; i++) + OUTREG(TV_V_LUMA_0 + (i <<2), v_luma[i]); + for (i = 0; i < 43; i++) + OUTREG(TV_V_CHROMA_0 + (i <<2), v_chroma[i]); OUTREG(TV_DAC, 0); OUTREG(TV_CTL, tv_ctl); @@ -414,7 +503,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, static enum detect_status i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) { - return OUTPUT_STATUS_UNKNOWN; + return OUTPUT_STATUS_CONNECTED; } /** @@ -426,31 +515,74 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) static DisplayModePtr i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) { - return NULL; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr new; + char stmp[32]; + + (void) pI830; + new = xnfcalloc(1, sizeof (DisplayModeRec)); + sprintf(stmp, "480i"); + new->name = xnfalloc(strlen(stmp) + 1); + strcpy(new->name, stmp); + + new->Clock = 108000; + + /* + new->HDisplay = 640; + new->HSyncStart = 664; + new->HSyncEnd = 704; + new->HTotal = 832; + + new->VDisplay = 480; + new->VSyncStart = 489; + new->VSyncEnd = 491; + new->VTotal = 520; + */ + new->HDisplay = 1024; + new->HSyncStart = 1048; + new->HSyncEnd = 1184; + new->HTotal = 1344; + + new->VDisplay = 768; + new->VSyncStart = 771; + new->VSyncEnd = 777; + new->VTotal = 806; + + new->type = M_T_PREFERRED; + + return new; } void i830_tv_init(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - + I830OutputPtr output = &pI830->output[pI830->num_outputs]; + struct i830_tv_priv *dev_priv; + if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; - pI830->output[pI830->num_outputs].dev_priv = - malloc(sizeof(struct i830_tv_priv)); - if (pI830->output[pI830->num_outputs].dev_priv == NULL) + output->type = I830_OUTPUT_TVOUT; + output->pipe = 0; + output->enabled = FALSE; + output->load_detect_temp = FALSE; + + output->dpms = i830_tv_dpms; + output->save = i830_tv_save; + output->restore = i830_tv_restore; + output->mode_valid = i830_tv_mode_valid; + output->pre_set_mode = i830_tv_pre_set_mode; + output->post_set_mode = i830_tv_post_set_mode; + output->detect = i830_tv_detect; + output->get_modes = i830_tv_get_modes; + + dev_priv = xnfcalloc(1, sizeof(struct i830_tv_priv)); + + if (dev_priv == NULL) return; - pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG; - pI830->output[pI830->num_outputs].dpms = i830_tv_dpms; - pI830->output[pI830->num_outputs].save = i830_tv_save; - pI830->output[pI830->num_outputs].restore = i830_tv_restore; - pI830->output[pI830->num_outputs].mode_valid = i830_tv_mode_valid; - pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode; - pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode; - pI830->output[pI830->num_outputs].detect = i830_tv_detect; - pI830->output[pI830->num_outputs].get_modes = i830_tv_get_modes; - + output->dev_priv = dev_priv; + ErrorF ("TV out is output %d\n", pI830->num_outputs); pI830->num_outputs++; } |