drivers/video/fbdev/geode/display_gx1.c

Source file repositories/reference/linux-study-clean/drivers/video/fbdev/geode/display_gx1.c

File Facts

System
Linux kernel
Corpus path
drivers/video/fbdev/geode/display_gx1.c
Extension
.c
Size
6114 bytes
Lines
211
Domain
Driver Families
Bucket
drivers/video
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * drivers/video/geode/display_gx1.c
 *   -- Geode GX1 display controller
 *
 * Copyright (C) 2005 Arcom Control Systems Ltd.
 *
 * Based on AMD's original 2.4 driver:
 *   Copyright (C) 2004 Advanced Micro Devices, Inc.
 */
#include <linux/spinlock.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/div64.h>
#include <asm/delay.h>

#include "geodefb.h"
#include "display_gx1.h"

static DEFINE_SPINLOCK(gx1_conf_reg_lock);

static u8 gx1_read_conf_reg(u8 reg)
{
	u8 val, ccr3;
	unsigned long flags;

	spin_lock_irqsave(&gx1_conf_reg_lock, flags);

	outb(CONFIG_CCR3, 0x22);
	ccr3 = inb(0x23);
	outb(CONFIG_CCR3, 0x22);
	outb(ccr3 | CONFIG_CCR3_MAPEN, 0x23);
	outb(reg, 0x22);
	val = inb(0x23);
	outb(CONFIG_CCR3, 0x22);
	outb(ccr3, 0x23);

	spin_unlock_irqrestore(&gx1_conf_reg_lock, flags);

	return val;
}

unsigned gx1_gx_base(void)
{
	return (gx1_read_conf_reg(CONFIG_GCR) & 0x03) << 30;
}

int gx1_frame_buffer_size(void)
{
	void __iomem *mc_regs;
	u32 bank_cfg;
	int d;
	unsigned dram_size = 0, fb_base;

	mc_regs = ioremap(gx1_gx_base() + 0x8400, 0x100);
	if (!mc_regs)
		return -ENOMEM;


	/* Calculate the total size of both DIMM0 and DIMM1. */
	bank_cfg = readl(mc_regs + MC_BANK_CFG);

	for (d = 0; d < 2; d++) {
		if ((bank_cfg & MC_BCFG_DIMM0_PG_SZ_MASK) != MC_BCFG_DIMM0_PG_SZ_NO_DIMM)
			dram_size += 0x400000 << ((bank_cfg & MC_BCFG_DIMM0_SZ_MASK) >> 8);
		bank_cfg >>= 16; /* look at DIMM1 next */
	}

	fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;

	iounmap(mc_regs);

	return dram_size - fb_base;
}

static void gx1_set_mode(struct fb_info *info)
{
	struct geodefb_par *par = info->par;
	u32 gcfg, tcfg, ocfg, dclk_div, val;
	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;

	/* Unlock the display controller registers. */
	readl(par->dc_regs + DC_UNLOCK);
	writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);

	gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
	tcfg = readl(par->dc_regs + DC_TIMING_CFG);

Annotation

Implementation Notes