2 *-----------------------------------------------------------------------------
3 * Filename: micro_init_tnc.c
5 *-----------------------------------------------------------------------------
6 * Copyright (c) 2002-2010, Intel Corporation.
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 *-----------------------------------------------------------------------------
29 *-----------------------------------------------------------------------------
32 #define MODULE_NAME hal.init
39 #include <igd_errno.h>
47 #include <igd_debug.h>
50 #include <asm/cacheflush.h>
53 #include <tnc/context.h>
54 #include <linux/pci_ids.h>
56 #include "../cmn/init_dispatch.h"
60 #define SCR1 0x71410 /* scratch register set by vbios indicating status*/
61 #define SCR2 0x71418 /* scratch register set by vbios indicating amount of stolen memory */
62 #define FW_ID 0xE1DF0000 /* firmware identifier */
63 #define ST_BIT 0x00000004 /* bit2- stolen memory bit */
64 #define PSB_GMCH_CTRL 0x52
65 #define PSB_GMCH_ENABLED 0x04
66 #define PSB_PGETBL_CTL 0x00002020
67 #define PSB_GATT_RESOURCE 2
68 #define PSB_GTT_RESOURCE 3
70 #define PSB_PTE_VALID 0x0001
75 * @addtogroup core_group
81 extern unsigned char io_mapped;
82 extern unsigned short io_base;
84 /* For dev2 [0:2:0] */
85 extern unsigned char io_mapped_lvds;
86 extern unsigned short io_base_lvds;
88 /* For dev3 [0:3:0] */
89 extern unsigned char io_mapped_sdvo;
90 extern unsigned short io_base_sdvo;
92 /* For dev31 [0:31:0] */
93 extern unsigned char io_mapped_lpc;
94 extern unsigned short io_base_lpc;
96 /* For STMicro SDVO [6:0:1] */
97 extern unsigned char io_mapped_sdvo_st;
98 extern unsigned short io_base_sdvo_st;
99 extern unsigned char io_mapped_sdvo_st_gpio;
100 extern unsigned short io_base_sdvo_st_gpio;
102 extern int full_config_tnc(igd_context_t *context,
103 init_dispatch_t *dispatch);
104 extern int get_revision_id_tnc(igd_context_t *context, os_pci_dev_t vga_dev, os_pci_dev_t sdvo_dev);
105 extern int full_get_param_tnc(igd_context_t *context, unsigned long id,
106 unsigned long *value);
107 extern void full_shutdown_tnc(igd_context_t *context);
109 extern int query_2d_caps_hwhint_tnc(
110 igd_context_t *context,
111 unsigned long caps_val,
112 unsigned long *status);
114 static int query_tnc(igd_context_t *context,init_dispatch_t *dispatch,
115 os_pci_dev_t vga_dev, unsigned int *bus, unsigned int *slot,
117 static int config_tnc(igd_context_t *context,
118 init_dispatch_t *dispatch);
119 static int set_param_tnc(igd_context_t *context, unsigned long id,
120 unsigned long value);
121 static int get_param_tnc(igd_context_t *context, unsigned long id,
122 unsigned long *value);
123 static void shutdown_tnc(igd_context_t *context);
125 static void gtt_shutdown_tnc(igd_context_t *context);
126 static void gtt_init_tnc(igd_context_t *context);
128 /* Helper Functions */
129 static int query_sch_message(unsigned long reg, unsigned long* value);
130 static int dump_fuse_values(void);
132 static platform_context_tnc_t platform_context_tnc;
134 os_pci_dev_t bridge_dev;
136 init_dispatch_t init_dispatch_tnc = {
137 "Intel Atom E6xx Processor",
145 query_2d_caps_hwhint_tnc
148 /* Array to keep the Bridge ID. Atom E6xx ULP uses a different bridge ID */
149 static unsigned short bridge_id[] =
151 PCI_DEVICE_ID_BRIDGE_TNC,
152 PCI_DEVICE_ID_BRIDGE_TNC_ULP,
159 * Atom E6xx GFX frequencies
160 * The gfx clock frequencies depends on the board SKU and ratio
161 * The table of frequencies can be found in Atom E6xx EAS
162 * Chapter: Clocks and Reset Unit
164 static unsigned short tnc_gfx_freq_list[RATIO_NO][SKU_NO] =
166 /* rows represent the gfx clock ratio,
169 /* sku_100 sku_100L sku_83 */
170 {200, 100, 166}, /*1:1*/
171 {266, 133, 222}, /*4:3*/
172 {320, 160, 266}, /*8:5*/
173 {400, 200, 333}, /*2:1 DEFAULT*/
174 {0, 0, 0 }, /*16:7 RSVD*/
175 {533, 266, 444}, /*8:3*/
176 {640, 320, 553}, /*16:5*/
177 {800, 400, 666} /*4:1 RSVD*/
180 static unsigned short tnc_core_freq_list[SKU_NO] =
182 /* sku_100 sku_100L sku_83 */
187 #define READ_FUS_EFF0 0xD08106F0
188 #define READ_FUS_EFF1 0xD08107F0
189 #define READ_FUS_EFF2 0xD08108F0
190 #define READ_FUS_EFF3 0xD08109F0
191 #define READ_FUS_EFF4 0xD0810AF0
192 #define READ_FUS_EFF5 0xD0810BF0
199 * Unmap the GTT mapping that was done during init time.
201 static void gtt_shutdown_tnc(igd_context_t *context)
203 if (context->device_context.virt_gttadr) {
204 iounmap(context->device_context.virt_gttadr);
206 context->device_context.virt_gttadr = NULL;
208 if(context->device_context.scratch_page){
209 __free_page(context->device_context.scratch_page);
210 context->device_context.scratch_page = NULL;
216 * Initialize the GTT.
217 * - Find the size of stolen memory
218 * - Add stolen memory to the GTT
219 * - Map the GTT and video memory
222 static void gtt_init_tnc(igd_context_t *context)
224 struct drm_device *dev;
225 unsigned char *mmio = context->device_context.virt_mmadr;
226 unsigned long dvmt_mode = 0;
227 unsigned long gtt_pages = 0;
228 unsigned long stolen_mem_size = 0;
229 unsigned long scratch;
232 unsigned short gmch_ctl;
233 unsigned long pge_ctl;
234 unsigned long gtt_phys_start;
235 unsigned long gatt_start;
236 unsigned long gatt_pages;
237 unsigned long gtt_start;
238 unsigned long gtt_order;
239 unsigned long stolen_mem_base;
240 unsigned long *gtt_table;
241 struct page *gtt_table_page;
244 dev = (struct drm_device *)context->drm_dev;
246 /* Enable the GMCH */
247 OS_PCI_READ_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
249 OS_PCI_WRITE_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
250 (gmch_ctl | PSB_GMCH_ENABLED));
251 context->device_context.gmch_ctl = gmch_ctl;
253 /* Get the page table control register */
254 pge_ctl = readl(mmio + PSB_PGETBL_CTL);
255 gtt_phys_start = pge_ctl & PAGE_MASK;
257 /* Create a scratch page to initialize empty GTT entries */
258 if(NULL == context->device_context.scratch_page){
259 context->device_context.scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
263 * Is pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); the same
264 * as pci_read_config_dword(dev->pdev, 0x1C, &value)?
266 * PSB_GATT_RESOURCE length is the amount of memory addressable
269 gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
270 gatt_pages = (pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT);
271 context->device_context.gatt_pages = gatt_pages;
274 * The GTT wasn't set up by the vBios
277 context->device_context.stolen_pages = 0;
279 gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
280 gtt_order = get_order(gtt_pages << PAGE_SHIFT);
281 gtt_table = (unsigned long *)__get_free_pages(GFP_KERNEL, gtt_order);
282 /* Make sure allocation was successful */
283 if (NULL == gtt_table) {
284 EMGD_ERROR("Failed to allocate kernel pages for GTT");
287 context->device_context.virt_gttadr = gtt_table;
289 for (i=0; i < (1 << gtt_order); i++) {
290 gtt_table_page = virt_to_page(gtt_table + (PAGE_SIZE * i));
291 EMGD_DEBUG("Setting reserved bit on %p", gtt_table_page);
292 set_bit(PG_reserved, >t_table_page->flags);
295 gtt_phys_start = virt_to_phys(gtt_table);
297 for (i = 0; i < gtt_pages; i++) {
298 gtt_table[i] = (unsigned long)context->device_context.scratch_page;
301 printk(KERN_INFO "Detected GTT was not enabled by firmware");
302 printk(KERN_INFO "GMMADR(region 0) start: 0x%08lx (%ldM).\n",
303 gatt_start, (gatt_pages / 256));
304 printk(KERN_INFO "GTTADR(region 3) start: 0x%08lx (can map %ldM RAM), and "
305 "actual RAM base 0x%08lx.\n",
306 (unsigned long)gtt_table, (gtt_pages * 4), gtt_phys_start);
308 /* Enable the newly created GTT */
309 EMGD_DEBUG("Enabling new GTT");
310 writel(gtt_phys_start, mmio + PSB_PGETBL_CTL);
311 pge_ctl = readl(mmio + PSB_PGETBL_CTL);
316 * Get the start address of the GTT page table
318 * In full_config_vga, this is done differently. The address is read
319 * from pcidev0's pci config space, at TNC_PCI_GTTADR and the size comes
320 * from TNC_OFFSET_VGA_MSAC. The value read for size is a size id
321 * 1 = 128, 2 = 256, 3 = 512
322 * emgd_gtt->gtt_start = OS_PCI_READ_CONFIG_32(
323 * context->platform_context->pcidev0, TNC_PCI_GTTADDR)
324 * gtt_pages = OS_PCI_READ_CONFIG_8(context->platform_context->pcidev0,
325 * TNC_OFFSET_VGA_MSAC) * 1024;
327 * PSB_GTT_RESOURCE length is the size of the GTT table. Thus,
328 * gtt_pages is the number of pages that make up the table.
330 gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
331 gtt_pages = (pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT);
333 /* Get stolen memory configuration. */
334 pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)&stolen_mem_base);
335 stolen_mem_size = gtt_phys_start - stolen_mem_base - PAGE_SIZE;
337 /* Display useful information in the kernel log */
338 printk(KERN_INFO "GMMADR(region 0) start: 0x%08lx (%ldM).\n",
339 gatt_start, (gatt_pages / 256));
340 printk(KERN_INFO "GTTADR(region 3) start: 0x%08lx (can map %ldM RAM), and "
341 "actual RAM base 0x%08lx.\n",
342 gtt_start, (gtt_pages * 4), gtt_phys_start);
343 printk(KERN_INFO "Stolen memory information \n");
344 printk(KERN_INFO " base in RAM: 0x%lx \n", stolen_mem_base);
345 printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - "
346 "(Stolen base)\n", (stolen_mem_size / 1024));
347 dvmt_mode = (gmch_ctl >> 4) & 0x7;
348 printk(KERN_INFO " size: %dM (dvmt mode=%ld)\n",
349 (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
351 context->device_context.virt_gttadr =
352 ioremap_nocache(gtt_start, gtt_pages << PAGE_SHIFT);
354 if (!context->device_context.virt_gttadr) {
355 printk(KERN_ERR "Failed to map the GTT.\n");
356 /* TODO: Clean up somelthing here */
360 /* Insert stolen memory pages into the beginning of GTT */
361 base = stolen_mem_base >> PAGE_SHIFT;
362 context->device_context.stolen_pages = stolen_mem_size >> PAGE_SHIFT;
364 printk(KERN_INFO "Set up %ld stolen pages starting at 0x%08lx, "
365 "GTT offset %dK\n", context->device_context.stolen_pages, base, 0);
367 for (i = 0; i < context->device_context.stolen_pages; i++) {
368 pte = ((base + i) << PAGE_SHIFT) | PSB_PTE_VALID;
369 writel(pte, context->device_context.virt_gttadr + i);
374 /* Update the scratch registers to say we have no stolen memory */
375 scratch = readl(mmio + SCR1);
376 if ((scratch & FW_ID) == FW_ID) {
377 /* if an EMGD vBios modify only the stolen memory bit */
379 writel(scratch, mmio + SCR1);
381 /* Not an EMGD vBios so just set the entire register to a known value */
382 writel((FW_ID|ST_BIT), mmio + SCR1);
386 * Report back that there is 0MB of stolen memory regardless of
387 * what was really in there. Fresh pages will be inserted over
388 * the top of the existing stolen memory.
390 writel(0, mmio + SCR2);
393 * FIXME: Shouldn't this fill in all the GTT page table entries with
402 * Helper function to query MCR registers
406 * @return -IGD_ERROR_INVAL on error
407 * @return 0 on success
409 static int query_sch_message(unsigned long reg, unsigned long* value){
411 platform_context_tnc_t *platform_context = &platform_context_tnc;
413 /* Send the opcode into the MCR */
414 if(OS_PCI_WRITE_CONFIG_32(platform_context->bridgedev,
416 EMGD_ERROR_EXIT("Writing into the MCR Failed");
417 return -IGD_ERROR_INVAL;
420 if(OS_PCI_READ_CONFIG_32(platform_context->bridgedev,
423 EMGD_ERROR_EXIT("Writing to MDR Failed");
424 return -IGD_ERROR_INVAL;
439 * @return -IGD_ERROR_NODEV on failure
440 * @return 0 on success
442 static int query_tnc(
443 igd_context_t *context,
444 init_dispatch_t *dispatch,
445 os_pci_dev_t vga_dev,
450 platform_context_tnc_t *platform_context = &platform_context_tnc;
458 /* So we don't have to pollute our function tables with multiple
459 * entries for every variant of TNC, update the device ID if one
460 * of the other SKUs is found
462 context->device_context.did = PCI_DEVICE_ID_VGA_TNC;
464 platform_context->did = context->device_context.did;
465 context->platform_context = (void *)&platform_context_tnc;
467 OS_PTHREAD_MUTEX_INIT(&platform_context_tnc.flip_mutex, NULL);
469 /* find and store the bridge dev since we will be using it a lot
470 * in the init modules */
471 while(bridge_id[i] != 0){
472 platform_context->bridgedev = OS_PCI_FIND_DEVICE(
475 0xFFFF, /* Scan the whole PCI bus */
479 if(platform_context->bridgedev){
480 bridge_dev = platform_context->bridgedev;
481 context->device_context.bid = bridge_id[i];
487 * Current specs indicate that Atom E6xx has only one PCI function.
488 * If this changes then we need to make sure we have func 0
489 * here as in previous chips.
491 platform_context->pcidev0 = vga_dev;
494 platform_context->pcidev1 = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_INTEL,
495 PCI_DEVICE_ID_SDVO_TNC,
501 platform_context->stbridgedev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_STMICRO,
502 PCI_DEVICE_ID_SDVO_TNC_ST,
508 if (platform_context->stbridgedev) {
509 platform_context->stgpiodev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_STMICRO,
510 PCI_DEVICE_ID_SDVO_TNC_ST_GPIO,
516 if (!platform_context->stgpiodev) {
517 platform_context->stgpiodev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_STMICRO,
518 PCI_DEVICE_ID_SDVO_TNC_ST_GPIO,
523 if (!platform_context->stgpiodev) {
524 printk("Using STM device, but is not CUT1 or CUT2\n");
525 EMGD_ERROR_EXIT("Using STM device, but is not Cut1 or Cut2");
526 return -IGD_ERROR_NODEV;
531 /* Set to NULL, so full_shutdown_tnc() knows whether it was initialized: */
532 platform_context->lpc_dev = NULL;
535 * finds the bus, device, func to be returned. Do this for D2:F0 only.
536 * the OS does not need to know the existence of D3:F0
538 OS_PCI_GET_SLOT_ADDRESS(vga_dev, bus, slot, func);
540 get_revision_id_tnc(context, vga_dev, platform_context->pcidev1);
544 * This must be in query so it is available early for the vBIOS.
546 if(OS_PCI_READ_CONFIG_32(vga_dev,
547 TNC_PCI_BSM, &context->device_context.fb_adr)) {
548 EMGD_ERROR_EXIT("Reading BSM");
549 return -IGD_ERROR_NODEV;
551 context->device_context.fb_adr &= 0xFFFFF000;
553 EMGD_DEBUG("BSM (High)@: 0x%lx, (Low) 0x%4lx",
554 (context->device_context.fb_adr >> 16), context->device_context.fb_adr);
558 * This must be in query so it is available early for the vBIOS.
560 if(OS_PCI_READ_CONFIG_16(vga_dev, TNC_PCI_IOBAR, &io_base)) {
561 EMGD_ERROR_EXIT("Reading IO Base");
562 return -IGD_ERROR_NODEV;
565 /* Base Address is defined in Bits 15:3*/
566 io_base_lvds = io_base &= 0xfff8;
567 EMGD_DEBUG("io @: 0x%x", io_base);
569 /* Gen4 is always io_mapped */
570 io_mapped_lvds = io_mapped = 1;
572 /* Set dev3 iobase. */
573 if(OS_PCI_READ_CONFIG_16((os_pci_dev_t)platform_context->pcidev1,
574 TNC_PCI_IOBAR, &io_base_sdvo)) {
576 EMGD_ERROR_EXIT("Reading SDVO IO Base");
577 return -IGD_ERROR_NODEV;
580 /* Base Address is defined in Bits 15:3*/
581 io_base_sdvo &= 0xfff8;
584 EMGD_DEBUG("sdvo io @: 0x%x", io_base_sdvo);
586 /* Set stmicro sdvo iobase. */
587 if(OS_PCI_READ_CONFIG_16((os_pci_dev_t)platform_context->stbridgedev,
588 TNC_PCI_IOBAR, &io_base_sdvo_st)) {
590 EMGD_ERROR_EXIT("Reading SDVO IO Base");
591 return -IGD_ERROR_NODEV;
594 /* Base Address is defined in Bits 15:3*/
595 io_base_sdvo_st &= 0xfff8;
597 io_mapped_sdvo_st = 1;
598 EMGD_DEBUG("STMicro's sdvo io @: 0x%x", io_base_sdvo_st);
600 /* Set stmicro gpio sdvo iobase. */
601 if(OS_PCI_READ_CONFIG_16((os_pci_dev_t)platform_context->stgpiodev,
602 TNC_PCI_IOBAR, &io_base_sdvo_st_gpio)) {
604 EMGD_ERROR_EXIT("Reading SDVO IO Base");
605 return -IGD_ERROR_NODEV;
608 /* Base Address is defined in Bits 15:3*/
609 io_base_sdvo_st_gpio &= 0xfff8;
611 io_mapped_sdvo_st_gpio = 1;
612 EMGD_DEBUG("STMicro's gpio io @: 0x%x", io_base_sdvo_st_gpio);
614 /* ---------------------------------------------------
615 * Initialize Device 31 : LPC Interface
616 * --------------------------------------------------*/
618 * Map the LPC Interface Configuration [D31:F0]GPIO_BAR.
619 * The Atom E6xx LVDS pins are connected to GPIO pins,
620 * accessible using LPC Interface GPIO_BAR. These registers
621 * will later be used to "bit bash" the LVDS DDC signals
622 * SDVO does not need these registers.
623 * VBIOS may need access to these registers
626 platform_context->lpc_dev = OS_PCI_FIND_DEVICE(PCI_VENDOR_ID_INTEL,
627 PCI_DEVICE_ID_LPC_TNC,
629 31, /* LPC[D31:F0] */
633 if(!platform_context->lpc_dev){
635 * We could not detect the LPC interface in the PCI Bus. This will
636 * be a problem. Sound the alarm, return with NO ERROR so that we do
637 * not go and map the GPIO_BAR
639 EMGD_ERROR_EXIT("Reading GPIO BAR");
643 /* Set dev31 iobase */
645 /* Do not enable LPC device as System BIOS owns and does this */
647 /* read the GPIO BAR (OFFSET 44:47) */
648 if(OS_PCI_READ_CONFIG_16(platform_context->lpc_dev,
649 TNC_PCI_GBA, &io_base_lpc)) {
650 EMGD_ERROR_EXIT("Reading LPC GPIO BAR");
651 /* We cannot read the GPIO BAR. It is a problem but we can go on with init
652 * return with NO ERROR*/
656 io_base_lpc &= 0xffc0;
659 EMGD_DEBUG("lpc io @: 0x%x", io_base_lpc);
670 * @return -IGD_ERROR_NODEV on failure
671 * @return 0 on success
673 static int config_tnc(igd_context_t *context,
674 init_dispatch_t *dispatch)
676 unsigned long freq[2];
677 platform_context_tnc_t *platform_context = &platform_context_tnc;
680 unsigned int lp_ctrl_reg;
681 unsigned int hp_ctrl_reg;
682 unsigned int ved_cg_dis_reg;
687 OPT_MICRO_CALL(full_config_tnc(context, dispatch));
689 /* Get graphics and core frequency param if it exists */
690 if(!get_param_tnc(context, IGD_PARAM_GFX_FREQ,
692 context->device_context.gfx_freq = (unsigned short)freq[0];
693 context->device_context.core_freq = (unsigned short)freq[1];
698 * Coreclk register above is used to determine some clocking information
699 * there is also a fuse to limit the dclk. More research needed.
701 /* From KT: Atom E6xx LVDS min and max dot clocks are 19.75 MHz to 79.5 MHz,
702 * Atom E6xx SDVO min and max dot clocks are 25 MHz to 165 MHz */
703 context->device_context.max_dclk = 79500; /* in KHz */
706 /* This breaks VBIOS LVDS display. If this is truly a workaround for
707 * system BIOS then we need to understand what the system BIOS is going
708 * to do and make sure it doesn't re-break VBIOS. The hp_ctrl_reg write
709 * is the write that actually breaks LVDS display. Tested with BIOS34
710 * which has the P-Unit workaround and LVDS still works.
713 /* This is just a workaround.
714 * GVD.G_LP_Control register is set to default mode for BIT0~BIT3.
715 * GVD.H_HP Control register's BIT1 is set 1.
716 * TODO: Removed this after this is fix in system BIOS.
718 lp_ctrl_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f4);
720 lp_ctrl_reg &= ~(BIT2 | BIT3);
721 EMGD_WRITE32(lp_ctrl_reg, EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f4);
723 hp_ctrl_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f8);
725 EMGD_WRITE32(hp_ctrl_reg, EMGD_MMIO(context->device_context.virt_mmadr) + 0x20f8);
727 /* This is just a workaround.
728 * GVD.VED_CG_DIS register is set to disable clock gating for BIT16, BIT0~BIT8.
729 * Tested with Punit B0_500309_CFG2 and Punit C0_060510_CFG2 in BIOS39 and
732 ved_cg_dis_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x2064);
733 ved_cg_dis_reg |= (BIT16 | BIT8 | 0xFF);
734 EMGD_WRITE32(ved_cg_dis_reg, EMGD_MMIO(context->device_context.virt_mmadr) + 0x2064);
736 /* read out the fuse values */
740 gtt_init_tnc(context);
743 * Setting the LBB to 0xFF if it is 0.
744 * This register is used to dynamic LVDS backlight control. By default,
745 * the register will reset to 0x0, this will cause the LVDS to be "off" when
746 * PD_ATTR_ID_BLM_LEGACY_MODE attribute is set. Customers could write
747 * application to set this register.
749 * TODO: The right way to fix this is to check for the attribute in lvds.c
750 * then set the register through pd. But this will add more code to VBIOS
751 * (as we need to add dispatch functions in pd)
754 if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0, 0xF4, &lbb)) {
755 EMGD_DEBUG("Reading Legacy Backlight Brightness");
756 return -IGD_ERROR_NODEV;
759 if(OS_PCI_WRITE_CONFIG_32(platform_context->pcidev0,
760 0xF4, (lbb | 0xFF))){
761 EMGD_DEBUG("Writing into Legacy Backlight Brightness");
762 return -IGD_ERROR_INVAL;
777 * @return -IGD_ERROR_INVAL on failure
778 * @return 0 on success
780 static int get_param_tnc(igd_context_t *context, unsigned long id,
781 unsigned long *value)
783 #define FB_SKU_MASK (BIT12|BIT13|BIT14)
784 #define FB_SKU_SHIFT 12
785 #define FB_GFX_CLOCK_DIVIDE_MASK (BIT20|BIT21|BIT22)
786 #define FB_GFX_CLOCK_DIVIDE_SHIFT 20
789 unsigned long control_reg;
791 unsigned short ratio;
795 EMGD_DEBUG("ID: 0x%lx", id);
797 /* Scratch registers used as below:
801 * Bits 31-16 - EID Firmware identifier 0xE1DF
802 * Bits 15-00 - Tell what data is present.
803 * Here are bits for what we are using know:
805 * Bit 1 - List of ports for which displays are attached
806 * Bit 2 - Memory reservation
807 * If any of the above bits is set that mean data is followed
808 * in the next registers.
812 * Bits 07-00 - Panel Id
813 * Bits 11-08 - Port list
814 * Information for Port list: If any of the bit is set means,
815 * a display is attached to that port as follows:
817 * Bit 09 - DVOA/Internal LVDS
823 * Bits 15-00 - Reserved Memory value in number of 4k size pages
828 case IGD_PARAM_PORT_LIST:
830 control_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) +
834 * Verify that the Embedded Firware is present.
836 if ((control_reg>>16) != 0xE1DF) {
837 EMGD_DEBUG("Exit No Embedded vBIOS found");
839 return -IGD_ERROR_INVAL;
843 * If the port list bit is set in control register,
846 if (control_reg & 0x2) {
850 temp = (unsigned char)((EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x71414)>>8) & 0xFF);
851 EMGD_DEBUG("Connected Port Bits: 0x%x", temp);
854 * The meanings of bits in temp were dictated by VBIOS
855 * and should not change due to backward compatibility
859 /* Internal LVDS port */
867 EMGD_DEBUG("Port List read failed: Incorrect Operation");
868 ret = -IGD_ERROR_INVAL;
871 case IGD_PARAM_GFX_FREQ:
873 /* Read the fuse value */
874 if(query_sch_message(READ_FUS_EFF3, &control_reg)){
875 EMGD_ERROR("Cannot read GFX clock");
877 EMGD_DEBUG("SKU [reg 0x%x] value = 0x%lx", READ_FUS_EFF3, control_reg);
880 * Sku and Ratio bits determine the gfx clock speed
881 * sku - 0:sku_100 1:sku_100L 2:sku_83
882 * ratio - 0-1:1 1-4:3 2-8:5 3-2:1 4-16:7(rsvd) 5-8:3 6-16:5 7:4:1(rsvd)
884 sku = (unsigned short)((control_reg & FB_SKU_MASK) >> FB_SKU_SHIFT) & 0x3;
885 ratio = (unsigned short)((control_reg & FB_GFX_CLOCK_DIVIDE_MASK) >> FB_GFX_CLOCK_DIVIDE_SHIFT) & 0x7;
887 EMGD_DEBUG("sku = 0x%x Ratio = 0x%x", sku, ratio);
889 if(sku < SKU_NO && ratio < RATIO_NO){
890 /* get the graphics clock speed from the sku-ratio array */
891 value[0] = tnc_gfx_freq_list[ratio][sku];
892 value[1] = tnc_core_freq_list[sku];
894 EMGD_ERROR("tnc_gfx_freq_list ARRAY OUT OF RANGE");
895 /* set to the lowest default value */
900 EMGD_DEBUG("TNC GFX core frequency = %lu MHz", value[0]);
901 EMGD_DEBUG("TNC Core clock frequency = %lu MHz", value[1]);
906 /* If the param is not found here then it may only be in the
909 OPT_MICRO_CALL_RET(ret, full_get_param_tnc(context, id, value));
923 * @return -IGD_ERROR_INVAL
925 static int set_param_tnc(igd_context_t *context, unsigned long id,
932 * Functions reads all the fuse values and dumps out the value
933 * @return -IGD_ERROR_INVAL
936 static int dump_fuse_values(void)
938 unsigned long value = 0;
940 if(query_sch_message(READ_FUS_EFF0, &value)){
941 EMGD_ERROR_EXIT("Reading Fuse Value Failed");
943 EMGD_DEBUG("READ_FUS_EFF0 [%lx]", value);
945 if(query_sch_message(READ_FUS_EFF1, &value)){
946 EMGD_ERROR_EXIT("Reading Fuse Value Failed");
948 EMGD_DEBUG("READ_FUS_EFF1 [%lx]", value);
950 if(query_sch_message(READ_FUS_EFF2, &value)){
951 EMGD_ERROR_EXIT("Reading Fuse Value Failed");
953 EMGD_DEBUG("READ_FUS_EFF2 [%lx]", value);
955 if(query_sch_message(READ_FUS_EFF3, &value)){
956 EMGD_ERROR_EXIT("Reading Fuse Value Failed");
958 EMGD_DEBUG("READ_FUS_EFF3 [%lx]", value);
960 if(query_sch_message(READ_FUS_EFF4, &value)){
961 EMGD_ERROR_EXIT("Reading Fuse Value Failed");
963 EMGD_DEBUG("READ_FUS_EFF4 [%lx]", value);
965 if(query_sch_message(READ_FUS_EFF5, &value)){
966 EMGD_ERROR_EXIT("Reading Fuse Value Failed");
968 EMGD_DEBUG("READ_FUS_EFF5 [%lx]", value);
979 static void shutdown_tnc(igd_context_t *context)
981 gtt_shutdown_tnc(context);
983 OPT_MICRO_VOID_CALL(full_shutdown_tnc(context));
993 * @return -IGD_ERROR_NODEV on failure
994 * @return 0 on success
996 int get_revision_id_tnc(igd_context_t *context,
997 os_pci_dev_t vga_dev,
998 os_pci_dev_t sdvo_dev)
1000 platform_context_tnc_t *platform_context;
1004 platform_context = (platform_context_tnc_t *)context->platform_context;
1007 if(OS_PCI_READ_CONFIG_8(vga_dev, PCI_RID,
1008 (unsigned char *)&context->device_context.rid)) {
1009 EMGD_ERROR_EXIT("Error occured reading RID");
1010 return -IGD_ERROR_NODEV;
1013 if(OS_PCI_READ_CONFIG_8(sdvo_dev, PCI_RID,
1014 &platform_context->tnc_dev3_rid)) {
1015 EMGD_ERROR_EXIT("Error occured reading TNC SDVO RID");
1016 return -IGD_ERROR_NODEV;
1019 EMGD_DEBUG(" rid = 0x%lx", context->device_context.rid);