public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Antonino A. Daplas" <adaplas@gmail.com>
To: Alan Hourihane <alanh@fairlite.demon.co.uk>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH 01/01] New FBDev driver for Intel Vermilion Range
Date: Fri, 06 Apr 2007 08:09:18 +0800	[thread overview]
Message-ID: <1175818158.31131.63.camel@daplas> (raw)
In-Reply-To: <1175769886.10382.29.camel@localhost>

On Thu, 2007-04-05 at 11:44 +0100, Alan Hourihane wrote:
> Attached is a patch against 2.6.21-rc5 which adds the Intel Vermilion
> Range support.
> 
> Intel funded Tungsten Graphics to do this work.
> 
> If there's any problems or updates needed to be done to get accepted,
> please let me know.
> 

Preferably, add sparse annotations and compile with make C=1. I've
included possible sparse annotations (the only ones I can see) below.
> 
> +
> +struct cr_sys {
> +	struct vml_sys sys;
> +	struct pci_dev *mch_dev;
> +	struct pci_dev *lpc_dev;
> +	__u32 mch_bar;
> +	__u8 *mch_regs_base;

void __iomem *mch_regs_base; (sparse)

> +	__u32 gpio_bar;
> +	__u32 saved_panel_state;
> +	__u32 saved_clock;
> +};
> +
> 
> +static void crvml_panel_on(const struct vml_sys *sys)
> +{
> +	const struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +	__u32 addr = crsys->gpio_bar + CRVML_PANEL_PORT;
> +	__u32 cur = inl(addr);
> +
> +	if (!(cur & CRVML_PANEL_ON)) {
> +		/* Make sure LVDS controller is down. */
> +		if (cur & 0x00000001) {
> +			cur &= ~CRVML_LVDS_ON;
> +			outl(cur, addr);
> +		}
> +		/* Power up Panel */
> +		schedule_timeout(HZ / 10);
> +		cur |= CRVML_PANEL_ON;
> +		outl(cur, addr);
> +	}
> +
> +	/* Power up LVDS controller */
> +
> +	if (!(cur & CRVML_LVDS_ON)) {
> +		schedule_timeout(HZ / 10);
> +		outl(cur | CRVML_LVDS_ON, addr);
> +	}
> +}
> +
> +static void crvml_panel_off(const struct vml_sys *sys)
> +{
> +	const struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +
> +	__u32 addr = crsys->gpio_bar + CRVML_PANEL_PORT;
> +	__u32 cur = inl(addr);
> +
> +	/* Power down LVDS controller first to avoid high currents */
> +	if (cur & CRVML_LVDS_ON) {
> +		cur &= ~CRVML_LVDS_ON;
> +		outl(cur, addr);
> +	}
> +	if (cur & CRVML_PANEL_ON) {
> +		schedule_timeout(HZ / 10);
> +		outl(cur & ~CRVML_PANEL_ON, addr);
> +	}
> +}
> +
> +static void crvml_backlight_on(const struct vml_sys *sys)
> +{
> +	const struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +	__u32 addr = crsys->gpio_bar + CRVML_PANEL_PORT;
> +	__u32 cur = inl(addr);
> +
> +	if (cur & CRVML_BACKLIGHT_OFF) {
> +		cur &= ~CRVML_BACKLIGHT_OFF;
> +		outl(cur, addr);
> +	}
> +}
> +
> +static void crvml_backlight_off(const struct vml_sys *sys)
> +{
> +	const struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +	__u32 addr = crsys->gpio_bar + CRVML_PANEL_PORT;
> +	__u32 cur = inl(addr);
> +
> +	if (!(cur & CRVML_BACKLIGHT_OFF)) {
> +		cur |= CRVML_BACKLIGHT_OFF;
> +		outl(cur, addr);
> +	}
> +}
> 

Perhaps backling_on/off and panel_on/off can be moved to the backlight
subsystem?

