aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_sdvo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c193
1 files changed, 108 insertions, 85 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index fbe6f3931b1..7b31f55f55c 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -273,20 +273,20 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
273 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; 273 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
274 int i; 274 int i;
275 275
276 DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); 276 printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
277 for (i = 0; i < args_len; i++) 277 for (i = 0; i < args_len; i++)
278 printk("%02X ", ((u8 *)args)[i]); 278 printk(KERN_DEBUG "%02X ", ((u8 *)args)[i]);
279 for (; i < 8; i++) 279 for (; i < 8; i++)
280 printk(" "); 280 printk(KERN_DEBUG " ");
281 for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { 281 for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
282 if (cmd == sdvo_cmd_names[i].cmd) { 282 if (cmd == sdvo_cmd_names[i].cmd) {
283 printk("(%s)", sdvo_cmd_names[i].name); 283 printk(KERN_DEBUG "(%s)", sdvo_cmd_names[i].name);
284 break; 284 break;
285 } 285 }
286 } 286 }
287 if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) 287 if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
288 printk("(%02X)",cmd); 288 printk(KERN_DEBUG "(%02X)", cmd);
289 printk("\n"); 289 printk(KERN_DEBUG "\n");
290} 290}
291#else 291#else
292#define intel_sdvo_debug_write(o, c, a, l) 292#define intel_sdvo_debug_write(o, c, a, l)
@@ -323,17 +323,18 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output,
323 u8 status) 323 u8 status)
324{ 324{
325 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; 325 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
326 int i;
326 327
327 DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv)); 328 printk(KERN_DEBUG "%s: R: ", SDVO_NAME(sdvo_priv));
328 for (i = 0; i < response_len; i++) 329 for (i = 0; i < response_len; i++)
329 printk("%02X ", ((u8 *)response)[i]); 330 printk(KERN_DEBUG "%02X ", ((u8 *)response)[i]);
330 for (; i < 8; i++) 331 for (; i < 8; i++)
331 printk(" "); 332 printk(KERN_DEBUG " ");
332 if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) 333 if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
333 printk("(%s)", cmd_status_names[status]); 334 printk(KERN_DEBUG "(%s)", cmd_status_names[status]);
334 else 335 else
335 printk("(??? %d)", status); 336 printk(KERN_DEBUG "(??? %d)", status);
336 printk("\n"); 337 printk(KERN_DEBUG "\n");
337} 338}
338#else 339#else
339#define intel_sdvo_debug_response(o, r, l, s) 340#define intel_sdvo_debug_response(o, r, l, s)
@@ -588,9 +589,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
588 struct intel_sdvo_preferred_input_timing_args args; 589 struct intel_sdvo_preferred_input_timing_args args;
589 uint8_t status; 590 uint8_t status;
590 591
592 memset(&args, 0, sizeof(args));
591 args.clock = clock; 593 args.clock = clock;
592 args.width = width; 594 args.width = width;
593 args.height = height; 595 args.height = height;
596 args.interlace = 0;
597 args.scaled = 0;
594 intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, 598 intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
595 &args, sizeof(args)); 599 &args, sizeof(args));
596 status = intel_sdvo_read_response(output, NULL, 0); 600 status = intel_sdvo_read_response(output, NULL, 0);
@@ -683,7 +687,7 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
683 dtd->part1.v_high = (((height >> 8) & 0xf) << 4) | 687 dtd->part1.v_high = (((height >> 8) & 0xf) << 4) |
684 ((v_blank_len >> 8) & 0xf); 688 ((v_blank_len >> 8) & 0xf);
685 689
686 dtd->part2.h_sync_off = h_sync_offset; 690 dtd->part2.h_sync_off = h_sync_offset & 0xff;
687 dtd->part2.h_sync_width = h_sync_len & 0xff; 691 dtd->part2.h_sync_width = h_sync_len & 0xff;
688 dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | 692 dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
689 (v_sync_len & 0xf); 693 (v_sync_len & 0xf);
@@ -705,27 +709,10 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
705static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, 709static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
706 struct intel_sdvo_dtd *dtd) 710 struct intel_sdvo_dtd *dtd)
707{ 711{
708 uint16_t width, height;
709 uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
710 uint16_t h_sync_offset, v_sync_offset;
711
712 width = mode->crtc_hdisplay;
713 height = mode->crtc_vdisplay;
714
715 /* do some mode translations */
716 h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
717 h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
718
719 v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
720 v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
721
722 h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
723 v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
724
725 mode->hdisplay = dtd->part1.h_active; 712 mode->hdisplay = dtd->part1.h_active;
726 mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; 713 mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
727 mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off; 714 mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off;
728 mode->hsync_start += (dtd->part2.sync_off_width_high & 0xa0) << 2; 715 mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2;
729 mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width; 716 mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width;
730 mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; 717 mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4;
731 mode->htotal = mode->hdisplay + dtd->part1.h_blank; 718 mode->htotal = mode->hdisplay + dtd->part1.h_blank;
@@ -735,7 +722,7 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
735 mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; 722 mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
736 mode->vsync_start = mode->vdisplay; 723 mode->vsync_start = mode->vdisplay;
737 mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; 724 mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf;
738 mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0a) << 2; 725 mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2;
739 mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0; 726 mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0;
740 mode->vsync_end = mode->vsync_start + 727 mode->vsync_end = mode->vsync_start +
741 (dtd->part2.v_sync_off_width & 0xf); 728 (dtd->part2.v_sync_off_width & 0xf);
@@ -745,7 +732,7 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
745 732
746 mode->clock = dtd->part1.clock * 10; 733 mode->clock = dtd->part1.clock * 10;
747 734
748 mode->flags &= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); 735 mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
749 if (dtd->part2.dtd_flags & 0x2) 736 if (dtd->part2.dtd_flags & 0x2)
750 mode->flags |= DRM_MODE_FLAG_PHSYNC; 737 mode->flags |= DRM_MODE_FLAG_PHSYNC;
751 if (dtd->part2.dtd_flags & 0x4) 738 if (dtd->part2.dtd_flags & 0x4)
@@ -924,6 +911,27 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
924 SDVO_HBUF_TX_VSYNC); 911 SDVO_HBUF_TX_VSYNC);
925} 912}
926 913
914static void intel_sdvo_set_tv_format(struct intel_output *output)
915{
916 struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
917 struct intel_sdvo_tv_format *format, unset;
918 u8 status;
919
920 format = &sdvo_priv->tv_format;
921 memset(&unset, 0, sizeof(unset));
922 if (memcmp(format, &unset, sizeof(*format))) {
923 DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
924 SDVO_NAME(sdvo_priv));
925 format->ntsc_m = 1;
926 intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
927 sizeof(*format));
928 status = intel_sdvo_read_response(output, NULL, 0);
929 if (status != SDVO_CMD_STATUS_SUCCESS)
930 DRM_DEBUG("%s: Failed to set TV format\n",
931 SDVO_NAME(sdvo_priv));
932 }
933}
934
927static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, 935static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
928 struct drm_display_mode *mode, 936 struct drm_display_mode *mode,
929 struct drm_display_mode *adjusted_mode) 937 struct drm_display_mode *adjusted_mode)
@@ -968,6 +976,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
968 &input_dtd); 976 &input_dtd);
969 intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); 977 intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
970 978
979 drm_mode_set_crtcinfo(adjusted_mode, 0);
980
981 mode->clock = adjusted_mode->clock;
982
983 adjusted_mode->clock *=
984 intel_sdvo_get_pixel_multiplier(mode);
971 } else { 985 } else {
972 return false; 986 return false;
973 } 987 }
@@ -1012,7 +1026,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1012 sdvox |= SDVO_AUDIO_ENABLE; 1026 sdvox |= SDVO_AUDIO_ENABLE;
1013 } 1027 }
1014 1028
1015 intel_sdvo_get_dtd_from_mode(&input_dtd, mode); 1029 /* We have tried to get input timing in mode_fixup, and filled into
1030 adjusted_mode */
1031 if (sdvo_priv->is_tv)
1032 intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
1033 else
1034 intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
1016 1035
1017 /* If it's a TV, we already set the output timing in mode_fixup. 1036 /* If it's a TV, we already set the output timing in mode_fixup.
1018 * Otherwise, the output timing is equal to the input timing. 1037 * Otherwise, the output timing is equal to the input timing.
@@ -1027,6 +1046,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1027 /* Set the input timing to the screen. Assume always input 0. */ 1046 /* Set the input timing to the screen. Assume always input 0. */
1028 intel_sdvo_set_target_input(output, true, false); 1047 intel_sdvo_set_target_input(output, true, false);
1029 1048
1049 if (sdvo_priv->is_tv)
1050 intel_sdvo_set_tv_format(output);
1051
1030 /* We would like to use intel_sdvo_create_preferred_input_timing() to 1052 /* We would like to use intel_sdvo_create_preferred_input_timing() to
1031 * provide the device with a timing it can support, if it supports that 1053 * provide the device with a timing it can support, if it supports that
1032 * feature. However, presumably we would need to adjust the CRTC to 1054 * feature. However, presumably we would need to adjust the CRTC to
@@ -1395,7 +1417,7 @@ static void
1395intel_sdvo_check_tv_format(struct intel_output *output) 1417intel_sdvo_check_tv_format(struct intel_output *output)
1396{ 1418{
1397 struct intel_sdvo_priv *dev_priv = output->dev_priv; 1419 struct intel_sdvo_priv *dev_priv = output->dev_priv;
1398 struct intel_sdvo_tv_format format, unset; 1420 struct intel_sdvo_tv_format format;
1399 uint8_t status; 1421 uint8_t status;
1400 1422
1401 intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0); 1423 intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
@@ -1403,15 +1425,7 @@ intel_sdvo_check_tv_format(struct intel_output *output)
1403 if (status != SDVO_CMD_STATUS_SUCCESS) 1425 if (status != SDVO_CMD_STATUS_SUCCESS)
1404 return; 1426 return;
1405 1427
1406 memset(&unset, 0, sizeof(unset)); 1428 memcpy(&dev_priv->tv_format, &format, sizeof(format));
1407 if (memcmp(&format, &unset, sizeof(format))) {
1408 DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
1409 SDVO_NAME(dev_priv));
1410
1411 format.ntsc_m = true;
1412 intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0);
1413 status = intel_sdvo_read_response(output, NULL, 0);
1414 }
1415} 1429}
1416 1430
1417/* 1431/*
@@ -1420,68 +1434,70 @@ intel_sdvo_check_tv_format(struct intel_output *output)
1420 * XXX: all 60Hz refresh? 1434 * XXX: all 60Hz refresh?
1421 */ 1435 */
1422struct drm_display_mode sdvo_tv_modes[] = { 1436struct drm_display_mode sdvo_tv_modes[] = {
1423 { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815680, 321, 384, 416, 1437 { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384,
1424 200, 0, 232, 201, 233, 4196112, 0, 1438 416, 0, 200, 201, 232, 233, 0,
1425 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1439 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1426 { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814080, 321, 384, 416, 1440 { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814, 320, 321, 384,
1427 240, 0, 272, 241, 273, 4196112, 0, 1441 416, 0, 240, 241, 272, 273, 0,
1428 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1442 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1429 { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910080, 401, 464, 496, 1443 { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910, 400, 401, 464,
1430 300, 0, 332, 301, 333, 4196112, 0, 1444 496, 0, 300, 301, 332, 333, 0,
1431 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1445 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1432 { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913280, 641, 704, 736, 1446 { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913, 640, 641, 704,
1433 350, 0, 382, 351, 383, 4196112, 0, 1447 736, 0, 350, 351, 382, 383, 0,
1434 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1448 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1435 { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736, 1449 { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121, 640, 641, 704,
1436 400, 0, 432, 401, 433, 4196112, 0, 1450 736, 0, 400, 401, 432, 433, 0,
1437 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1451 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1438 { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736, 1452 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 22654, 640, 641, 704,
1439 400, 0, 432, 401, 433, 4196112, 0, 1453 736, 0, 480, 481, 512, 513, 0,
1440 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1454 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1441 { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624000, 705, 768, 800, 1455 { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624, 704, 705, 768,
1442 480, 0, 512, 481, 513, 4196112, 0, 1456 800, 0, 480, 481, 512, 513, 0,
1443 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1457 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1444 { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232000, 705, 768, 800, 1458 { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232, 704, 705, 768,
1445 576, 0, 608, 577, 609, 4196112, 0, 1459 800, 0, 576, 577, 608, 609, 0,
1446 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1460 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1447 { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751680, 721, 784, 816, 1461 { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751, 720, 721, 784,
1448 350, 0, 382, 351, 383, 4196112, 0, 1462 816, 0, 350, 351, 382, 383, 0,
1449 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1463 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1450 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199680, 721, 784, 816, 1464 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199, 720, 721, 784,
1451 400, 0, 432, 401, 433, 4196112, 0, 1465 816, 0, 400, 401, 432, 433, 0,
1452 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1466 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1453 { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116480, 721, 784, 816, 1467 { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116, 720, 721, 784,
1454 480, 0, 512, 481, 513, 4196112, 0, 1468 816, 0, 480, 481, 512, 513, 0,
1455 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1469 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1456 { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054080, 721, 784, 816, 1470 { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054, 720, 721, 784,
1457 540, 0, 572, 541, 573, 4196112, 0, 1471 816, 0, 540, 541, 572, 573, 0,
1458 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1472 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1459 { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816640, 721, 784, 816, 1473 { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816, 720, 721, 784,
1460 576, 0, 608, 577, 609, 4196112, 0, 1474 816, 0, 576, 577, 608, 609, 0,
1461 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1475 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1462 { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570560, 769, 832, 864, 1476 { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570, 768, 769, 832,
1463 576, 0, 608, 577, 609, 4196112, 0, 1477 864, 0, 576, 577, 608, 609, 0,
1464 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1478 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1465 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030080, 801, 864, 896, 1479 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030, 800, 801, 864,
1466 600, 0, 632, 601, 633, 4196112, 0, 1480 896, 0, 600, 601, 632, 633, 0,
1467 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1481 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1468 { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581760, 833, 896, 928, 1482 { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581, 832, 833, 896,
1469 624, 0, 656, 625, 657, 4196112, 0, 1483 928, 0, 624, 625, 656, 657, 0,
1470 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1484 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1471 { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707040, 921, 984, 1016, 1485 { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707, 920, 921, 984,
1472 766, 0, 798, 767, 799, 4196112, 0, 1486 1016, 0, 766, 767, 798, 799, 0,
1473 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1487 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1474 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827200, 1025, 1088, 1120, 1488 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827, 1024, 1025, 1088,
1475 768, 0, 800, 769, 801, 4196112, 0, 1489 1120, 0, 768, 769, 800, 801, 0,
1476 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1490 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1477 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265920, 1281, 1344, 1376, 1491 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265, 1280, 1281, 1344,
1478 1024, 0, 1056, 1025, 1057, 4196112, 0, 1492 1376, 0, 1024, 1025, 1056, 1057, 0,
1479 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1493 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1480}; 1494};
1481 1495
1482static void intel_sdvo_get_tv_modes(struct drm_connector *connector) 1496static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
1483{ 1497{
1484 struct intel_output *output = to_intel_output(connector); 1498 struct intel_output *output = to_intel_output(connector);
1499 struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
1500 struct intel_sdvo_sdtv_resolution_request tv_res;
1485 uint32_t reply = 0; 1501 uint32_t reply = 0;
1486 uint8_t status; 1502 uint8_t status;
1487 int i = 0; 1503 int i = 0;
@@ -1491,15 +1507,22 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
1491 /* Read the list of supported input resolutions for the selected TV 1507 /* Read the list of supported input resolutions for the selected TV
1492 * format. 1508 * format.
1493 */ 1509 */
1510 memset(&tv_res, 0, sizeof(tv_res));
1511 memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
1494 intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, 1512 intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
1495 NULL, 0); 1513 &tv_res, sizeof(tv_res));
1496 status = intel_sdvo_read_response(output, &reply, 3); 1514 status = intel_sdvo_read_response(output, &reply, 3);
1497 if (status != SDVO_CMD_STATUS_SUCCESS) 1515 if (status != SDVO_CMD_STATUS_SUCCESS)
1498 return; 1516 return;
1499 1517
1500 for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) 1518 for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++)
1501 if (reply & (1 << i)) 1519 if (reply & (1 << i)) {
1502 drm_mode_probed_add(connector, &sdvo_tv_modes[i]); 1520 struct drm_display_mode *nmode;
1521 nmode = drm_mode_duplicate(connector->dev,
1522 &sdvo_tv_modes[i]);
1523 if (nmode)
1524 drm_mode_probed_add(connector, nmode);
1525 }
1503} 1526}
1504 1527
1505static int intel_sdvo_get_modes(struct drm_connector *connector) 1528static int intel_sdvo_get_modes(struct drm_connector *connector)