void ast_set_index_reg_mask(struct ast_private *ast, uint32_t base, uint8_t index, uint8_t mask, uint8_t val) { u8 tmp; ast_io_write8(ast, base, index); tmp = (ast_io_read8(ast, base + 1) & mask) | val; ast_set_index_reg(ast, base, index, tmp); }
static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, struct ast_vbios_mode_info *vbios_mode) { struct ast_private *ast = crtc->dev->dev_private; u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate; u32 hborder, vborder; bool check_sync; struct ast_vbios_enhtable *best = NULL; switch (crtc->primary->fb->bits_per_pixel) { case 8: vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; color_index = VGAModeIndex - 1; break; case 16: vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; color_index = HiCModeIndex; break; case 24: case 32: vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; color_index = TrueCModeIndex; break; default: return false; } switch (crtc->mode.crtc_hdisplay) { case 640: vbios_mode->enh_table = &res_640x480[refresh_rate_index]; break; case 800: vbios_mode->enh_table = &res_800x600[refresh_rate_index]; break; case 1024: vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; break; case 1280: if (crtc->mode.crtc_vdisplay == 800) vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; else vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; break; case 1360: vbios_mode->enh_table = &res_1360x768[refresh_rate_index]; break; case 1440: vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; break; case 1600: if (crtc->mode.crtc_vdisplay == 900) vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; else vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; break; case 1680: vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; break; case 1920: if (crtc->mode.crtc_vdisplay == 1080) vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; else vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; break; default: return false; } refresh_rate = drm_mode_vrefresh(mode); check_sync = vbios_mode->enh_table->flags & WideScreenMode; do { struct ast_vbios_enhtable *loop = vbios_mode->enh_table; while (loop->refresh_rate != 0xff) { if ((check_sync) && (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (loop->flags & PVSync)) || ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (loop->flags & NVSync)) || ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (loop->flags & PHSync)) || ((mode->flags & DRM_MODE_FLAG_PHSYNC) && (loop->flags & NHSync)))) { loop++; continue; } if (loop->refresh_rate <= refresh_rate && (!best || loop->refresh_rate > best->refresh_rate)) best = loop; loop++; } if (best || !check_sync) break; check_sync = 0; } while (1); if (best) vbios_mode->enh_table = best; hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0; vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0; adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht; adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder; adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder; adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder + vbios_mode->enh_table->hfp; adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder + vbios_mode->enh_table->hfp + vbios_mode->enh_table->hsync); adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt; adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder; adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder; adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder + vbios_mode->enh_table->vfp; adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder + vbios_mode->enh_table->vfp + vbios_mode->enh_table->vsync); refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; mode_id = vbios_mode->enh_table->mode_id; if (ast->chip == AST1180) { /* TODO 1180 */ } else { ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4)); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); if (vbios_mode->enh_table->flags & NewModeInfo) { ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); } }
bool ast_launch_m68k(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; u32 i, data, len = 0; u32 boot_address; u8 *fw_addr = NULL; u8 jreg; data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (!data) { if (ast->dp501_fw_addr) { fw_addr = ast->dp501_fw_addr; len = 32*1024; } else if (ast->dp501_fw) { fw_addr = (u8 *)ast->dp501_fw->data; len = ast->dp501_fw->size; } /* Get BootAddress */ ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8); data = ast_mindwm(ast, 0x1e6e0004); switch (data & 0x03) { case 0: boot_address = 0x44000000; break; default: case 1: boot_address = 0x48000000; break; case 2: boot_address = 0x50000000; break; case 3: boot_address = 0x60000000; break; } boot_address -= 0x200000; /* -2MB */ /* copy image to buffer */ for (i = 0; i < len; i += 4) { data = *(u32 *)(fw_addr + i); ast_moutdwm(ast, boot_address + i, data); } /* Init SCU */ ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8); /* Launch FW */ ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address); ast_moutdwm(ast, 0x1e6e2100, 1); /* Update Scratch */ data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff; /* D[11:9] = 100b: UEFI handling */ data |= 0x800; ast_moutdwm(ast, 0x1e6e2040, data); jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */ jreg |= 0x02; ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg); } return true; }