> +
> 
> +static int crvml_sys_restore(struct vml_sys *sys)
> +{
> +	struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +	__u32 *clock_reg = (__u32 *) (crsys->mch_regs_base + CRVML_REG_CLOCK);

__u32 __iomem *clock_reg = crsys->mch_regs_base + CRVML_REG_CLOCK; (sparse)

> +	__u32 cur = crsys->saved_panel_state;
> +
> +	if (cur & CRVML_BACKLIGHT_OFF) {
> +		crvml_backlight_off(sys);
> +	} else {
> +		crvml_backlight_on(sys);
> +	}
> +
> +	if (cur & CRVML_PANEL_ON) {
> +		crvml_panel_on(sys);
> +	} else {
> +		crvml_panel_off(sys);
> +		if (cur & CRVML_LVDS_ON) {
> +			;
> +			/* Will not power up LVDS controller while panel is off */
> +		}
> +	}
> +	iowrite32(crsys->saved_clock, clock_reg);
> +	ioread32(clock_reg);
> +
> +	return 0;
> +}
> +
> +static int crvml_sys_save(struct vml_sys *sys)
> +{
> +	struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +	__u32 *clock_reg = (__u32 *) (crsys->mch_regs_base + CRVML_REG_CLOCK);
> +

__u32 __iomem *clock_reg = crsys->mch_regs_base + CRVML_REG_CLOCK; (sparse)

> +	crsys->saved_panel_state = inl(crsys->gpio_bar + CRVML_PANEL_PORT);
> +	crsys->saved_clock = ioread32(clock_reg);
> +
> +	return 0;
> +}
> +
> +static int crvml_nearest_index(const struct vml_sys *sys, int clock)
> +{
> +
> +	int i;
> +	int cur_index;
> +	int cur_diff;
> +	int diff;
> +
> +	cur_index = 0;
> +	cur_diff = clock - crvml_clocks[0];
> +	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
> +	for (i = 1; i < crvml_num_clocks; ++i) {
> +		diff = clock - crvml_clocks[i];
> +		diff = (diff < 0) ? -diff : diff;
> +		if (diff < cur_diff) {
> +			cur_index = i;
> +			cur_diff = diff;
> +		}
> +	}
> +	return cur_index;
> +}
> +
> +static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
> +{
> +	return crvml_clocks[crvml_nearest_index(sys, clock)];
> +}
> +
> +static int crvml_set_clock(struct vml_sys *sys, int clock)
> +{
> +	struct cr_sys *crsys = container_of(sys, struct cr_sys, sys);
> +	__u32 *clock_reg = (__u32 *) (crsys->mch_regs_base + CRVML_REG_CLOCK);
> 

__u32 __iomem *clock_reg = crsys->mch_regs_base + CRVML_REG_CLOCK; (sparse)

> +	int index;
> +	__u32 clock_val;
> +
> +	index = crvml_nearest_index(sys, clock);
> +
> +	if (crvml_clocks[index] != clock)
> +		return -EINVAL;
> +
> +	clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
> +	clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
> +	iowrite32(clock_val, clock_reg);
> +	ioread32(clock_reg);
> +
> +	return 0;
> +}
> +

