drm/i915: Fix SDVO TV support
This brings SDVO TV support from 2D driver, including origin fix f1ca56e17d0 and later fix 2fcf4fcccfe. Also fix wrong modeline definitions for SDVO TV. Signed-off-by: Zhenyu Wang <zhenyu.z.wang@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
e642c6f1d2
commit
7026d4ac1f
2 changed files with 108 additions and 52 deletions
|
@ -1106,6 +1106,26 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* SDVO TV has fixed PLL values depend on its clock range,
|
||||
this mirrors vbios setting. */
|
||||
if (is_sdvo && is_tv) {
|
||||
if (adjusted_mode->clock >= 100000
|
||||
&& adjusted_mode->clock < 140500) {
|
||||
clock.p1 = 2;
|
||||
clock.p2 = 10;
|
||||
clock.n = 3;
|
||||
clock.m1 = 16;
|
||||
clock.m2 = 8;
|
||||
} else if (adjusted_mode->clock >= 140500
|
||||
&& adjusted_mode->clock <= 200000) {
|
||||
clock.p1 = 1;
|
||||
clock.p2 = 10;
|
||||
clock.n = 6;
|
||||
clock.m1 = 12;
|
||||
clock.m2 = 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_IGD(dev))
|
||||
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
|
||||
else
|
||||
|
|
|
@ -911,6 +911,27 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
|
|||
SDVO_HBUF_TX_VSYNC);
|
||||
}
|
||||
|
||||
static void intel_sdvo_set_tv_format(struct intel_output *output)
|
||||
{
|
||||
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
||||
struct intel_sdvo_tv_format *format, unset;
|
||||
u8 status;
|
||||
|
||||
format = &sdvo_priv->tv_format;
|
||||
memset(&unset, 0, sizeof(unset));
|
||||
if (memcmp(format, &unset, sizeof(*format))) {
|
||||
DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
format->ntsc_m = 1;
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
|
||||
sizeof(*format));
|
||||
status = intel_sdvo_read_response(output, NULL, 0);
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
DRM_DEBUG("%s: Failed to set TV format\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
|
@ -955,6 +976,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|||
&input_dtd);
|
||||
intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
|
||||
|
||||
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
||||
|
||||
mode->clock = adjusted_mode->clock;
|
||||
|
||||
adjusted_mode->clock *=
|
||||
intel_sdvo_get_pixel_multiplier(mode);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -999,6 +1026,11 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|||
sdvox |= SDVO_AUDIO_ENABLE;
|
||||
}
|
||||
|
||||
/* We have tried to get input timing in mode_fixup, and filled into
|
||||
adjusted_mode */
|
||||
if (sdvo_priv->is_tv)
|
||||
intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
|
||||
else
|
||||
intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
|
||||
|
||||
/* If it's a TV, we already set the output timing in mode_fixup.
|
||||
|
@ -1014,6 +1046,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|||
/* Set the input timing to the screen. Assume always input 0. */
|
||||
intel_sdvo_set_target_input(output, true, false);
|
||||
|
||||
if (sdvo_priv->is_tv)
|
||||
intel_sdvo_set_tv_format(output);
|
||||
|
||||
/* We would like to use intel_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
|
||||
|
@ -1382,7 +1417,7 @@ static void
|
|||
intel_sdvo_check_tv_format(struct intel_output *output)
|
||||
{
|
||||
struct intel_sdvo_priv *dev_priv = output->dev_priv;
|
||||
struct intel_sdvo_tv_format format, unset;
|
||||
struct intel_sdvo_tv_format format;
|
||||
uint8_t status;
|
||||
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
|
||||
|
@ -1390,15 +1425,7 @@ intel_sdvo_check_tv_format(struct intel_output *output)
|
|||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
memset(&unset, 0, sizeof(unset));
|
||||
if (memcmp(&format, &unset, sizeof(format))) {
|
||||
DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
|
||||
SDVO_NAME(dev_priv));
|
||||
|
||||
format.ntsc_m = true;
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0);
|
||||
status = intel_sdvo_read_response(output, NULL, 0);
|
||||
}
|
||||
memcpy(&dev_priv->tv_format, &format, sizeof(format));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1407,68 +1434,70 @@ intel_sdvo_check_tv_format(struct intel_output *output)
|
|||
* XXX: all 60Hz refresh?
|
||||
*/
|
||||
struct drm_display_mode sdvo_tv_modes[] = {
|
||||
{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815680, 321, 384, 416,
|
||||
200, 0, 232, 201, 233, 4196112, 0,
|
||||
{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384,
|
||||
416, 0, 200, 201, 232, 233, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814080, 321, 384, 416,
|
||||
240, 0, 272, 241, 273, 4196112, 0,
|
||||
{ DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814, 320, 321, 384,
|
||||
416, 0, 240, 241, 272, 273, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910080, 401, 464, 496,
|
||||
300, 0, 332, 301, 333, 4196112, 0,
|
||||
{ DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910, 400, 401, 464,
|
||||
496, 0, 300, 301, 332, 333, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913280, 641, 704, 736,
|
||||
350, 0, 382, 351, 383, 4196112, 0,
|
||||
{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913, 640, 641, 704,
|
||||
736, 0, 350, 351, 382, 383, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736,
|
||||
400, 0, 432, 401, 433, 4196112, 0,
|
||||
{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121, 640, 641, 704,
|
||||
736, 0, 400, 401, 432, 433, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736,
|
||||
400, 0, 432, 401, 433, 4196112, 0,
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 22654, 640, 641, 704,
|
||||
736, 0, 480, 481, 512, 513, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624000, 705, 768, 800,
|
||||
480, 0, 512, 481, 513, 4196112, 0,
|
||||
{ DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624, 704, 705, 768,
|
||||
800, 0, 480, 481, 512, 513, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232000, 705, 768, 800,
|
||||
576, 0, 608, 577, 609, 4196112, 0,
|
||||
{ DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232, 704, 705, 768,
|
||||
800, 0, 576, 577, 608, 609, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751680, 721, 784, 816,
|
||||
350, 0, 382, 351, 383, 4196112, 0,
|
||||
{ DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751, 720, 721, 784,
|
||||
816, 0, 350, 351, 382, 383, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199680, 721, 784, 816,
|
||||
400, 0, 432, 401, 433, 4196112, 0,
|
||||
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199, 720, 721, 784,
|
||||
816, 0, 400, 401, 432, 433, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116480, 721, 784, 816,
|
||||
480, 0, 512, 481, 513, 4196112, 0,
|
||||
{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116, 720, 721, 784,
|
||||
816, 0, 480, 481, 512, 513, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054080, 721, 784, 816,
|
||||
540, 0, 572, 541, 573, 4196112, 0,
|
||||
{ DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054, 720, 721, 784,
|
||||
816, 0, 540, 541, 572, 573, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816640, 721, 784, 816,
|
||||
576, 0, 608, 577, 609, 4196112, 0,
|
||||
{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816, 720, 721, 784,
|
||||
816, 0, 576, 577, 608, 609, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570560, 769, 832, 864,
|
||||
576, 0, 608, 577, 609, 4196112, 0,
|
||||
{ DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570, 768, 769, 832,
|
||||
864, 0, 576, 577, 608, 609, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030080, 801, 864, 896,
|
||||
600, 0, 632, 601, 633, 4196112, 0,
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030, 800, 801, 864,
|
||||
896, 0, 600, 601, 632, 633, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581760, 833, 896, 928,
|
||||
624, 0, 656, 625, 657, 4196112, 0,
|
||||
{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581, 832, 833, 896,
|
||||
928, 0, 624, 625, 656, 657, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707040, 921, 984, 1016,
|
||||
766, 0, 798, 767, 799, 4196112, 0,
|
||||
{ DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707, 920, 921, 984,
|
||||
1016, 0, 766, 767, 798, 799, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827200, 1025, 1088, 1120,
|
||||
768, 0, 800, 769, 801, 4196112, 0,
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827, 1024, 1025, 1088,
|
||||
1120, 0, 768, 769, 800, 801, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265920, 1281, 1344, 1376,
|
||||
1024, 0, 1056, 1025, 1057, 4196112, 0,
|
||||
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265, 1280, 1281, 1344,
|
||||
1376, 0, 1024, 1025, 1056, 1057, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
};
|
||||
|
||||
static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_output *output = to_intel_output(connector);
|
||||
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
||||
struct intel_sdvo_sdtv_resolution_request tv_res;
|
||||
uint32_t reply = 0;
|
||||
uint8_t status;
|
||||
int i = 0;
|
||||
|
@ -1478,15 +1507,22 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|||
/* Read the list of supported input resolutions for the selected TV
|
||||
* format.
|
||||
*/
|
||||
memset(&tv_res, 0, sizeof(tv_res));
|
||||
memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
|
||||
NULL, 0);
|
||||
&tv_res, sizeof(tv_res));
|
||||
status = intel_sdvo_read_response(output, &reply, 3);
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++)
|
||||
if (reply & (1 << i))
|
||||
drm_mode_probed_add(connector, &sdvo_tv_modes[i]);
|
||||
if (reply & (1 << i)) {
|
||||
struct drm_display_mode *nmode;
|
||||
nmode = drm_mode_duplicate(connector->dev,
|
||||
&sdvo_tv_modes[i]);
|
||||
if (nmode)
|
||||
drm_mode_probed_add(connector, nmode);
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_sdvo_get_modes(struct drm_connector *connector)
|
||||
|
|
Loading…
Reference in a new issue