aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2005-07-29 17:03:33 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-29 18:01:14 -0400
commite4c5c82024f5f292c0069cf40422b8f3bf5e684e (patch)
tree09a6633c9a9d9ec388f90f1b12f2ea2553130ac3
parente1afc3f522ed088405fc8932110d338330db82bb (diff)
[PATCH] fbdev: Replace memcpy with for-loop when preparing bitmap
Do not use memcpy in fb_pad_aligned_buffer. It is suboptimal because only a few bytes are moved at a time. Replace with a for-loop. Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/video/fbmem.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 40784a944d05..d2e19f6dd72c 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -80,10 +80,12 @@ EXPORT_SYMBOL(fb_get_color_depth);
80 */ 80 */
81void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) 81void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
82{ 82{
83 int i; 83 int i, j;
84 84
85 for (i = height; i--; ) { 85 for (i = height; i--; ) {
86 memcpy(dst, src, s_pitch); 86 /* s_pitch is a few bytes at the most, memcpy is suboptimal */
87 for (j = 0; j < s_pitch; j++)
88 dst[j] = src[j];
87 src += s_pitch; 89 src += s_pitch;
88 dst += d_pitch; 90 dst += d_pitch;
89 } 91 }
#n120'>120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232











                                                           
                       






                                                       
                                       








                                                   
                                    



                                                              
                                   








                                                               
                                   



























                                                                    







                                           


























                                                                   






                                   











































                                                                     
                                        










                                                                    

                                      






                                                               


















































                                                                
/* rtc-bq4802.c: TI BQ4802 RTC driver.
 *
 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/slab.h>

MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
MODULE_DESCRIPTION("TI BQ4802 RTC driver");
MODULE_LICENSE("GPL");

struct bq4802 {
	void __iomem		*regs;
	unsigned long		ioport;
	struct rtc_device	*rtc;
	spinlock_t		lock;
	struct resource		*r;
	u8 (*read)(struct bq4802 *, int);
	void (*write)(struct bq4802 *, int, u8);
};

static u8 bq4802_read_io(struct bq4802 *p, int off)
{
	return inb(p->ioport + off);
}

static void bq4802_write_io(struct bq4802 *p, int off, u8 val)
{
	outb(val, p->ioport + off);
}

static u8 bq4802_read_mem(struct bq4802 *p, int off)
{
	return readb(p->regs + off);
}

static void bq4802_write_mem(struct bq4802 *p, int off, u8 val)
{
	writeb(val, p->regs + off);
}

static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct bq4802 *p = platform_get_drvdata(pdev);
	unsigned long flags;
	unsigned int century;
	u8 val;

	spin_lock_irqsave(&p->lock, flags);

	val = p->read(p, 0x0e);
	p->write(p, 0xe, val | 0x08);

	tm->tm_sec = p->read(p, 0x00);
	tm->tm_min = p->read(p, 0x02);
	tm->tm_hour = p->read(p, 0x04);
	tm->tm_mday = p->read(p, 0x06);
	tm->tm_mon = p->read(p, 0x09);
	tm->tm_year = p->read(p, 0x0a);
	tm->tm_wday = p->read(p, 0x08);
	century = p->read(p, 0x0f);

	p->write(p, 0x0e, val);

	spin_unlock_irqrestore(&p->lock, flags);

	tm->tm_sec = bcd2bin(tm->tm_sec);
	tm->tm_min = bcd2bin(tm->tm_min);
	tm->tm_hour = bcd2bin(tm->tm_hour);
	tm->tm_mday = bcd2bin(tm->tm_mday);
	tm->tm_mon = bcd2bin(tm->tm_mon);
	tm->tm_year = bcd2bin(tm->tm_year);
	tm->tm_wday = bcd2bin(tm->tm_wday);
	century = bcd2bin(century);

	tm->tm_year += (century * 100);
	tm->tm_year -= 1900;

	tm->tm_mon--;

	return 0;
}

static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct bq4802 *p = platform_get_drvdata(pdev);
	u8 sec, min, hrs, day, mon, yrs, century, val;
	unsigned long flags;
	unsigned int year;

	year = tm->tm_year + 1900;
	century = year / 100;
	yrs = year % 100;

	mon = tm->tm_mon + 1;   /* tm_mon starts at zero */
	day = tm->tm_mday;
	hrs = tm->tm_hour;
	min = tm->tm_min;
	sec = tm->tm_sec;

	sec = bin2bcd(sec);
	min = bin2bcd(min);
	hrs = bin2bcd(hrs);
	day = bin2bcd(day);
	mon = bin2bcd(mon);
	yrs = bin2bcd(yrs);
	century = bin2bcd(century);

	spin_lock_irqsave(&p->lock, flags);

	val = p->read(p, 0x0e);
	p->write(p, 0x0e, val | 0x08);

	p->write(p, 0x00, sec);
	p->write(p, 0x02, min);
	p->write(p, 0x04, hrs);
	p->write(p, 0x06, day);
	p->write(p, 0x09, mon);
	p->write(p, 0x0a, yrs);
	p->write(p, 0x0f, century);

	p->write(p, 0x0e, val);

	spin_unlock_irqrestore(&p->lock, flags);

	return 0;
}

static const struct rtc_class_ops bq4802_ops = {
	.read_time	= bq4802_read_time,
	.set_time	= bq4802_set_time,
};

static int __devinit bq4802_probe(struct platform_device *pdev)
{
	struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL);
	int err = -ENOMEM;

	if (!p)
		goto out;

	spin_lock_init(&p->lock);

	p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!p->r) {
		p->r = platform_get_resource(pdev, IORESOURCE_IO, 0);
		err = -EINVAL;
		if (!p->r)
			goto out_free;
	}
	if (p->r->flags & IORESOURCE_IO) {
		p->ioport = p->r->start;
		p->read = bq4802_read_io;
		p->write = bq4802_write_io;
	} else if (p->r->flags & IORESOURCE_MEM) {
		p->regs = ioremap(p->r->start, resource_size(p->r));
		p->read = bq4802_read_mem;
		p->write = bq4802_write_mem;
	} else {
		err = -EINVAL;
		goto out_free;
	}

	platform_set_drvdata(pdev, p);

	p->rtc = rtc_device_register("bq4802", &pdev->dev,
				     &bq4802_ops, THIS_MODULE);
	if (IS_ERR(p->rtc)) {
		err = PTR_ERR(p->rtc);
		goto out_iounmap;
	}

	err = 0;
out:
	return err;

out_iounmap:
	if (p->r->flags & IORESOURCE_MEM)
		iounmap(p->regs);
out_free:
	kfree(p);
	goto out;
}

static int __devexit bq4802_remove(struct platform_device *pdev)
{
	struct bq4802 *p = platform_get_drvdata(pdev);

	rtc_device_unregister(p->rtc);
	if (p->r->flags & IORESOURCE_MEM)
		iounmap(p->regs);

	platform_set_drvdata(pdev, NULL);

	kfree(p);

	return 0;
}

/* work with hotplug and coldplug */
MODULE_ALIAS("platform:rtc-bq4802");

static struct platform_driver bq4802_driver = {
	.driver		= {
		.name	= "rtc-bq4802",
		.owner	= THIS_MODULE,
	},
	.probe		= bq4802_probe,
	.remove		= __devexit_p(bq4802_remove),
};

static int __init bq4802_init(void)
{
	return platform_driver_register(&bq4802_driver);
}

static void __exit bq4802_exit(void)
{
	platform_driver_unregister(&bq4802_driver);
}

module_init(bq4802_init);
module_exit(bq4802_exit);