> +
> +static int __init crvml_init(void)
> +{
> +	int err = 0;
> +	struct vml_sys *sys;
> +	struct cr_sys *crsys;
> +
> +	crsys = (struct cr_sys *)kmalloc(sizeof(*crsys), GFP_KERNEL);
> +
> +	if (!crsys)
> +		return -ENOMEM;
> +
> +	sys = &crsys->sys;
> +	err = crvml_sysinit(crsys);
> +	if (err) {
> +		kfree(crsys);
> +		return err;
> +	}
> +
> +	sys->destroy = crvml_sys_destroy;
> +	sys->subsys = crvml_subsys;
> +	sys->save = crvml_sys_save;
> +	sys->restore = crvml_sys_restore;
> +	sys->prog_clock = crvml_false;
> +	sys->set_clock = crvml_set_clock;
> +	sys->has_panel = crvml_true;

Hmm...

> +
> +#ifndef FB_BLANK_UNBLANK
> +#define FB_BLANK_UNBLANK	VESA_NO_BLANKING
> +#endif
> +#ifndef FB_BLANK_NORMAL
> +#define FB_BLANK_NORMAL		VESA_NO_BLANKING + 1
> +#endif
> +#ifndef FB_BLANK_VSYNC_SUSPEND
> +#define FB_BLANK_VSYNC_SUSPEND	VESA_VSYNC_SUSPEND + 1
> +#endif
> +#ifndef FB_BLANK_HSYNC_SUSPEND
> +#define FB_BLANK_HSYNC_SUSPEND	VESA_HSYNC_SUSPEND + 1
> +#endif
> +#ifndef FB_BLANK_POWERDOWN
> +#define FB_BLANK_POWERDOWN	VESA_POWERDOWN + 1
> +#endif

Since this driver going to be part of the kernel, the above is redundant,
you don't need it.

> 
> +static int __devinit vml_pci_probe(struct pci_dev *dev,
> +				   const struct pci_device_id *id)
> +{
> +	struct vml_info *vinfo;
> +	struct fb_info *info;
> +	struct vml_par *par;
> +	int err = 0;
> +
> +	par = kmalloc(sizeof(*par), GFP_KERNEL);
> +	if (par == NULL)
> +		return -ENOMEM;
> +
> +	vinfo = kmalloc(sizeof(*vinfo), GFP_KERNEL);

You can use kzalloc instead of kmalloc.

> +	if (vinfo == NULL) {
> +		err = -ENOMEM;
> +		goto out_err_0;
> +	}
> +
> +	memset(vinfo, 0, sizeof(*vinfo));
> +	memset(par, 0, sizeof(*par));
> +

You can also use framebuffer_alloc()/framebuffer_release() for
struct fb_info and for par.  But if it is not possible,
set info->device = dev->dev so your driver can show up in sysfs.

> +	vinfo->par = par;
> +	vinfo->pipe = 0;
> +	par->mutex = &global_mutex;
> +	INIT_LIST_HEAD(&par->gpu.head);
> +	par->gpu_list = &global_gpu_list;
> +	par->vdc = dev;
> +	atomic_set(&par->refcount, 1);
> +
> +	switch (id->device) {
> +	case VML_DEVICE_VDC:
> +		if ((err = vmlfb_get_gpu(par)))
> +			goto out_err_1;
> +		if ((err = pci_enable_device(dev)))
> +			goto out_err_1;
> +		pci_set_drvdata(dev, &vinfo->info);
> +		break;
> +	default:
> +		err = -ENODEV;
> +		goto out_err_1;
> +		break;
> +	}
> +
> +	info = &vinfo->info;
> +	info->flags = FBINFO_PARTIAL_PAN_OK;

Since your driver is tristate, do 

info->flags  = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK;

I will probably use this flag later to differentiate driver modules
to fix a bug in the logo drawing code.

You may also wish to add FBINFO_HW_ACCEL_YPAN for faster text scrolling.

> 
> +
> +static void vml_wait_vblank(struct vml_info *vinfo)
> +{
> +	schedule_timeout(HZ / 40);
> 

This is not really wait for vblank, is it?


> +
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
> +static int vmlfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
> +		       unsigned long arg, struct fb_info *info)
> +#else
> +static int vmlfb_ioctl(struct fb_info *info, unsigned int cmd,
> +		       unsigned long arg)
> +#endif
> 

Similarly, you can remove the above version checks.

Tony


  parent reply	other threads:[~2007-04-06  0:09 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-05 10:44 [PATCH 01/01] New FBDev driver for Intel Vermilion Range Alan Hourihane
2007-04-05 17:38 ` Valdis.Kletnieks
2007-04-05 18:42   ` James Simmons
2007-04-05 18:58   ` Alan Hourihane
     [not found] ` <200704052138.08897.arnd@arndb.de>
2007-04-05 21:42   ` Alan Hourihane
2007-04-05 21:56     ` Arnd Bergmann
2007-04-05 22:00     ` Antonino A. Daplas
2007-04-06  0:09 ` Antonino A. Daplas [this message]
2007-04-06 13:39   ` Alan Hourihane
2007-04-09 20:10 ` Pavel Machek
2007-04-20  9:04 ` Alan Hourihane
2007-04-20 13:51   ` Antonino A. Daplas
2007-04-20 13:54     ` Alan Hourihane

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1175818158.31131.63.camel@daplas \
    --to=adaplas@gmail.com \
    --cc=alanh@fairlite.demon.co.uk \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox