Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/ast: add widescreen + rb modes from X.org driver (v2)

This syncs up the mode code from the X.org driver upstream,
and adds the mode validation step for hw that doesn't have
widescreen.

v2: (from Egbert Eich <eich@suse.de)
squash drm/ast: Use correct structure member for mode validation
to avoid bisect regression.

In struct drm_display_mode crtc_hdisplay and crtc_vdisplay are holding
the crtc parameters after mode fixup. For validation we need hdisplay and
vdisplay.

Signed-off-by: Egbert Eich <eich@suse.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>

+145 -27
+1
drivers/gpu/drm/ast/ast_drv.h
··· 102 102 * we have. */ 103 103 struct ttm_bo_kmap_obj cache_kmap; 104 104 int next_cursor; 105 + bool support_wide_screen; 105 106 }; 106 107 107 108 int ast_driver_load(struct drm_device *dev, unsigned long flags);
+28
drivers/gpu/drm/ast/ast_main.c
··· 66 66 static int ast_detect_chip(struct drm_device *dev) 67 67 { 68 68 struct ast_private *ast = dev->dev_private; 69 + uint32_t data, jreg; 69 70 70 71 if (dev->pdev->device == PCI_CHIP_AST1180) { 71 72 ast->chip = AST1100; ··· 105 104 DRM_INFO("AST 2000 detected\n"); 106 105 } 107 106 } 107 + 108 + switch (ast->chip) { 109 + case AST1180: 110 + ast->support_wide_screen = true; 111 + break; 112 + case AST2000: 113 + ast->support_wide_screen = false; 114 + break; 115 + default: 116 + jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 117 + if (!(jreg & 0x80)) 118 + ast->support_wide_screen = true; 119 + else if (jreg & 0x01) 120 + ast->support_wide_screen = true; 121 + else { 122 + ast->support_wide_screen = false; 123 + if (ast->chip == AST2300) { 124 + ast_write32(ast, 0xf004, 0x1e6e0000); 125 + ast_write32(ast, 0xf000, 0x1); 126 + data = ast_read32(ast, 0x1207c); 127 + if ((data & 0x300) == 0) /* ast1300 */ 128 + ast->support_wide_screen = true; 129 + } 130 + } 131 + break; 132 + } 133 + 108 134 return 0; 109 135 } 110 136
+67 -9
drivers/gpu/drm/ast/ast_mode.c
··· 115 115 else 116 116 vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; 117 117 break; 118 + case 1360: 119 + vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; 120 + break; 118 121 case 1440: 119 122 vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; 120 123 break; 121 124 case 1600: 122 - vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; 125 + if (crtc->mode.crtc_vdisplay == 900) 126 + vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; 127 + else 128 + vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; 123 129 break; 124 130 case 1680: 125 131 vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; ··· 181 175 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); 182 176 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); 183 177 184 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); 185 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel); 186 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); 187 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); 188 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); 178 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); 179 + if (vbios_mode->enh_table->flags & NewModeInfo) { 180 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); 181 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->fb->bits_per_pixel); 182 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); 183 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); 184 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); 189 185 190 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); 191 - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); 186 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); 187 + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); 188 + } 192 189 } 193 190 194 191 return true; ··· 755 746 static int ast_mode_valid(struct drm_connector *connector, 756 747 struct drm_display_mode *mode) 757 748 { 758 - return MODE_OK; 749 + struct ast_private *ast = connector->dev->dev_private; 750 + int flags = MODE_NOMODE; 751 + uint32_t jtemp; 752 + 753 + if (ast->support_wide_screen) { 754 + if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) 755 + return MODE_OK; 756 + if ((mode->hdisplay == 1280) && (mode->vdisplay == 800)) 757 + return MODE_OK; 758 + if ((mode->hdisplay == 1440) && (mode->vdisplay == 900)) 759 + return MODE_OK; 760 + if ((mode->hdisplay == 1360) && (mode->vdisplay == 768)) 761 + return MODE_OK; 762 + if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) 763 + return MODE_OK; 764 + 765 + if ((ast->chip == AST2100) || (ast->chip == AST2200) || (ast->chip == AST2300) || (ast->chip == AST1180)) { 766 + if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) 767 + return MODE_OK; 768 + 769 + if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) { 770 + jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); 771 + if (jtemp & 0x01) 772 + return MODE_NOMODE; 773 + else 774 + return MODE_OK; 775 + } 776 + } 777 + } 778 + switch (mode->hdisplay) { 779 + case 640: 780 + if (mode->vdisplay == 480) flags = MODE_OK; 781 + break; 782 + case 800: 783 + if (mode->vdisplay == 600) flags = MODE_OK; 784 + break; 785 + case 1024: 786 + if (mode->vdisplay == 768) flags = MODE_OK; 787 + break; 788 + case 1280: 789 + if (mode->vdisplay == 1024) flags = MODE_OK; 790 + break; 791 + case 1600: 792 + if (mode->vdisplay == 1200) flags = MODE_OK; 793 + break; 794 + default: 795 + return flags; 796 + } 797 + 798 + return flags; 759 799 } 760 800 761 801 static void ast_connector_destroy(struct drm_connector *connector)
+49 -18
drivers/gpu/drm/ast/ast_tables.h
··· 42 42 #define HBorder 0x00000020 43 43 #define VBorder 0x00000010 44 44 #define WideScreenMode 0x00000100 45 - 45 + #define NewModeInfo 0x00000200 46 46 47 47 /* DCLK Index */ 48 48 #define VCLK25_175 0x00 ··· 67 67 #define VCLK106_5 0x12 68 68 #define VCLK146_25 0x13 69 69 #define VCLK148_5 0x14 70 + #define VCLK71 0x15 71 + #define VCLK88_75 0x16 72 + #define VCLK119 0x17 73 + #define VCLK85_5 0x18 74 + #define VCLK97_75 0x19 70 75 71 76 static struct ast_vbios_dclk_info dclk_table[] = { 72 77 {0x2C, 0xE7, 0x03}, /* 00: VCLK25_175 */ ··· 95 90 {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ 96 91 {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ 97 92 {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ 93 + {0x47, 0x6c, 0x80}, /* 15: VCLK71 */ 94 + {0x25, 0x65, 0x80}, /* 16: VCLK88.75 */ 95 + {0x77, 0x58, 0x80}, /* 17: VCLK119 */ 96 + {0x32, 0x67, 0x80}, /* 18: VCLK85_5 */ 98 97 }; 99 98 100 99 static struct ast_vbios_stdtable vbios_stdtable[] = { ··· 234 225 (SyncPP | Charx8Dot), 0xFF, 1, 0x33 }, 235 226 }; 236 227 237 - static struct ast_vbios_enhtable res_1920x1200[] = { 238 - {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz */ 239 - (SyncNP | Charx8Dot), 60, 1, 0x34 }, 240 - {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz */ 241 - (SyncNP | Charx8Dot), 0xFF, 1, 0x34 }, 228 + /* 16:9 */ 229 + static struct ast_vbios_enhtable res_1360x768[] = { 230 + {1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* 60Hz */ 231 + (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 }, 232 + {1792, 1360, 64,112, 795, 768, 3, 6, VCLK85_5, /* end */ 233 + (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 }, 242 234 }; 235 + 236 + static struct ast_vbios_enhtable res_1600x900[] = { 237 + {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ 238 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x3A }, 239 + {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* end */ 240 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x3A } 241 + }; 242 + 243 + static struct ast_vbios_enhtable res_1920x1080[] = { 244 + {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ 245 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x38 }, 246 + {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ 247 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x38 }, 248 + }; 249 + 243 250 244 251 /* 16:10 */ 245 252 static struct ast_vbios_enhtable res_1280x800[] = { 253 + {1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71, /* 60Hz RB */ 254 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 35 }, 246 255 {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ 247 - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode), 60, 1, 0x35 }, 256 + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x35 }, 248 257 {1680, 1280, 72,128, 831, 800, 3, 6, VCLK83_5, /* 60Hz */ 249 - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode), 0xFF, 1, 0x35 }, 258 + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x35 }, 250 259 251 260 }; 252 261 253 262 static struct ast_vbios_enhtable res_1440x900[] = { 263 + {1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75, /* 60Hz RB */ 264 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x36 }, 254 265 {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ 255 - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode), 60, 1, 0x36 }, 266 + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x36 }, 256 267 {1904, 1440, 80,152, 934, 900, 3, 6, VCLK106_5, /* 60Hz */ 257 - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode), 0xFF, 1, 0x36 }, 268 + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x36 }, 258 269 }; 259 270 260 271 static struct ast_vbios_enhtable res_1680x1050[] = { 272 + {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119, /* 60Hz RB */ 273 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x37 }, 261 274 {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ 262 - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode), 60, 1, 0x37 }, 275 + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x37 }, 263 276 {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25, /* 60Hz */ 264 - (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode), 0xFF, 1, 0x37 }, 277 + (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x37 }, 265 278 }; 266 279 267 - /* HDTV */ 268 - static struct ast_vbios_enhtable res_1920x1080[] = { 269 - {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ 270 - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode), 60, 1, 0x38 }, 271 - {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5, /* 60Hz */ 272 - (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode), 0xFF, 1, 0x38 }, 280 + static struct ast_vbios_enhtable res_1920x1200[] = { 281 + {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz */ 282 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x34 }, 283 + {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154, /* 60Hz */ 284 + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x34 }, 273 285 }; 286 + 274 287 #endif