blob: 16f6b8a7cf2a10dc2c744766699cf265583305e5 [file] [log] [blame]
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -04001// Hooks for via vgabios calls into main bios.
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05005// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -04006
Kevin O'Connordfefeb52009-12-13 13:04:17 -05007#include "bregs.h" // set_code_invalid
Kevin O'Connor47358772008-12-26 13:01:23 -05008#include "biosvar.h" // GET_GLOBAL
9#include "pci.h" // pci_find_device
Kevin O'Connor22e1b912009-07-19 18:52:46 -040010#include "pci_regs.h" // PCI_VENDOR_ID
Kevin O'Connor47358772008-12-26 13:01:23 -050011#include "pci_ids.h" // PCI_VENDOR_ID_VIA
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -040012#include "util.h" // handle_155f
13#include "config.h" // CONFIG_*
14
Kevin O'Connorc1de91b2011-07-02 13:50:21 -040015#define VH_VIA 1
16#define VH_INTEL 2
Kevin O'Connor22e1b912009-07-19 18:52:46 -040017
Kevin O'Connorc1de91b2011-07-02 13:50:21 -040018int VGAHookHandlerType VAR16VISIBLE;
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +020019
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -040020static void
Kevin O'Connor22e1b912009-07-19 18:52:46 -040021handle_155fXX(struct bregs *regs)
22{
Kevin O'Connordfefeb52009-12-13 13:04:17 -050023 set_code_unimplemented(regs, RET_EUNSUPPORTED);
Kevin O'Connor22e1b912009-07-19 18:52:46 -040024}
25
26
27/****************************************************************
28 * Via hooks
29 ****************************************************************/
30
Kevin O'Connorc1de91b2011-07-02 13:50:21 -040031int ViaFBsize VAR16VISIBLE, ViaRamSpeed VAR16VISIBLE;
32
Kevin O'Connor22e1b912009-07-19 18:52:46 -040033static void
34via_155f01(struct bregs *regs)
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -040035{
36 regs->eax = 0x5f;
37 regs->cl = 2; // panel type = 2 = 1024 * 768
38 set_success(regs);
Kevin O'Connor47358772008-12-26 13:01:23 -050039 dprintf(1, "Warning: VGA panel type is hardcoded\n");
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -040040}
41
42static void
Kevin O'Connor22e1b912009-07-19 18:52:46 -040043via_155f02(struct bregs *regs)
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -040044{
45 regs->eax = 0x5f;
46 regs->bx = 2;
47 regs->cx = 0x401; // PAL + crt only
48 regs->dx = 0; // TV Layout - default
49 set_success(regs);
Kevin O'Connor47358772008-12-26 13:01:23 -050050 dprintf(1, "Warning: VGA TV/CRT output type is hardcoded\n");
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -040051}
52
Kevin O'Connorc1de91b2011-07-02 13:50:21 -040053static void
54via_155f18(struct bregs *regs)
55{
56 int fbsize = GET_GLOBAL(ViaFBsize), ramspeed = GET_GLOBAL(ViaRamSpeed);
57 if (fbsize < 0 || ramspeed < 0) {
58 set_code_invalid(regs, RET_EUNSUPPORTED);
59 return;
60 }
61 regs->eax = 0x5f;
62 regs->ebx = 0x500 | (ramspeed << 4) | fbsize;
63 regs->ecx = 0x060;
64 set_success(regs);
65}
66
67static void
68via_155f19(struct bregs *regs)
69{
70 set_invalid_silent(regs);
71}
72
73static void
74via_155f(struct bregs *regs)
75{
76 switch (regs->al) {
77 case 0x01: via_155f01(regs); break;
78 case 0x02: via_155f02(regs); break;
79 case 0x18: via_155f18(regs); break;
80 case 0x19: via_155f19(regs); break;
81 default: handle_155fXX(regs); break;
82 }
83}
84
Kevin O'Connor47358772008-12-26 13:01:23 -050085static int
Kevin O'Connor22e1b912009-07-19 18:52:46 -040086getFBSize(u16 bdf)
Kevin O'Connor47358772008-12-26 13:01:23 -050087{
Kevin O'Connor47358772008-12-26 13:01:23 -050088 /* FB config */
89 u8 reg = pci_config_readb(bdf, 0xa1);
90
91 /* GFX disabled ? */
92 if (!(reg & 0x80))
Kevin O'Connor22e1b912009-07-19 18:52:46 -040093 return -1;
Kevin O'Connor47358772008-12-26 13:01:23 -050094
Kevin O'Connorc1de91b2011-07-02 13:50:21 -040095 static u8 mem_power[] = {0, 3, 4, 5, 6, 7, 8, 9};
96 return mem_power[(reg >> 4) & 0x7];
Kevin O'Connor47358772008-12-26 13:01:23 -050097}
98
99static int
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400100getViaRamSpeed(u16 bdf)
101{
102 return (pci_config_readb(bdf, 0x90) & 0x07) + 3;
103}
104
105static int
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500106getAMDRamSpeed(void)
Kevin O'Connor47358772008-12-26 13:01:23 -0500107{
108 int bdf = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL);
109 if (bdf < 0)
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400110 return -1;
Kevin O'Connor47358772008-12-26 13:01:23 -0500111
112 /* mem clk 0 = DDR2 400 */
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400113 return (pci_config_readb(bdf, 0x94) & 0x7) + 6;
Kevin O'Connor47358772008-12-26 13:01:23 -0500114}
115
116/* int 0x15 - 5f18
117
118 ECX = unknown/dont care
119 EBX[3..0] Frame Buffer Size 2^N MiB
120 EBX[7..4] Memory speed:
121 0: SDR 66Mhz
122 1: SDR 100Mhz
123 2: SDR 133Mhz
124 3: DDR 100Mhz (PC1600 or DDR200)
125 4: DDR 133Mhz (PC2100 or DDR266)
126 5: DDR 166Mhz (PC2700 or DDR333)
127 6: DDR 200Mhz (PC3200 or DDR400)
128 7: DDR2 133Mhz (DDR2 533)
129 8: DDR2 166Mhz (DDR2 667)
130 9: DDR2 200Mhz (DDR2 800)
131 A: DDR2 233Mhz (DDR2 1066)
132 B: and above: Unknown
133 EBX[?..8] Total memory size?
134 EAX = 0x5f for success
Kevin O'Connor47358772008-12-26 13:01:23 -0500135*/
136
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400137#define PCI_DEVICE_ID_VIA_K8M890CE_3 0x3336
138#define PCI_DEVICE_ID_VIA_VX855_MEMCTRL 0x3409
139
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400140static void
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400141via_setup(struct pci_device *pci)
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400142{
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400143 VGAHookHandlerType = VH_VIA;
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400144
145 int bdf = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_K8M890CE_3);
146 if (bdf >= 0) {
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400147 ViaFBsize = getFBSize(bdf);
148 ViaRamSpeed = getAMDRamSpeed();
149 return;
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400150 }
151 bdf = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_MEMCTRL);
152 if (bdf >= 0) {
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400153 ViaFBsize = getFBSize(bdf);
154 ViaRamSpeed = getViaRamSpeed(bdf);
155 return;
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400156 }
157
158 dprintf(1, "Warning: VGA memory size and speed is hardcoded\n");
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400159 ViaFBsize = 5; // 32M frame buffer
160 ViaRamSpeed = 4; // MCLK = DDR266
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400161}
162
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400163
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200164/****************************************************************
165 * Intel VGA hooks
166 ****************************************************************/
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400167
168u8 IntelDisplayType VAR16VISIBLE, IntelDisplayId VAR16VISIBLE;
169
170static void
171intel_155f35(struct bregs *regs)
172{
173 regs->ax = 0x005f;
174 regs->cl = GET_GLOBAL(IntelDisplayType);
175 set_success(regs);
176}
177
178static void
179intel_155f40(struct bregs *regs)
180{
181 regs->ax = 0x005f;
182 regs->cl = GET_GLOBAL(IntelDisplayId);
183 set_success(regs);
184}
185
186static void
187intel_155f(struct bregs *regs)
188{
189 switch (regs->al) {
190 case 0x35: intel_155f35(regs); break;
191 case 0x40: intel_155f40(regs); break;
192 default: handle_155fXX(regs); break;
193 }
194}
195
196#define BOOT_DISPLAY_DEFAULT (0)
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200197#define BOOT_DISPLAY_CRT (1 << 0)
198#define BOOT_DISPLAY_TV (1 << 1)
199#define BOOT_DISPLAY_EFP (1 << 2)
200#define BOOT_DISPLAY_LCD (1 << 3)
201#define BOOT_DISPLAY_CRT2 (1 << 4)
202#define BOOT_DISPLAY_TV2 (1 << 5)
203#define BOOT_DISPLAY_EFP2 (1 << 6)
204#define BOOT_DISPLAY_LCD2 (1 << 7)
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400205
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200206static void
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400207roda_setup(struct pci_device *pci)
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200208{
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400209 VGAHookHandlerType = VH_INTEL;
210 // IntelDisplayType = BOOT_DISPLAY_DEFAULT;
211 IntelDisplayType = BOOT_DISPLAY_LCD;
212 // IntelDisplayId = inb(0x60f) & 0x0f; // Correct according to Crete
213 IntelDisplayId = 3; // Correct according to empirical studies
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200214}
215
216static void
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400217kontron_setup(struct pci_device *pci)
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200218{
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400219 VGAHookHandlerType = VH_INTEL;
220 IntelDisplayType = BOOT_DISPLAY_CRT;
221 IntelDisplayId = 3;
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200222}
223
224static void
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400225getac_setup(struct pci_device *pci)
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200226{
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200227}
228
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400229
230/****************************************************************
231 * Entry and setup
232 ****************************************************************/
233
234// Main 16bit entry point
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400235void
236handle_155f(struct bregs *regs)
237{
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400238 if (!CONFIG_VGAHOOKS) {
239 handle_155fXX(regs);
240 return;
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400241 }
242
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400243 int htype = GET_GLOBAL(VGAHookHandlerType);
244 switch (htype) {
245 case VH_VIA: via_155f(regs); break;
246 case VH_INTEL: intel_155f(regs); break;
247 default: handle_155fXX(regs); break;
248 }
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400249}
250
251// Setup
252void
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400253vgahook_setup(struct pci_device *pci)
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400254{
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400255 if (!CONFIG_VGAHOOKS || !CBvendor || !CBpart)
Kevin O'Connor22e1b912009-07-19 18:52:46 -0400256 return;
Stefan Reinauer8cb8ba52010-06-09 09:45:28 +0200257
Kevin O'Connorc1de91b2011-07-02 13:50:21 -0400258 if (strcmp(CBvendor, "KONTRON") == 0 && strcmp(CBpart, "986LCD-M") == 0)
259 kontron_setup(pci);
260 else if (strcmp(CBvendor, "GETAC") == 0 && strcmp(CBpart, "P470") == 0)
261 getac_setup(pci);
262 else if (strcmp(CBvendor, "RODA") == 0 && strcmp(CBpart, "RK886EX") == 0)
263 roda_setup(pci);
264 else if (pci->vendor == PCI_VENDOR_ID_VIA)
265 via_setup(pci);
Kevin O'Connorcbffa8e2008-08-17 11:11:07 -0400266}