diff --git a/src/i830_display.c b/src/i830_display.c index 7a8e96d..7f17cda 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1319,11 +1319,11 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; - if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) && - !is_tv) + if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830))) { - int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock; + int sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; + ErrorF("zhen: set CRTC sdvo multiply %d\n", sdvo_pixel_multiply); } } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 0750166..410ee24 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -702,13 +702,13 @@ i830_sdvo_get_dtd_from_mode(struct i830_sdvo_dtd *dtd, DisplayModePtr mode) dtd->part1.v_high = (((height >> 8) & 0xf) << 4) | ((v_blank_len >> 8) & 0xf); - dtd->part2.h_sync_off = h_sync_offset; + dtd->part2.h_sync_off = h_sync_offset & 0xff; dtd->part2.h_sync_width = h_sync_len & 0xff; dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | (v_sync_len & 0xf); dtd->part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | - ((v_sync_len & 0x30) >> 4); + ((v_sync_len & 0x300) >> 8); dtd->part2.dtd_flags = 0x18; if (mode->Flags & V_PHSYNC) @@ -724,27 +724,10 @@ i830_sdvo_get_dtd_from_mode(struct i830_sdvo_dtd *dtd, DisplayModePtr mode) static void i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd) { - uint16_t width, height; - uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; - uint16_t h_sync_offset, v_sync_offset; - - width = mode->CrtcHDisplay; - height = mode->CrtcVDisplay; - - /* do some mode translations */ - h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart; - h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; - - v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart; - v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - - h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart; - v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart; - mode->HDisplay = dtd->part1.h_active; mode->HDisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; mode->HSyncStart = mode->HDisplay + dtd->part2.h_sync_off; - mode->HSyncStart += (dtd->part2.sync_off_width_high & 0xa0) << 2; + mode->HSyncStart += (dtd->part2.sync_off_width_high & 0xc0) << 2; mode->HSyncEnd = mode->HSyncStart + dtd->part2.h_sync_width; mode->HSyncEnd += (dtd->part2.sync_off_width_high & 0x30) << 4; mode->HTotal = mode->HDisplay + dtd->part1.h_blank; @@ -754,7 +737,7 @@ i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd) mode->VDisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; mode->VSyncStart = mode->VDisplay; mode->VSyncStart += (dtd->part2.v_sync_off_width >> 4) & 0xf; - mode->VSyncStart += (dtd->part2.sync_off_width_high & 0x0a) << 2; + mode->VSyncStart += (dtd->part2.sync_off_width_high & 0x0c) << 2; mode->VSyncStart += dtd->part2.v_sync_off_high & 0xc0; mode->VSyncEnd = mode->VSyncStart + (dtd->part2.v_sync_off_width & 0xf); mode->VSyncEnd += (dtd->part2.sync_off_width_high & 0x3) << 4; @@ -763,7 +746,7 @@ i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd) mode->Clock = dtd->part1.clock * 10; - mode->Flags &= (V_PHSYNC | V_PVSYNC); + mode->Flags &= ~(V_PHSYNC | V_PVSYNC); if (dtd->part2.dtd_flags & 0x2) mode->Flags |= V_PHSYNC; if (dtd->part2.dtd_flags & 0x4) @@ -953,6 +936,30 @@ static void i830_sdvo_set_avi_infoframe(xf86OutputPtr output, SDVO_HBUF_TX_VSYNC); } +static void +i830_sdvo_set_tv_format(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + struct i830_sdvo_tv_format *format, unset; + uint8_t status; + + format = &dev_priv->tv_format; + memset(&unset, 0, sizeof(unset)); + if (memcmp(format, &unset, sizeof(*format))) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "%s: Choosing default TV format of NTSC-M\n", + SDVO_NAME(dev_priv)); + format->ntsc_m = 1; + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format, + sizeof(*format)); + status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + ErrorF("zhen: set TV format failed\n"); + } +} + static Bool i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) @@ -1045,30 +1052,38 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, sdvox |= SDVO_AUDIO_ENABLE; } - i830_sdvo_get_dtd_from_mode(&input_dtd, mode); + if (dev_priv->is_tv) + i830_sdvo_set_tv_format(output); + + /* We have tried to get input timing in mode_fixup, and filled into + adjusted_mode */ + if (dev_priv->is_tv) + i830_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + else + i830_sdvo_get_dtd_from_mode(&input_dtd, mode); /* If it's a TV, we already set the output timing in mode_fixup. * Otherwise, the output timing is equal to the input timing. */ + i830_sdvo_set_target_output(output, dev_priv->controlled_output); + /* Set the input timing to the screen. Assume always input 0. */ + i830_sdvo_set_target_input(output, TRUE, FALSE); + if (!dev_priv->is_tv) { /* Set the output timing to the screen */ - i830_sdvo_set_target_output(output, dev_priv->controlled_output); i830_sdvo_set_output_timing(output, &input_dtd); } - /* Set the input timing to the screen. Assume always input 0. */ - i830_sdvo_set_target_input(output, TRUE, FALSE); - /* We would like to use i830_sdvo_create_preferred_input_timing() to * provide the device with a timing it can support, if it supports that * feature. However, presumably we would need to adjust the CRTC to output * the preferred timing, and we don't support that currently. */ #if 0 - success = i830_sdvo_create_preferred_input_timing(output, clock, - width, height); + success = i830_sdvo_create_preferred_input_timing(output, + mode->Clock / 10, mode->HDisplay, mode->VDisplay); if (success) { - struct i830_sdvo_dtd *input_dtd; + struct i830_sdvo_dtd input_dtd; i830_sdvo_get_preferred_input_timing(output, &input_dtd); i830_sdvo_set_input_timing(output, &input_dtd); @@ -1077,7 +1092,10 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, i830_sdvo_set_input_timing(output, &input_dtd); #endif - switch (i830_sdvo_get_pixel_multiplier(mode)) { + sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); + ErrorF("zhen: set clock rate mult %d\n", sdvo_pixel_multiply); + + switch (sdvo_pixel_multiply) { case 1: i830_sdvo_set_clock_rate_mult(output, SDVO_CLOCK_RATE_MULT_1X); break; @@ -1109,7 +1127,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; - sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); if (IS_I965G(pI830)) { /* done in crtc_mode_set as the dpll_md reg must be written early */ } else if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) { @@ -1567,6 +1584,7 @@ i830_sdvo_check_tv_format(xf86OutputPtr output) if (status != SDVO_CMD_STATUS_SUCCESS) return; + /* memset(&unset, 0, sizeof(unset)); if (memcmp(&format, &unset, sizeof(format))) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1574,9 +1592,14 @@ i830_sdvo_check_tv_format(xf86OutputPtr output) SDVO_NAME(dev_priv)); format.ntsc_m = TRUE; - i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0); + i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format, + sizeof(format)); status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + ErrorF("zhen: set TV format failed\n"); } + */ + memcpy(&dev_priv->tv_format, &format, sizeof(format)); } static DisplayModePtr @@ -1586,6 +1609,7 @@ i830_sdvo_get_tv_modes(xf86OutputPtr output) struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; DisplayModePtr modes = NULL; struct i830_sdvo_sdtv_resolution_reply *res = &dev_priv->sdtv_resolutions; + struct i830_sdvo_sdtv_resolution_request tv_res; uint8_t status; float refresh = 60; /* XXX */ @@ -1593,7 +1617,10 @@ i830_sdvo_get_tv_modes(xf86OutputPtr output) /* Read the list of supported input resolutions for the selected TV format. */ - i830_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, NULL, 0); + memset(&tv_res, 0, sizeof(tv_res)); + memcpy(&tv_res, &dev_priv->tv_format, sizeof(tv_res)); + i830_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, + &tv_res, sizeof(tv_res)); status = i830_sdvo_read_response(output, res, sizeof(*res)); if (status != SDVO_CMD_STATUS_SUCCESS) return NULL;