ast_mode.c (50235B)
1/* 2 * Copyright 2012 Red Hat Inc. 3 * Parts based on xf86-video-ast 4 * Copyright (c) 2005 ASPEED Technology Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 * 26 */ 27/* 28 * Authors: Dave Airlie <airlied@redhat.com> 29 */ 30 31#include <linux/export.h> 32#include <linux/pci.h> 33 34#include <drm/drm_atomic.h> 35#include <drm/drm_atomic_helper.h> 36#include <drm/drm_atomic_state_helper.h> 37#include <drm/drm_crtc.h> 38#include <drm/drm_crtc_helper.h> 39#include <drm/drm_fourcc.h> 40#include <drm/drm_gem_atomic_helper.h> 41#include <drm/drm_gem_framebuffer_helper.h> 42#include <drm/drm_gem_vram_helper.h> 43#include <drm/drm_managed.h> 44#include <drm/drm_plane_helper.h> 45#include <drm/drm_probe_helper.h> 46#include <drm/drm_simple_kms_helper.h> 47 48#include "ast_drv.h" 49#include "ast_tables.h" 50 51static inline void ast_load_palette_index(struct ast_private *ast, 52 u8 index, u8 red, u8 green, 53 u8 blue) 54{ 55 ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index); 56 ast_io_read8(ast, AST_IO_SEQ_PORT); 57 ast_io_write8(ast, AST_IO_DAC_DATA, red); 58 ast_io_read8(ast, AST_IO_SEQ_PORT); 59 ast_io_write8(ast, AST_IO_DAC_DATA, green); 60 ast_io_read8(ast, AST_IO_SEQ_PORT); 61 ast_io_write8(ast, AST_IO_DAC_DATA, blue); 62 ast_io_read8(ast, AST_IO_SEQ_PORT); 63} 64 65static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc) 66{ 67 u16 *r, *g, *b; 68 int i; 69 70 if (!crtc->enabled) 71 return; 72 73 r = crtc->gamma_store; 74 g = r + crtc->gamma_size; 75 b = g + crtc->gamma_size; 76 77 for (i = 0; i < 256; i++) 78 ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); 79} 80 81static bool ast_get_vbios_mode_info(const struct drm_format_info *format, 82 const struct drm_display_mode *mode, 83 struct drm_display_mode *adjusted_mode, 84 struct ast_vbios_mode_info *vbios_mode) 85{ 86 u32 refresh_rate_index = 0, refresh_rate; 87 const struct ast_vbios_enhtable *best = NULL; 88 u32 hborder, vborder; 89 bool check_sync; 90 91 switch (format->cpp[0] * 8) { 92 case 8: 93 vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; 94 break; 95 case 16: 96 vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; 97 break; 98 case 24: 99 case 32: 100 vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; 101 break; 102 default: 103 return false; 104 } 105 106 switch (mode->crtc_hdisplay) { 107 case 640: 108 vbios_mode->enh_table = &res_640x480[refresh_rate_index]; 109 break; 110 case 800: 111 vbios_mode->enh_table = &res_800x600[refresh_rate_index]; 112 break; 113 case 1024: 114 vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; 115 break; 116 case 1280: 117 if (mode->crtc_vdisplay == 800) 118 vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; 119 else 120 vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; 121 break; 122 case 1360: 123 vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; 124 break; 125 case 1440: 126 vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; 127 break; 128 case 1600: 129 if (mode->crtc_vdisplay == 900) 130 vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; 131 else 132 vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; 133 break; 134 case 1680: 135 vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; 136 break; 137 case 1920: 138 if (mode->crtc_vdisplay == 1080) 139 vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; 140 else 141 vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; 142 break; 143 default: 144 return false; 145 } 146 147 refresh_rate = drm_mode_vrefresh(mode); 148 check_sync = vbios_mode->enh_table->flags & WideScreenMode; 149 150 while (1) { 151 const struct ast_vbios_enhtable *loop = vbios_mode->enh_table; 152 153 while (loop->refresh_rate != 0xff) { 154 if ((check_sync) && 155 (((mode->flags & DRM_MODE_FLAG_NVSYNC) && 156 (loop->flags & PVSync)) || 157 ((mode->flags & DRM_MODE_FLAG_PVSYNC) && 158 (loop->flags & NVSync)) || 159 ((mode->flags & DRM_MODE_FLAG_NHSYNC) && 160 (loop->flags & PHSync)) || 161 ((mode->flags & DRM_MODE_FLAG_PHSYNC) && 162 (loop->flags & NHSync)))) { 163 loop++; 164 continue; 165 } 166 if (loop->refresh_rate <= refresh_rate 167 && (!best || loop->refresh_rate > best->refresh_rate)) 168 best = loop; 169 loop++; 170 } 171 if (best || !check_sync) 172 break; 173 check_sync = 0; 174 } 175 176 if (best) 177 vbios_mode->enh_table = best; 178 179 hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; 180 vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; 181 182 adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; 183 adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; 184 adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; 185 adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder + 186 vbios_mode->enh_table->hfp; 187 adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder + 188 vbios_mode->enh_table->hfp + 189 vbios_mode->enh_table->hsync); 190 191 adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; 192 adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; 193 adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; 194 adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder + 195 vbios_mode->enh_table->vfp; 196 adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder + 197 vbios_mode->enh_table->vfp + 198 vbios_mode->enh_table->vsync); 199 200 return true; 201} 202 203static void ast_set_vbios_color_reg(struct ast_private *ast, 204 const struct drm_format_info *format, 205 const struct ast_vbios_mode_info *vbios_mode) 206{ 207 u32 color_index; 208 209 switch (format->cpp[0]) { 210 case 1: 211 color_index = VGAModeIndex - 1; 212 break; 213 case 2: 214 color_index = HiCModeIndex; 215 break; 216 case 3: 217 case 4: 218 color_index = TrueCModeIndex; 219 break; 220 default: 221 return; 222 } 223 224 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4)); 225 226 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); 227 228 if (vbios_mode->enh_table->flags & NewModeInfo) { 229 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); 230 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, format->cpp[0] * 8); 231 } 232} 233 234static void ast_set_vbios_mode_reg(struct ast_private *ast, 235 const struct drm_display_mode *adjusted_mode, 236 const struct ast_vbios_mode_info *vbios_mode) 237{ 238 u32 refresh_rate_index, mode_id; 239 240 refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; 241 mode_id = vbios_mode->enh_table->mode_id; 242 243 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); 244 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); 245 246 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); 247 248 if (vbios_mode->enh_table->flags & NewModeInfo) { 249 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); 250 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); 251 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); 252 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); 253 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); 254 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); 255 } 256} 257 258static void ast_set_std_reg(struct ast_private *ast, 259 struct drm_display_mode *mode, 260 struct ast_vbios_mode_info *vbios_mode) 261{ 262 const struct ast_vbios_stdtable *stdtable; 263 u32 i; 264 u8 jreg; 265 266 stdtable = vbios_mode->std_table; 267 268 jreg = stdtable->misc; 269 ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); 270 271 /* Set SEQ; except Screen Disable field */ 272 ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03); 273 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, stdtable->seq[0]); 274 for (i = 1; i < 4; i++) { 275 jreg = stdtable->seq[i]; 276 ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1), jreg); 277 } 278 279 /* Set CRTC; except base address and offset */ 280 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); 281 for (i = 0; i < 12; i++) 282 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); 283 for (i = 14; i < 19; i++) 284 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); 285 for (i = 20; i < 25; i++) 286 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]); 287 288 /* set AR */ 289 jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); 290 for (i = 0; i < 20; i++) { 291 jreg = stdtable->ar[i]; 292 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i); 293 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg); 294 } 295 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14); 296 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00); 297 298 jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); 299 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20); 300 301 /* Set GR */ 302 for (i = 0; i < 9; i++) 303 ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]); 304} 305 306static void ast_set_crtc_reg(struct ast_private *ast, 307 struct drm_display_mode *mode, 308 struct ast_vbios_mode_info *vbios_mode) 309{ 310 u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0; 311 u16 temp, precache = 0; 312 313 if ((ast->chip == AST2500) && 314 (vbios_mode->enh_table->flags & AST2500PreCatchCRT)) 315 precache = 40; 316 317 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00); 318 319 temp = (mode->crtc_htotal >> 3) - 5; 320 if (temp & 0x100) 321 jregAC |= 0x01; /* HT D[8] */ 322 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp); 323 324 temp = (mode->crtc_hdisplay >> 3) - 1; 325 if (temp & 0x100) 326 jregAC |= 0x04; /* HDE D[8] */ 327 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp); 328 329 temp = (mode->crtc_hblank_start >> 3) - 1; 330 if (temp & 0x100) 331 jregAC |= 0x10; /* HBS D[8] */ 332 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp); 333 334 temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f; 335 if (temp & 0x20) 336 jreg05 |= 0x80; /* HBE D[5] */ 337 if (temp & 0x40) 338 jregAD |= 0x01; /* HBE D[5] */ 339 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f)); 340 341 temp = ((mode->crtc_hsync_start-precache) >> 3) - 1; 342 if (temp & 0x100) 343 jregAC |= 0x40; /* HRS D[5] */ 344 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp); 345 346 temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f; 347 if (temp & 0x20) 348 jregAD |= 0x04; /* HRE D[5] */ 349 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05)); 350 351 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC); 352 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD); 353 354 /* vert timings */ 355 temp = (mode->crtc_vtotal) - 2; 356 if (temp & 0x100) 357 jreg07 |= 0x01; 358 if (temp & 0x200) 359 jreg07 |= 0x20; 360 if (temp & 0x400) 361 jregAE |= 0x01; 362 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp); 363 364 temp = (mode->crtc_vsync_start) - 1; 365 if (temp & 0x100) 366 jreg07 |= 0x04; 367 if (temp & 0x200) 368 jreg07 |= 0x80; 369 if (temp & 0x400) 370 jregAE |= 0x08; 371 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp); 372 373 temp = (mode->crtc_vsync_end - 1) & 0x3f; 374 if (temp & 0x10) 375 jregAE |= 0x20; 376 if (temp & 0x20) 377 jregAE |= 0x40; 378 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf); 379 380 temp = mode->crtc_vdisplay - 1; 381 if (temp & 0x100) 382 jreg07 |= 0x02; 383 if (temp & 0x200) 384 jreg07 |= 0x40; 385 if (temp & 0x400) 386 jregAE |= 0x02; 387 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp); 388 389 temp = mode->crtc_vblank_start - 1; 390 if (temp & 0x100) 391 jreg07 |= 0x08; 392 if (temp & 0x200) 393 jreg09 |= 0x20; 394 if (temp & 0x400) 395 jregAE |= 0x04; 396 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp); 397 398 temp = mode->crtc_vblank_end - 1; 399 if (temp & 0x100) 400 jregAE |= 0x10; 401 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp); 402 403 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07); 404 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09); 405 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80)); 406 407 if (precache) 408 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80); 409 else 410 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00); 411 412 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80); 413} 414 415static void ast_set_offset_reg(struct ast_private *ast, 416 struct drm_framebuffer *fb) 417{ 418 u16 offset; 419 420 offset = fb->pitches[0] >> 3; 421 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff)); 422 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f); 423} 424 425static void ast_set_dclk_reg(struct ast_private *ast, 426 struct drm_display_mode *mode, 427 struct ast_vbios_mode_info *vbios_mode) 428{ 429 const struct ast_vbios_dclk_info *clk_info; 430 431 if (ast->chip == AST2500) 432 clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index]; 433 else 434 clk_info = &dclk_table[vbios_mode->enh_table->dclk_index]; 435 436 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1); 437 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2); 438 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f, 439 (clk_info->param3 & 0xc0) | 440 ((clk_info->param3 & 0x3) << 4)); 441} 442 443static void ast_set_color_reg(struct ast_private *ast, 444 const struct drm_format_info *format) 445{ 446 u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; 447 448 switch (format->cpp[0] * 8) { 449 case 8: 450 jregA0 = 0x70; 451 jregA3 = 0x01; 452 jregA8 = 0x00; 453 break; 454 case 15: 455 case 16: 456 jregA0 = 0x70; 457 jregA3 = 0x04; 458 jregA8 = 0x02; 459 break; 460 case 32: 461 jregA0 = 0x70; 462 jregA3 = 0x08; 463 jregA8 = 0x02; 464 break; 465 } 466 467 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0); 468 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3); 469 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8); 470} 471 472static void ast_set_crtthd_reg(struct ast_private *ast) 473{ 474 /* Set Threshold */ 475 if (ast->chip == AST2600) { 476 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0); 477 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0); 478 } else if (ast->chip == AST2300 || ast->chip == AST2400 || 479 ast->chip == AST2500) { 480 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78); 481 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60); 482 } else if (ast->chip == AST2100 || 483 ast->chip == AST1100 || 484 ast->chip == AST2200 || 485 ast->chip == AST2150) { 486 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f); 487 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f); 488 } else { 489 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f); 490 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f); 491 } 492} 493 494static void ast_set_sync_reg(struct ast_private *ast, 495 struct drm_display_mode *mode, 496 struct ast_vbios_mode_info *vbios_mode) 497{ 498 u8 jreg; 499 500 jreg = ast_io_read8(ast, AST_IO_MISC_PORT_READ); 501 jreg &= ~0xC0; 502 if (vbios_mode->enh_table->flags & NVSync) 503 jreg |= 0x80; 504 if (vbios_mode->enh_table->flags & NHSync) 505 jreg |= 0x40; 506 ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg); 507} 508 509static void ast_set_start_address_crt1(struct ast_private *ast, 510 unsigned int offset) 511{ 512 u32 addr; 513 514 addr = offset >> 2; 515 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff)); 516 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff)); 517 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff)); 518 519} 520 521static void ast_wait_for_vretrace(struct ast_private *ast) 522{ 523 unsigned long timeout = jiffies + HZ; 524 u8 vgair1; 525 526 do { 527 vgair1 = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); 528 } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout)); 529} 530 531/* 532 * Primary plane 533 */ 534 535static const uint32_t ast_primary_plane_formats[] = { 536 DRM_FORMAT_XRGB8888, 537 DRM_FORMAT_RGB565, 538 DRM_FORMAT_C8, 539}; 540 541static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, 542 struct drm_atomic_state *state) 543{ 544 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 545 plane); 546 struct drm_crtc_state *crtc_state; 547 struct ast_crtc_state *ast_crtc_state; 548 int ret; 549 550 if (!new_plane_state->crtc) 551 return 0; 552 553 crtc_state = drm_atomic_get_new_crtc_state(state, 554 new_plane_state->crtc); 555 556 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 557 DRM_PLANE_HELPER_NO_SCALING, 558 DRM_PLANE_HELPER_NO_SCALING, 559 false, true); 560 if (ret) 561 return ret; 562 563 if (!new_plane_state->visible) 564 return 0; 565 566 ast_crtc_state = to_ast_crtc_state(crtc_state); 567 568 ast_crtc_state->format = new_plane_state->fb->format; 569 570 return 0; 571} 572 573static void 574ast_primary_plane_helper_atomic_update(struct drm_plane *plane, 575 struct drm_atomic_state *state) 576{ 577 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 578 plane); 579 struct drm_device *dev = plane->dev; 580 struct ast_private *ast = to_ast_private(dev); 581 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 582 plane); 583 struct drm_gem_vram_object *gbo; 584 s64 gpu_addr; 585 struct drm_framebuffer *fb = new_state->fb; 586 struct drm_framebuffer *old_fb = old_state->fb; 587 588 if (!old_fb || (fb->format != old_fb->format)) { 589 struct drm_crtc_state *crtc_state = new_state->crtc->state; 590 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); 591 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; 592 593 ast_set_color_reg(ast, fb->format); 594 ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info); 595 } 596 597 gbo = drm_gem_vram_of_gem(fb->obj[0]); 598 gpu_addr = drm_gem_vram_offset(gbo); 599 if (drm_WARN_ON_ONCE(dev, gpu_addr < 0)) 600 return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */ 601 602 ast_set_offset_reg(ast, fb); 603 ast_set_start_address_crt1(ast, (u32)gpu_addr); 604 605 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); 606} 607 608static void 609ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, 610 struct drm_atomic_state *state) 611{ 612 struct ast_private *ast = to_ast_private(plane->dev); 613 614 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20); 615} 616 617static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { 618 DRM_GEM_VRAM_PLANE_HELPER_FUNCS, 619 .atomic_check = ast_primary_plane_helper_atomic_check, 620 .atomic_update = ast_primary_plane_helper_atomic_update, 621 .atomic_disable = ast_primary_plane_helper_atomic_disable, 622}; 623 624static const struct drm_plane_funcs ast_primary_plane_funcs = { 625 .update_plane = drm_atomic_helper_update_plane, 626 .disable_plane = drm_atomic_helper_disable_plane, 627 .destroy = drm_plane_cleanup, 628 .reset = drm_atomic_helper_plane_reset, 629 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 630 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 631}; 632 633static int ast_primary_plane_init(struct ast_private *ast) 634{ 635 struct drm_device *dev = &ast->base; 636 struct drm_plane *primary_plane = &ast->primary_plane; 637 int ret; 638 639 ret = drm_universal_plane_init(dev, primary_plane, 0x01, 640 &ast_primary_plane_funcs, 641 ast_primary_plane_formats, 642 ARRAY_SIZE(ast_primary_plane_formats), 643 NULL, DRM_PLANE_TYPE_PRIMARY, NULL); 644 if (ret) { 645 drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret); 646 return ret; 647 } 648 drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs); 649 650 return 0; 651} 652 653/* 654 * Cursor plane 655 */ 656 657static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height) 658{ 659 union { 660 u32 ul; 661 u8 b[4]; 662 } srcdata32[2], data32; 663 union { 664 u16 us; 665 u8 b[2]; 666 } data16; 667 u32 csum = 0; 668 s32 alpha_dst_delta, last_alpha_dst_delta; 669 u8 __iomem *dstxor; 670 const u8 *srcxor; 671 int i, j; 672 u32 per_pixel_copy, two_pixel_copy; 673 674 alpha_dst_delta = AST_MAX_HWC_WIDTH << 1; 675 last_alpha_dst_delta = alpha_dst_delta - (width << 1); 676 677 srcxor = src; 678 dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; 679 per_pixel_copy = width & 1; 680 two_pixel_copy = width >> 1; 681 682 for (j = 0; j < height; j++) { 683 for (i = 0; i < two_pixel_copy; i++) { 684 srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; 685 srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; 686 data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); 687 data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); 688 data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); 689 data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); 690 691 writel(data32.ul, dstxor); 692 csum += data32.ul; 693 694 dstxor += 4; 695 srcxor += 8; 696 697 } 698 699 for (i = 0; i < per_pixel_copy; i++) { 700 srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; 701 data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); 702 data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); 703 writew(data16.us, dstxor); 704 csum += (u32)data16.us; 705 706 dstxor += 2; 707 srcxor += 4; 708 } 709 dstxor += last_alpha_dst_delta; 710 } 711 712 /* write checksum + signature */ 713 dst += AST_HWC_SIZE; 714 writel(csum, dst); 715 writel(width, dst + AST_HWC_SIGNATURE_SizeX); 716 writel(height, dst + AST_HWC_SIGNATURE_SizeY); 717 writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); 718 writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); 719} 720 721static void ast_set_cursor_base(struct ast_private *ast, u64 address) 722{ 723 u8 addr0 = (address >> 3) & 0xff; 724 u8 addr1 = (address >> 11) & 0xff; 725 u8 addr2 = (address >> 19) & 0xff; 726 727 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0); 728 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1); 729 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); 730} 731 732static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y, 733 u8 x_offset, u8 y_offset) 734{ 735 u8 x0 = (x & 0x00ff); 736 u8 x1 = (x & 0x0f00) >> 8; 737 u8 y0 = (y & 0x00ff); 738 u8 y1 = (y & 0x0700) >> 8; 739 740 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset); 741 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset); 742 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, x0); 743 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, x1); 744 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, y0); 745 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); 746} 747 748static void ast_set_cursor_enabled(struct ast_private *ast, bool enabled) 749{ 750 static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | 751 AST_IO_VGACRCB_HWC_ENABLED); 752 753 u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP; 754 755 if (enabled) 756 vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED; 757 758 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, mask, vgacrcb); 759} 760 761static const uint32_t ast_cursor_plane_formats[] = { 762 DRM_FORMAT_ARGB8888, 763}; 764 765static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, 766 struct drm_atomic_state *state) 767{ 768 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 769 plane); 770 struct drm_framebuffer *fb = new_plane_state->fb; 771 struct drm_crtc_state *crtc_state; 772 int ret; 773 774 if (!new_plane_state->crtc) 775 return 0; 776 777 crtc_state = drm_atomic_get_new_crtc_state(state, 778 new_plane_state->crtc); 779 780 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, 781 DRM_PLANE_HELPER_NO_SCALING, 782 DRM_PLANE_HELPER_NO_SCALING, 783 true, true); 784 if (ret) 785 return ret; 786 787 if (!new_plane_state->visible) 788 return 0; 789 790 if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT) 791 return -EINVAL; 792 793 return 0; 794} 795 796static void 797ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, 798 struct drm_atomic_state *state) 799{ 800 struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane); 801 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 802 plane); 803 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 804 plane); 805 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state); 806 struct drm_framebuffer *fb = new_state->fb; 807 struct ast_private *ast = to_ast_private(plane->dev); 808 struct iosys_map dst_map = 809 ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].map; 810 u64 dst_off = 811 ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].off; 812 struct iosys_map src_map = shadow_plane_state->data[0]; 813 unsigned int offset_x, offset_y; 814 u16 x, y; 815 u8 x_offset, y_offset; 816 u8 __iomem *dst; 817 u8 __iomem *sig; 818 const u8 *src; 819 820 src = src_map.vaddr; /* TODO: Use mapping abstraction properly */ 821 dst = dst_map.vaddr_iomem; /* TODO: Use mapping abstraction properly */ 822 sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */ 823 824 /* 825 * Do data transfer to HW cursor BO. If a new cursor image was installed, 826 * point the scanout engine to dst_gbo's offset and page-flip the HWC buffers. 827 */ 828 829 ast_update_cursor_image(dst, src, fb->width, fb->height); 830 831 if (new_state->fb != old_state->fb) { 832 ast_set_cursor_base(ast, dst_off); 833 834 ++ast_cursor_plane->next_hwc_index; 835 ast_cursor_plane->next_hwc_index %= ARRAY_SIZE(ast_cursor_plane->hwc); 836 } 837 838 /* 839 * Update location in HWC signature and registers. 840 */ 841 842 writel(new_state->crtc_x, sig + AST_HWC_SIGNATURE_X); 843 writel(new_state->crtc_y, sig + AST_HWC_SIGNATURE_Y); 844 845 offset_x = AST_MAX_HWC_WIDTH - fb->width; 846 offset_y = AST_MAX_HWC_HEIGHT - fb->height; 847 848 if (new_state->crtc_x < 0) { 849 x_offset = (-new_state->crtc_x) + offset_x; 850 x = 0; 851 } else { 852 x_offset = offset_x; 853 x = new_state->crtc_x; 854 } 855 if (new_state->crtc_y < 0) { 856 y_offset = (-new_state->crtc_y) + offset_y; 857 y = 0; 858 } else { 859 y_offset = offset_y; 860 y = new_state->crtc_y; 861 } 862 863 ast_set_cursor_location(ast, x, y, x_offset, y_offset); 864 865 /* Dummy write to enable HWC and make the HW pick-up the changes. */ 866 ast_set_cursor_enabled(ast, true); 867} 868 869static void 870ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, 871 struct drm_atomic_state *state) 872{ 873 struct ast_private *ast = to_ast_private(plane->dev); 874 875 ast_set_cursor_enabled(ast, false); 876} 877 878static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { 879 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 880 .atomic_check = ast_cursor_plane_helper_atomic_check, 881 .atomic_update = ast_cursor_plane_helper_atomic_update, 882 .atomic_disable = ast_cursor_plane_helper_atomic_disable, 883}; 884 885static void ast_cursor_plane_destroy(struct drm_plane *plane) 886{ 887 struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane); 888 size_t i; 889 struct drm_gem_vram_object *gbo; 890 struct iosys_map map; 891 892 for (i = 0; i < ARRAY_SIZE(ast_cursor_plane->hwc); ++i) { 893 gbo = ast_cursor_plane->hwc[i].gbo; 894 map = ast_cursor_plane->hwc[i].map; 895 drm_gem_vram_vunmap(gbo, &map); 896 drm_gem_vram_unpin(gbo); 897 drm_gem_vram_put(gbo); 898 } 899 900 drm_plane_cleanup(plane); 901} 902 903static const struct drm_plane_funcs ast_cursor_plane_funcs = { 904 .update_plane = drm_atomic_helper_update_plane, 905 .disable_plane = drm_atomic_helper_disable_plane, 906 .destroy = ast_cursor_plane_destroy, 907 DRM_GEM_SHADOW_PLANE_FUNCS, 908}; 909 910static int ast_cursor_plane_init(struct ast_private *ast) 911{ 912 struct drm_device *dev = &ast->base; 913 struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane; 914 struct drm_plane *cursor_plane = &ast_cursor_plane->base; 915 size_t size, i; 916 struct drm_gem_vram_object *gbo; 917 struct iosys_map map; 918 int ret; 919 s64 off; 920 921 /* 922 * Allocate backing storage for cursors. The BOs are permanently 923 * pinned to the top end of the VRAM. 924 */ 925 926 size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); 927 928 for (i = 0; i < ARRAY_SIZE(ast_cursor_plane->hwc); ++i) { 929 gbo = drm_gem_vram_create(dev, size, 0); 930 if (IS_ERR(gbo)) { 931 ret = PTR_ERR(gbo); 932 goto err_hwc; 933 } 934 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM | 935 DRM_GEM_VRAM_PL_FLAG_TOPDOWN); 936 if (ret) 937 goto err_drm_gem_vram_put; 938 ret = drm_gem_vram_vmap(gbo, &map); 939 if (ret) 940 goto err_drm_gem_vram_unpin; 941 off = drm_gem_vram_offset(gbo); 942 if (off < 0) { 943 ret = off; 944 goto err_drm_gem_vram_vunmap; 945 } 946 ast_cursor_plane->hwc[i].gbo = gbo; 947 ast_cursor_plane->hwc[i].map = map; 948 ast_cursor_plane->hwc[i].off = off; 949 } 950 951 /* 952 * Create the cursor plane. The plane's destroy callback will release 953 * the backing storages' BO memory. 954 */ 955 956 ret = drm_universal_plane_init(dev, cursor_plane, 0x01, 957 &ast_cursor_plane_funcs, 958 ast_cursor_plane_formats, 959 ARRAY_SIZE(ast_cursor_plane_formats), 960 NULL, DRM_PLANE_TYPE_CURSOR, NULL); 961 if (ret) { 962 drm_err(dev, "drm_universal_plane failed(): %d\n", ret); 963 goto err_hwc; 964 } 965 drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs); 966 967 return 0; 968 969err_hwc: 970 while (i) { 971 --i; 972 gbo = ast_cursor_plane->hwc[i].gbo; 973 map = ast_cursor_plane->hwc[i].map; 974err_drm_gem_vram_vunmap: 975 drm_gem_vram_vunmap(gbo, &map); 976err_drm_gem_vram_unpin: 977 drm_gem_vram_unpin(gbo); 978err_drm_gem_vram_put: 979 drm_gem_vram_put(gbo); 980 } 981 return ret; 982} 983 984/* 985 * CRTC 986 */ 987 988static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) 989{ 990 struct ast_private *ast = to_ast_private(crtc->dev); 991 u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF; 992 993 /* TODO: Maybe control display signal generation with 994 * Sync Enable (bit CR17.7). 995 */ 996 switch (mode) { 997 case DRM_MODE_DPMS_ON: 998 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0); 999 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0); 1000 if (ast->tx_chip_types & AST_TX_DP501_BIT) 1001 ast_set_dp501_video_output(crtc->dev, 1); 1002 1003 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { 1004 ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON); 1005 ast_wait_for_vretrace(ast); 1006 ast_dp_set_on_off(crtc->dev, 1); 1007 } 1008 1009 ast_crtc_load_lut(ast, crtc); 1010 break; 1011 case DRM_MODE_DPMS_STANDBY: 1012 case DRM_MODE_DPMS_SUSPEND: 1013 case DRM_MODE_DPMS_OFF: 1014 ch = mode; 1015 if (ast->tx_chip_types & AST_TX_DP501_BIT) 1016 ast_set_dp501_video_output(crtc->dev, 0); 1017 1018 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { 1019 ast_dp_set_on_off(crtc->dev, 0); 1020 ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF); 1021 } 1022 1023 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0x20); 1024 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch); 1025 break; 1026 } 1027} 1028 1029static enum drm_mode_status 1030ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) 1031{ 1032 struct ast_private *ast = to_ast_private(crtc->dev); 1033 enum drm_mode_status status; 1034 uint32_t jtemp; 1035 1036 if (ast->support_wide_screen) { 1037 if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050)) 1038 return MODE_OK; 1039 if ((mode->hdisplay == 1280) && (mode->vdisplay == 800)) 1040 return MODE_OK; 1041 if ((mode->hdisplay == 1440) && (mode->vdisplay == 900)) 1042 return MODE_OK; 1043 if ((mode->hdisplay == 1360) && (mode->vdisplay == 768)) 1044 return MODE_OK; 1045 if ((mode->hdisplay == 1600) && (mode->vdisplay == 900)) 1046 return MODE_OK; 1047 1048 if ((ast->chip == AST2100) || (ast->chip == AST2200) || 1049 (ast->chip == AST2300) || (ast->chip == AST2400) || 1050 (ast->chip == AST2500) || (ast->chip == AST2600)) { 1051 if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080)) 1052 return MODE_OK; 1053 1054 if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) { 1055 jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); 1056 if (jtemp & 0x01) 1057 return MODE_NOMODE; 1058 else 1059 return MODE_OK; 1060 } 1061 } 1062 } 1063 1064 status = MODE_NOMODE; 1065 1066 switch (mode->hdisplay) { 1067 case 640: 1068 if (mode->vdisplay == 480) 1069 status = MODE_OK; 1070 break; 1071 case 800: 1072 if (mode->vdisplay == 600) 1073 status = MODE_OK; 1074 break; 1075 case 1024: 1076 if (mode->vdisplay == 768) 1077 status = MODE_OK; 1078 break; 1079 case 1280: 1080 if (mode->vdisplay == 1024) 1081 status = MODE_OK; 1082 break; 1083 case 1600: 1084 if (mode->vdisplay == 1200) 1085 status = MODE_OK; 1086 break; 1087 default: 1088 break; 1089 } 1090 1091 return status; 1092} 1093 1094static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, 1095 struct drm_atomic_state *state) 1096{ 1097 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, 1098 crtc); 1099 struct drm_device *dev = crtc->dev; 1100 struct ast_crtc_state *ast_state; 1101 const struct drm_format_info *format; 1102 bool succ; 1103 1104 if (!crtc_state->enable) 1105 return 0; /* no mode checks if CRTC is being disabled */ 1106 1107 ast_state = to_ast_crtc_state(crtc_state); 1108 1109 format = ast_state->format; 1110 if (drm_WARN_ON_ONCE(dev, !format)) 1111 return -EINVAL; /* BUG: We didn't set format in primary check(). */ 1112 1113 succ = ast_get_vbios_mode_info(format, &crtc_state->mode, 1114 &crtc_state->adjusted_mode, 1115 &ast_state->vbios_mode_info); 1116 if (!succ) 1117 return -EINVAL; 1118 1119 return 0; 1120} 1121 1122static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state) 1123{ 1124 struct drm_device *dev = crtc->dev; 1125 struct ast_private *ast = to_ast_private(dev); 1126 1127 /* 1128 * Concurrent operations could possibly trigger a call to 1129 * drm_connector_helper_funcs.get_modes by trying to read the 1130 * display modes. Protect access to I/O registers by acquiring 1131 * the I/O-register lock. Released in atomic_flush(). 1132 */ 1133 mutex_lock(&ast->ioregs_lock); 1134} 1135 1136static void 1137ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, 1138 struct drm_atomic_state *state) 1139{ 1140 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, 1141 crtc); 1142 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, 1143 crtc); 1144 struct drm_device *dev = crtc->dev; 1145 struct ast_private *ast = to_ast_private(dev); 1146 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); 1147 struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); 1148 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; 1149 1150 /* 1151 * The gamma LUT has to be reloaded after changing the primary 1152 * plane's color format. 1153 */ 1154 if (old_ast_crtc_state->format != ast_crtc_state->format) 1155 ast_crtc_load_lut(ast, crtc); 1156 1157 //Set Aspeed Display-Port 1158 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) 1159 ast_dp_set_mode(crtc, vbios_mode_info); 1160 1161 mutex_unlock(&ast->ioregs_lock); 1162} 1163 1164static void 1165ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, 1166 struct drm_atomic_state *state) 1167{ 1168 struct drm_device *dev = crtc->dev; 1169 struct ast_private *ast = to_ast_private(dev); 1170 struct drm_crtc_state *crtc_state = crtc->state; 1171 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); 1172 struct ast_vbios_mode_info *vbios_mode_info = 1173 &ast_crtc_state->vbios_mode_info; 1174 struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; 1175 1176 ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); 1177 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); 1178 ast_set_std_reg(ast, adjusted_mode, vbios_mode_info); 1179 ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info); 1180 ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info); 1181 ast_set_crtthd_reg(ast); 1182 ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info); 1183 1184 ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 1185} 1186 1187static void 1188ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, 1189 struct drm_atomic_state *state) 1190{ 1191 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, 1192 crtc); 1193 struct drm_device *dev = crtc->dev; 1194 struct ast_private *ast = to_ast_private(dev); 1195 1196 ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 1197 1198 /* 1199 * HW cursors require the underlying primary plane and CRTC to 1200 * display a valid mode and image. This is not the case during 1201 * full modeset operations. So we temporarily disable any active 1202 * plane, including the HW cursor. Each plane's atomic_update() 1203 * helper will re-enable it if necessary. 1204 * 1205 * We only do this during *full* modesets. It does not affect 1206 * simple pageflips on the planes. 1207 */ 1208 drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); 1209 1210 /* 1211 * Ensure that no scanout takes place before reprogramming mode 1212 * and format registers. 1213 */ 1214 ast_wait_for_vretrace(ast); 1215} 1216 1217static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { 1218 .mode_valid = ast_crtc_helper_mode_valid, 1219 .atomic_check = ast_crtc_helper_atomic_check, 1220 .atomic_begin = ast_crtc_helper_atomic_begin, 1221 .atomic_flush = ast_crtc_helper_atomic_flush, 1222 .atomic_enable = ast_crtc_helper_atomic_enable, 1223 .atomic_disable = ast_crtc_helper_atomic_disable, 1224}; 1225 1226static void ast_crtc_reset(struct drm_crtc *crtc) 1227{ 1228 struct ast_crtc_state *ast_state = 1229 kzalloc(sizeof(*ast_state), GFP_KERNEL); 1230 1231 if (crtc->state) 1232 crtc->funcs->atomic_destroy_state(crtc, crtc->state); 1233 1234 if (ast_state) 1235 __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); 1236 else 1237 __drm_atomic_helper_crtc_reset(crtc, NULL); 1238} 1239 1240static struct drm_crtc_state * 1241ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) 1242{ 1243 struct ast_crtc_state *new_ast_state, *ast_state; 1244 struct drm_device *dev = crtc->dev; 1245 1246 if (drm_WARN_ON(dev, !crtc->state)) 1247 return NULL; 1248 1249 new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL); 1250 if (!new_ast_state) 1251 return NULL; 1252 __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base); 1253 1254 ast_state = to_ast_crtc_state(crtc->state); 1255 1256 new_ast_state->format = ast_state->format; 1257 memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info, 1258 sizeof(new_ast_state->vbios_mode_info)); 1259 1260 return &new_ast_state->base; 1261} 1262 1263static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc, 1264 struct drm_crtc_state *state) 1265{ 1266 struct ast_crtc_state *ast_state = to_ast_crtc_state(state); 1267 1268 __drm_atomic_helper_crtc_destroy_state(&ast_state->base); 1269 kfree(ast_state); 1270} 1271 1272static const struct drm_crtc_funcs ast_crtc_funcs = { 1273 .reset = ast_crtc_reset, 1274 .destroy = drm_crtc_cleanup, 1275 .set_config = drm_atomic_helper_set_config, 1276 .page_flip = drm_atomic_helper_page_flip, 1277 .atomic_duplicate_state = ast_crtc_atomic_duplicate_state, 1278 .atomic_destroy_state = ast_crtc_atomic_destroy_state, 1279}; 1280 1281static int ast_crtc_init(struct drm_device *dev) 1282{ 1283 struct ast_private *ast = to_ast_private(dev); 1284 struct drm_crtc *crtc = &ast->crtc; 1285 int ret; 1286 1287 ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane, 1288 &ast->cursor_plane.base, &ast_crtc_funcs, 1289 NULL); 1290 if (ret) 1291 return ret; 1292 1293 drm_mode_crtc_set_gamma_size(crtc, 256); 1294 drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs); 1295 1296 return 0; 1297} 1298 1299/* 1300 * VGA Connector 1301 */ 1302 1303static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) 1304{ 1305 struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector); 1306 struct drm_device *dev = connector->dev; 1307 struct ast_private *ast = to_ast_private(dev); 1308 struct edid *edid; 1309 int count; 1310 1311 if (!ast_vga_connector->i2c) 1312 goto err_drm_connector_update_edid_property; 1313 1314 /* 1315 * Protect access to I/O registers from concurrent modesetting 1316 * by acquiring the I/O-register lock. 1317 */ 1318 mutex_lock(&ast->ioregs_lock); 1319 1320 edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter); 1321 if (!edid) 1322 goto err_mutex_unlock; 1323 1324 mutex_unlock(&ast->ioregs_lock); 1325 1326 count = drm_add_edid_modes(connector, edid); 1327 kfree(edid); 1328 1329 return count; 1330 1331err_mutex_unlock: 1332 mutex_unlock(&ast->ioregs_lock); 1333err_drm_connector_update_edid_property: 1334 drm_connector_update_edid_property(connector, NULL); 1335 return 0; 1336} 1337 1338static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = { 1339 .get_modes = ast_vga_connector_helper_get_modes, 1340}; 1341 1342static const struct drm_connector_funcs ast_vga_connector_funcs = { 1343 .reset = drm_atomic_helper_connector_reset, 1344 .fill_modes = drm_helper_probe_single_connector_modes, 1345 .destroy = drm_connector_cleanup, 1346 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1347 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1348}; 1349 1350static int ast_vga_connector_init(struct drm_device *dev, 1351 struct ast_vga_connector *ast_vga_connector) 1352{ 1353 struct drm_connector *connector = &ast_vga_connector->base; 1354 int ret; 1355 1356 ast_vga_connector->i2c = ast_i2c_create(dev); 1357 if (!ast_vga_connector->i2c) 1358 drm_err(dev, "failed to add ddc bus for connector\n"); 1359 1360 if (ast_vga_connector->i2c) 1361 ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs, 1362 DRM_MODE_CONNECTOR_VGA, 1363 &ast_vga_connector->i2c->adapter); 1364 else 1365 ret = drm_connector_init(dev, connector, &ast_vga_connector_funcs, 1366 DRM_MODE_CONNECTOR_VGA); 1367 if (ret) 1368 return ret; 1369 1370 drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs); 1371 1372 connector->interlace_allowed = 0; 1373 connector->doublescan_allowed = 0; 1374 1375 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1376 1377 return 0; 1378} 1379 1380static int ast_vga_output_init(struct ast_private *ast) 1381{ 1382 struct drm_device *dev = &ast->base; 1383 struct drm_crtc *crtc = &ast->crtc; 1384 struct drm_encoder *encoder = &ast->output.vga.encoder; 1385 struct ast_vga_connector *ast_vga_connector = &ast->output.vga.vga_connector; 1386 struct drm_connector *connector = &ast_vga_connector->base; 1387 int ret; 1388 1389 ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC); 1390 if (ret) 1391 return ret; 1392 encoder->possible_crtcs = drm_crtc_mask(crtc); 1393 1394 ret = ast_vga_connector_init(dev, ast_vga_connector); 1395 if (ret) 1396 return ret; 1397 1398 ret = drm_connector_attach_encoder(connector, encoder); 1399 if (ret) 1400 return ret; 1401 1402 return 0; 1403} 1404 1405/* 1406 * SIL164 Connector 1407 */ 1408 1409static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector) 1410{ 1411 struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector); 1412 struct drm_device *dev = connector->dev; 1413 struct ast_private *ast = to_ast_private(dev); 1414 struct edid *edid; 1415 int count; 1416 1417 if (!ast_sil164_connector->i2c) 1418 goto err_drm_connector_update_edid_property; 1419 1420 /* 1421 * Protect access to I/O registers from concurrent modesetting 1422 * by acquiring the I/O-register lock. 1423 */ 1424 mutex_lock(&ast->ioregs_lock); 1425 1426 edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter); 1427 if (!edid) 1428 goto err_mutex_unlock; 1429 1430 mutex_unlock(&ast->ioregs_lock); 1431 1432 count = drm_add_edid_modes(connector, edid); 1433 kfree(edid); 1434 1435 return count; 1436 1437err_mutex_unlock: 1438 mutex_unlock(&ast->ioregs_lock); 1439err_drm_connector_update_edid_property: 1440 drm_connector_update_edid_property(connector, NULL); 1441 return 0; 1442} 1443 1444static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = { 1445 .get_modes = ast_sil164_connector_helper_get_modes, 1446}; 1447 1448static const struct drm_connector_funcs ast_sil164_connector_funcs = { 1449 .reset = drm_atomic_helper_connector_reset, 1450 .fill_modes = drm_helper_probe_single_connector_modes, 1451 .destroy = drm_connector_cleanup, 1452 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1453 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1454}; 1455 1456static int ast_sil164_connector_init(struct drm_device *dev, 1457 struct ast_sil164_connector *ast_sil164_connector) 1458{ 1459 struct drm_connector *connector = &ast_sil164_connector->base; 1460 int ret; 1461 1462 ast_sil164_connector->i2c = ast_i2c_create(dev); 1463 if (!ast_sil164_connector->i2c) 1464 drm_err(dev, "failed to add ddc bus for connector\n"); 1465 1466 if (ast_sil164_connector->i2c) 1467 ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs, 1468 DRM_MODE_CONNECTOR_DVII, 1469 &ast_sil164_connector->i2c->adapter); 1470 else 1471 ret = drm_connector_init(dev, connector, &ast_sil164_connector_funcs, 1472 DRM_MODE_CONNECTOR_DVII); 1473 if (ret) 1474 return ret; 1475 1476 drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs); 1477 1478 connector->interlace_allowed = 0; 1479 connector->doublescan_allowed = 0; 1480 1481 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1482 1483 return 0; 1484} 1485 1486static int ast_sil164_output_init(struct ast_private *ast) 1487{ 1488 struct drm_device *dev = &ast->base; 1489 struct drm_crtc *crtc = &ast->crtc; 1490 struct drm_encoder *encoder = &ast->output.sil164.encoder; 1491 struct ast_sil164_connector *ast_sil164_connector = &ast->output.sil164.sil164_connector; 1492 struct drm_connector *connector = &ast_sil164_connector->base; 1493 int ret; 1494 1495 ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); 1496 if (ret) 1497 return ret; 1498 encoder->possible_crtcs = drm_crtc_mask(crtc); 1499 1500 ret = ast_sil164_connector_init(dev, ast_sil164_connector); 1501 if (ret) 1502 return ret; 1503 1504 ret = drm_connector_attach_encoder(connector, encoder); 1505 if (ret) 1506 return ret; 1507 1508 return 0; 1509} 1510 1511/* 1512 * DP501 Connector 1513 */ 1514 1515static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector) 1516{ 1517 void *edid; 1518 bool succ; 1519 int count; 1520 1521 edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 1522 if (!edid) 1523 goto err_drm_connector_update_edid_property; 1524 1525 succ = ast_dp501_read_edid(connector->dev, edid); 1526 if (!succ) 1527 goto err_kfree; 1528 1529 drm_connector_update_edid_property(connector, edid); 1530 count = drm_add_edid_modes(connector, edid); 1531 kfree(edid); 1532 1533 return count; 1534 1535err_kfree: 1536 kfree(edid); 1537err_drm_connector_update_edid_property: 1538 drm_connector_update_edid_property(connector, NULL); 1539 return 0; 1540} 1541 1542static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = { 1543 .get_modes = ast_dp501_connector_helper_get_modes, 1544}; 1545 1546static const struct drm_connector_funcs ast_dp501_connector_funcs = { 1547 .reset = drm_atomic_helper_connector_reset, 1548 .fill_modes = drm_helper_probe_single_connector_modes, 1549 .destroy = drm_connector_cleanup, 1550 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1551 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1552}; 1553 1554static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector) 1555{ 1556 int ret; 1557 1558 ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs, 1559 DRM_MODE_CONNECTOR_DisplayPort); 1560 if (ret) 1561 return ret; 1562 1563 drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs); 1564 1565 connector->interlace_allowed = 0; 1566 connector->doublescan_allowed = 0; 1567 1568 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1569 1570 return 0; 1571} 1572 1573static int ast_dp501_output_init(struct ast_private *ast) 1574{ 1575 struct drm_device *dev = &ast->base; 1576 struct drm_crtc *crtc = &ast->crtc; 1577 struct drm_encoder *encoder = &ast->output.dp501.encoder; 1578 struct drm_connector *connector = &ast->output.dp501.connector; 1579 int ret; 1580 1581 ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); 1582 if (ret) 1583 return ret; 1584 encoder->possible_crtcs = drm_crtc_mask(crtc); 1585 1586 ret = ast_dp501_connector_init(dev, connector); 1587 if (ret) 1588 return ret; 1589 1590 ret = drm_connector_attach_encoder(connector, encoder); 1591 if (ret) 1592 return ret; 1593 1594 return 0; 1595} 1596 1597/* 1598 * ASPEED Display-Port Connector 1599 */ 1600 1601static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector) 1602{ 1603 void *edid; 1604 1605 int succ; 1606 int count; 1607 1608 edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 1609 if (!edid) 1610 goto err_drm_connector_update_edid_property; 1611 1612 succ = ast_astdp_read_edid(connector->dev, edid); 1613 if (succ < 0) 1614 goto err_kfree; 1615 1616 drm_connector_update_edid_property(connector, edid); 1617 count = drm_add_edid_modes(connector, edid); 1618 kfree(edid); 1619 1620 return count; 1621 1622err_kfree: 1623 kfree(edid); 1624err_drm_connector_update_edid_property: 1625 drm_connector_update_edid_property(connector, NULL); 1626 return 0; 1627} 1628 1629static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = { 1630 .get_modes = ast_astdp_connector_helper_get_modes, 1631}; 1632 1633static const struct drm_connector_funcs ast_astdp_connector_funcs = { 1634 .reset = drm_atomic_helper_connector_reset, 1635 .fill_modes = drm_helper_probe_single_connector_modes, 1636 .destroy = drm_connector_cleanup, 1637 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 1638 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1639}; 1640 1641static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector) 1642{ 1643 int ret; 1644 1645 ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs, 1646 DRM_MODE_CONNECTOR_DisplayPort); 1647 if (ret) 1648 return ret; 1649 1650 drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs); 1651 1652 connector->interlace_allowed = 0; 1653 connector->doublescan_allowed = 0; 1654 1655 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1656 1657 return 0; 1658} 1659 1660static int ast_astdp_output_init(struct ast_private *ast) 1661{ 1662 struct drm_device *dev = &ast->base; 1663 struct drm_crtc *crtc = &ast->crtc; 1664 struct drm_encoder *encoder = &ast->output.astdp.encoder; 1665 struct drm_connector *connector = &ast->output.astdp.connector; 1666 int ret; 1667 1668 ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); 1669 if (ret) 1670 return ret; 1671 encoder->possible_crtcs = drm_crtc_mask(crtc); 1672 1673 ret = ast_astdp_connector_init(dev, connector); 1674 if (ret) 1675 return ret; 1676 1677 ret = drm_connector_attach_encoder(connector, encoder); 1678 if (ret) 1679 return ret; 1680 1681 return 0; 1682} 1683 1684/* 1685 * Mode config 1686 */ 1687 1688static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = { 1689 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, 1690}; 1691 1692static const struct drm_mode_config_funcs ast_mode_config_funcs = { 1693 .fb_create = drm_gem_fb_create, 1694 .mode_valid = drm_vram_helper_mode_valid, 1695 .atomic_check = drm_atomic_helper_check, 1696 .atomic_commit = drm_atomic_helper_commit, 1697}; 1698 1699int ast_mode_config_init(struct ast_private *ast) 1700{ 1701 struct drm_device *dev = &ast->base; 1702 struct pci_dev *pdev = to_pci_dev(dev->dev); 1703 int ret; 1704 1705 ret = drmm_mode_config_init(dev); 1706 if (ret) 1707 return ret; 1708 1709 dev->mode_config.funcs = &ast_mode_config_funcs; 1710 dev->mode_config.min_width = 0; 1711 dev->mode_config.min_height = 0; 1712 dev->mode_config.preferred_depth = 24; 1713 dev->mode_config.prefer_shadow = 1; 1714 dev->mode_config.fb_base = pci_resource_start(pdev, 0); 1715 1716 if (ast->chip == AST2100 || 1717 ast->chip == AST2200 || 1718 ast->chip == AST2300 || 1719 ast->chip == AST2400 || 1720 ast->chip == AST2500 || 1721 ast->chip == AST2600) { 1722 dev->mode_config.max_width = 1920; 1723 dev->mode_config.max_height = 2048; 1724 } else { 1725 dev->mode_config.max_width = 1600; 1726 dev->mode_config.max_height = 1200; 1727 } 1728 1729 dev->mode_config.helper_private = &ast_mode_config_helper_funcs; 1730 1731 1732 ret = ast_primary_plane_init(ast); 1733 if (ret) 1734 return ret; 1735 1736 ret = ast_cursor_plane_init(ast); 1737 if (ret) 1738 return ret; 1739 1740 ast_crtc_init(dev); 1741 1742 if (ast->tx_chip_types & AST_TX_NONE_BIT) { 1743 ret = ast_vga_output_init(ast); 1744 if (ret) 1745 return ret; 1746 } 1747 if (ast->tx_chip_types & AST_TX_SIL164_BIT) { 1748 ret = ast_sil164_output_init(ast); 1749 if (ret) 1750 return ret; 1751 } 1752 if (ast->tx_chip_types & AST_TX_DP501_BIT) { 1753 ret = ast_dp501_output_init(ast); 1754 if (ret) 1755 return ret; 1756 } 1757 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { 1758 ret = ast_astdp_output_init(ast); 1759 if (ret) 1760 return ret; 1761 } 1762 1763 drm_mode_config_reset(dev); 1764 1765 return 0; 1766}