Ник:
Пароль:

Контакты

E-mail: info@starterkit.ru
тел.: +7 922 680-21-73
тел.: +7 922 680-21-74
Телеграм: t.me/starterkit_ru
Партнеры:
otladka.com.ua - г.Киев

Способы оплаты

User Info


Добро пожаловать,
Guest

Регистрация или входРегистрация или вход
Потеряли пароль?Потеряли пароль?

Ник:
Пароль:

ПользователейПользователей:11
Поисковых ботовПоисковых ботов:3
ГостейГостей:1

ОбновитьПодробнееВсегоВсего:15
Форум » starterkit.ru » Embedded Linux
lcd siemens s65 & linux
sasa
Добавлено 25.05.2009 20:11 Редактировалось 25.05.2009 20:19 Сообщение: 21
sasa
5

Регистрация: 20.05.2009
Цитата
вот там в самом конце ответ с оринтацие осей ))

да - я там ссылку на дополнительные объяснения пропустил когда смотрел раньше, так что все есть для нормальной работы - вас будет интересовать режим +90 degree либо -90 degree, зависит от того как удобней экран расположен Собственно в драйвере надо всего лишь - правильно проинициализировать lcd а потом всего лишь заполнять весь экран периодически тем что ядро заполняет :)
Спуститься к концу Подняться к началу
Персональная информация
Tyug
Добавлено 26.05.2009 21:51 Сообщение: 22
Tyug
0

Регистрация: 21.05.2009
Спасибо sasa за драйвер.
У меня был тоже дисплей от nokia 6100, правда с контроллером от epson. Вобщем то переделки минимальные, поменять инициализацию, коды команд и ножку reset на gpio повесить,
вредный контроллер, пока не помахаешь ножкой ресета перед запуском не хочет ничего делать.
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 28.05.2009 23:10 Сообщение: 23
sasa
5

Регистрация: 20.05.2009
reset - это вообще не проблема, lph88 очень чуствителен к cs - у него програмное управление команда/данные, если бы не не это можно было перевести spi в 16 битный режим и свести затраты процессора к минимуму, практически к нулю. атмеловский драйвер spi не поддерживает динамическое переключение количество бит на слово - оно просто не реализовано, хотя там буквально пару строк дописать, это вообщето предусмотрено линуксовым фреймворком. Думаю все же займусь этим когда будет время - напишу правильный драйвер для lph88 без атмеловского драйвера spi - сделаю напрямую работу с железом или мб допишу поддержку динамического переключения длины слова, в голове уже все готово :)
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 29.05.2009 21:27 Сообщение: 24
sasa
5

Регистрация: 20.05.2009
Вот немного обновленная версия драйвера - теперь работает фрэймбуферная консоль, для spi создается буфер приема (чтобы не править атмеловский драйвер spi) и поправлена старая ошибка которую недавно заметил - трэд останавливался после того как освобождена память при отключении драйвера.

Код
/*
* Copyright (C) 2009, Alexander Kudjashev <Kudjashev@gmail.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
* Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven
*
* This driver was written to be used with s65 lph88fb lcd
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/uaccess.h>
#include <mach/gpio.h>

/* lcd resolution */
#define X_RES 176
#define Y_RES 132
#define B_PP 16
#define MEM_LEN (X_RES * Y_RES * B_PP / 8)


static u8 lcd_init_data[] __devinitdata = {0x00,0x00,0x01,
0x07,0x00,0x00, 0x02,0x04,0x00, 0x04,0x00,0x00,
0x0C,0x00,0x01, 0x0D,0x06,0x16, 0x0E,0x10,0x10,
0x03,0x00,0x0C, 0x0E,0x2D,0x1F, 0x0D,0x06,0x16,
0x01,0x03,0x15, 0x0F,0x00,0x00, 0x0B,0x00,0x00,
0x11,0x00,0x00, 0x06,0x00,0x00, 0x05,0x00,0x38,
0x14,0xAF,0x00, 0x15,0x00,0x00, 0x16,0x83,0x00,
0x17,0xAF,0x00, 0x20,0x00,0x00, 0x30,0x00,0x00,
0x31,0x04,0x00, 0x32,0x02,0x07, 0x33,0x07,0x00,
0x34,0x00,0x05, 0x35,0x07,0x03, 0x36,0x07,0x07,
0x37,0x00,0x07, 0x3A,0x12,0x00, 0x3B,0x00,0x09,
0x07,0x00,0x05, 0x07,0x00,0x25, 0x07,0x00,0x27,
0x07,0x00,0x37};

static void lcd_comtype(struct spi_device *spi, u8 type)
{
u8 buff[3];

buff[0] = 0x74;
buff[1] = 0x00;
buff[2] = type;

spi_write(spi, buff, 3);
}

static void lcd_comdata(struct spi_device *spi, u8 data1, u8 data2)
{
u8 buff[3];

buff[0] = 0x76;
buff[1] = data1;
buff[2] = data2;

spi_write(spi, buff, 3);
}

static void lcd_command(struct spi_device *spi, u8 *data)
{
lcd_comtype(spi, data[0]);
lcd_comdata(spi, data[1], data[2]);

switch(data[0]) {
/* Power Control - need delay */
case 0x03:
case 0x04:
case 0x0c:
case 0x0d:
case 0x0e:
mdelay(40);
}
}

struct lph88fb_par {
struct spi_message msg;
struct spi_transfer xfer;
struct spi_device *spi;
struct task_struct *lph88fb_thread_task;
u8 *buffer;
u8 *screen;
u8 *rx;
u32 pseudo_palette[16];
};

static struct fb_fix_screeninfo lph88fb_fix __devinitdata = {
.id = "lph88fb",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.xpanstep = 0,
.ypanstep = 0,
.ywrapstep = 0,
.line_length = X_RES * B_PP / 8,
.accel = FB_ACCEL_NONE,
};

static struct fb_var_screeninfo lph88fb_var __devinitdata = {
.xres = X_RES,
.yres = Y_RES,
.xres_virtual = X_RES,
.yres_virtual = Y_RES,
.activate = FB_ACTIVATE_NOW,
.vmode = FB_VMODE_NONINTERLACED,
.bits_per_pixel = B_PP,
.red = { 11, 5, 0 },
.green = { 5, 6, 0 },
.blue = { 0, 5, 0 },
.nonstd = 0,
};

static int lph88fb_setcolreg(unsigned regno, unsigned r, unsigned g,
unsigned b, unsigned transp,
struct fb_info *info)
{

if (regno >= 16)
return -EINVAL;

((u32 *) info->pseudo_palette)[regno] =
(r & 0xf800) | (g & 0xfc00) >> 5 | (b & 0xf800) >> 11;

return 0;
}

static struct fb_ops lph88fb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = lph88fb_setcolreg,
.fb_read = fb_sys_read,
.fb_write = fb_sys_write,
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
};

static int lph88fb_thread(void *param)
{
struct lph88fb_par *par = (struct lph88fb_par *)param;
int i;
u8 *shadow = &par->screen[1];
u8 *buffer = par->buffer;

par->screen[0] = 0x76;

while(!kthread_should_stop()) {
for(i = 0; i < MEM_LEN; i += 2) {
shadow[i] = buffer[i+1];
shadow[i+1] = buffer[i];
}

lcd_comtype(par->spi, 0x21);
lcd_comdata(par->spi, 0x00, 0x00);
lcd_comtype(par->spi, 0x22);

spi_sync(par->spi, &par->msg);
}
return 0;
}

static int __devinit lph88fb_probe(struct spi_device *spi)
{
struct fb_info *info;
struct lph88fb_par *par;
struct spi_message *m;
struct spi_transfer *x;
int retval, i;

spi->max_speed_hz = 20 * 1000 * 1000;
spi->bits_per_word = 8;
spi->mode = SPI_MODE_0;

retval = spi_setup(spi);
if(retval < 0)
return retval;

/* reset lcd controller */
at91_set_gpio_output(AT91_PIN_PB4, 1);
mdelay(10);
at91_set_gpio_value(AT91_PIN_PB4, 0);
mdelay(1);
at91_set_gpio_value(AT91_PIN_PB4, 1);
mdelay(10);

for(i = 0; i < sizeof(lcd_init_data); i += 3)
lcd_command(spi, &lcd_init_data[i]);

retval = -ENOMEM;

info = framebuffer_alloc(sizeof(struct lph88fb_par), &spi->dev);
if(!info)
return retval;

par = info->par;
par->spi = spi;
par->buffer = alloc_pages_exact(MEM_LEN, GFP_KERNEL | __GFP_ZERO);
if(!par->buffer)
goto err;

par->screen = kmalloc(MEM_LEN + 1, GFP_KERNEL);
if(!par->screen)
goto err1;

par->rx = kmalloc(MEM_LEN + 1, GFP_KERNEL);
if(!par->rx)
goto err2;

info->screen_base = par->buffer;
info->fbops = &lph88fb_ops;
info->var = lph88fb_var;
info->fix = lph88fb_fix;
info->fix.smem_len = MEM_LEN;
info->fix.smem_start = (unsigned long)virt_to_phys(info->screen_base);
info->screen_size = MEM_LEN;
info->flags = FBINFO_FLAG_DEFAULT;
info->pseudo_palette = par->pseudo_palette;

retval = fb_alloc_cmap(&(info->cmap), 256, 0);
if (retval < 0)
goto err3;

retval = register_framebuffer(info);
if (retval < 0)
goto err4;

dev_set_drvdata(&spi->dev, info);

m = &par->msg;
x = &par->xfer;

spi_message_init(m);

x->tx_buf = par->screen;
x->rx_buf = par->rx;
x->len = MEM_LEN + 1;

spi_message_add_tail(x, m);

par->lph88fb_thread_task = kthread_run(lph88fb_thread, par, "lph88fb");
retval = -EIO;
if(IS_ERR(par->lph88fb_thread_task))
goto err5;

printk(KERN_INFO "fb%d: %s frame buffer device, %dK of video memory\n",
info->node, info->fix.id, info->fix.smem_len >> 10);

return 0;

err5:
unregister_framebuffer(info);
err4:
fb_dealloc_cmap(&info->cmap);
err3:
kfree(par->rx);
err2:
kfree(par->screen);
err1:
free_pages_exact(par->buffer, MEM_LEN);
err:
framebuffer_release(info);

return retval;
}

static int __devexit lph88fb_remove(struct spi_device *spi)
{
struct fb_info *info = dev_get_drvdata(&spi->dev);

if (info) {
struct lph88fb_par *par = info->par;

kthread_stop(par->lph88fb_thread_task);
unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
kfree(par->rx);
kfree(par->screen);
free_pages_exact(par->buffer, MEM_LEN);
framebuffer_release(info);
}
return 0;
}

/* Power down display on reboot, poweroff or halt */
static void lph88fb_shutdown(struct spi_device *spi)
{
at91_set_gpio_value(AT91_PIN_PB4, 0);
mdelay(1);
at91_set_gpio_value(AT91_PIN_PB4, 1);
mdelay(10);
}

static struct spi_driver lph88fb_driver = {
.driver = {
.name = "lph88fb",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = lph88fb_probe,
.remove = __devexit_p(lph88fb_remove),
.shutdown = lph88fb_shutdown,
};

static int __init lph88fb_init(void)
{
printk("lph88fb spi fb driver\n");
return spi_register_driver(&lph88fb_driver);
}

static void __exit lph88fb_exit(void)
{
spi_unregister_driver(&lph88fb_driver);
}

module_init(lph88fb_init);
module_exit(lph88fb_exit);

MODULE_AUTHOR("Alexander Kudjashev");
MODULE_DESCRIPTION("lph88 spi fb driver");
MODULE_LICENSE("GPL");
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 30.05.2009 20:03 Редактировалось 30.05.2009 21:45 Сообщение: 25
sasa
5

Регистрация: 20.05.2009
http://www.sasamy.narod.ru/bw.jpg
http://www.sasamy.narod.ru/color.jpg
http://www.sasamy.narod.ru/mc.jpg

вот новые картинки - допаял удвоитель на max232 до утроителя, в итоге из 5 В получил на lcd 10 В :) Сейчас светит вполне приемлемо.
Спуститься к концу Подняться к началу
Персональная информация
Lavin (Guest)
Добавлено 01.06.2009 04:07 Сообщение: 26
Lavin (Guest)

А как драйвер компилировать куда кидать и подгружать? как вывести консоль на него(она дублируется с UART или как?)
Вскором времени попробую переписать драйвер под себя.
Огромное спасибо sasa.Не моглибы протестить как видео воспроизводит и чуток на видео поснимать.Жутко руки чешутся повторить сие творение)
Спуститься к концу Подняться к началу
sasa
Добавлено 01.06.2009 11:05 Сообщение: 27
sasa
5

Регистрация: 20.05.2009
Цитата
А как драйвер компилировать куда кидать и подгружать?

Я тут выкладывал патч - он добавляет в меню menuconfig раздел для lph88 и добавляет запись в board-... для spi. Остается только галочки поставить при компиляции ядра.
Цитата
как вывести консоль на него(она дублируется с UART или как?)

Нужно в ядре выбрать в разделе
Device Drivers ---> Graphics support ---> Console display driver support --->Framebuffer Console support и там же Select compiled-in fonts и в нем какой нужен шрифт - я использую самый маленький Mini 4x6 font. Потом в /etc/inittab должен быть запущен getty на tty, например такая строчка должна быть
# Set up a couple of getty's
tty1::respawn:/sbin/getty 38400 tty1 linux
и это естественно не мешает иметь консоль и на uart одновренно - у меня обе включены.
Цитата
Вскором времени попробую переписать драйвер под себя.

если у вас ls020 - то лучше не повторять а сделать намного лучше :) там очень легко сделать spi в 16-ти битном режиме. Я вчера занимался заточкой атмеовского драйвера spi чтобы он на лету переключал 8-16 бит длину слова, не до конца работает, но то что это необходимо сделать - ясно как день. В таком виде как у меня сейчас драйвер сильно грузит процессор - доходит до 10% и это очень плохо, после заточки драйвера загрузка не превышала 1%. Так что оно стоит того. В треде убирается бесполезный цикл для перекидывания байтов, фреймбуфер создается когерентный с дма (может иметь одновременный доступ и дма и процессор) и spi перекидывает напрямую буфер - загрузка процессора минимальная. Если бы не оверхед кода в атмеловских драйверах - практически не должен занимать процессорное время. Я выложу попоздней пример как у меня сделан пробный драйвер чтобы легче было написать для ls020.
Цитата
Не моглибы протестить как видео воспроизводит

я как давно еще с нокией 6100 пытался - не смог заставить mplayer работать с таким нестандартным разрешением хотя и видео переконверчивал в подходящий формат.
Спуститься к концу Подняться к началу
Персональная информация
Lavin (Guest)
Добавлено 01.06.2009 12:29 Сообщение: 28
Lavin (Guest)

1.Разрешение здесь чуть более "стандартное")))
2.Насчет 16 битного режима.Я никогода не работал с портами ввода вывода на данном процессоре через драйвера.Пока что довольно ясно представляю как переделать вышепреведенный драйвер для ls020.Если вас не затруднит не могли бы выложить примерные наброски для 16 битного режима
3.Патч вроде нашел.Думаю не буду менять lph88 на ls020.только код другой подсуну.а то новечек буду большую часть времени тыкаться что где то не подправил
Спуститься к концу Подняться к началу
sasa
Добавлено 01.06.2009 13:37 Сообщение: 29
sasa
5

Регистрация: 20.05.2009
Вот рабочая версия с динамическим переключением 8-16 бит. Если бы в атмеловских драйверов была реализована эта ф-ция (а это стандартная ф-ция linux фреймворка spi) он бы работал без правки атмеловских драйверов (он работает с моими правками но глюкаво - есть артефакты и картинка дрожжит :)

Цитата
/*
* Copyright (C) 2009, Alexander Kudjashev <Kudjashev@gmail.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
* Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven
*
* This driver was written to be used with s65 lph88fb lcd
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
//#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/uaccess.h>
#include <mach/gpio.h>

/* lcd resolution */
#define X_RES 176
#define Y_RES 132
#define B_PP 16
#define MEM_LEN (X_RES * Y_RES * B_PP / 8)


static u8 lcd_init_data[] __devinitdata = {0x00,0x00,0x01,
0x07,0x00,0x00, 0x02,0x04,0x00, 0x04,0x00,0x00,
0x0C,0x00,0x01, 0x0D,0x06,0x16, 0x0E,0x10,0x10,
0x03,0x00,0x0C, 0x0E,0x2D,0x1F, 0x0D,0x06,0x16,
0x01,0x03,0x15, 0x0F,0x00,0x00, 0x0B,0x00,0x00,
0x11,0x00,0x00, 0x06,0x00,0x00, 0x05,0x00,0x38,
0x14,0xAF,0x00, 0x15,0x00,0x00, 0x16,0x83,0x00,
0x17,0xAF,0x00, 0x20,0x00,0x00, 0x30,0x00,0x00,
0x31,0x04,0x00, 0x32,0x02,0x07, 0x33,0x07,0x00,
0x34,0x00,0x05, 0x35,0x07,0x03, 0x36,0x07,0x07,
0x37,0x00,0x07, 0x3A,0x12,0x00, 0x3B,0x00,0x09,
0x07,0x00,0x05, 0x07,0x00,0x25, 0x07,0x00,0x27,
0x07,0x00,0x37};

static void lcd_comtype(struct spi_device *spi, u8 type)
{
u8 buff[3];

buff[0] = 0x74;
buff[1] = 0x00;
buff[2] = type;

spi_write(spi, buff, 3);
}

static void lcd_comdata(struct spi_device *spi, u8 data1, u8 data2)
{
u8 buff[3];

buff[0] = 0x76;
buff[1] = data1;
buff[2] = data2;

spi_write(spi, buff, 3);
}

static void lcd_command(struct spi_device *spi, u8 *data)
{
lcd_comtype(spi, data[0]);
lcd_comdata(spi, data[1], data[2]);

switch(data[0]) {
/* Power Control - need delay */
case 0x03:
case 0x04:
case 0x0c:
case 0x0d:
case 0x0e:
mdelay(40);
}
}

struct lph88fb_par {
struct spi_message msg;
struct spi_transfer xfer1;
struct spi_transfer xfer2;
struct spi_device *spi;
struct task_struct *lph88fb_thread_task;
u8 *fb_virt;
dma_addr_t fb_phys;
u32 pseudo_palette[16];
};

static struct fb_fix_screeninfo lph88fb_fix __devinitdata = {
.id = "lph88fb",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.xpanstep = 0,
.ypanstep = 0,
.ywrapstep = 0,
.line_length = X_RES * B_PP / 8,
.accel = FB_ACCEL_NONE,
};

static struct fb_var_screeninfo lph88fb_var __devinitdata = {
.xres = X_RES,
.yres = Y_RES,
.xres_virtual = X_RES,
.yres_virtual = Y_RES,
.activate = FB_ACTIVATE_NOW,
.vmode = FB_VMODE_NONINTERLACED,
.bits_per_pixel = B_PP,
.red = { 11, 5, 0 },
.green = { 5, 6, 0 },
.blue = { 0, 5, 0 },
.nonstd = 0,
};

static int lph88fb_setcolreg(unsigned regno, unsigned r, unsigned g,
unsigned b, unsigned transp,
struct fb_info *info)
{

if (regno >= 16)
return -EINVAL;

((u32 *) info->pseudo_palette)[regno] =
(r & 0xf800) | (g & 0xfc00) >> 5 | (b & 0xf800) >> 11;

return 0;
}

static struct fb_ops lph88fb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = lph88fb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};

static int lph88fb_thread(void *param)
{
struct lph88fb_par *par = (struct lph88fb_par *)param;

while(!kthread_should_stop()) {

lcd_comtype(par->spi, 0x21);
lcd_comdata(par->spi, 0x00, 0x00);
lcd_comtype(par->spi, 0x22);

spi_sync(par->spi, &par->msg);
}
return 0;
}

static int __devinit lph88fb_probe(struct spi_device *spi)
{
struct fb_info *info;
struct lph88fb_par *par;
struct spi_message *m;
struct spi_transfer *x;
int retval, i;

spi->max_speed_hz = 12 * 1000 * 1000;
spi->bits_per_word = 8;
spi->mode = SPI_MODE_0;

retval = spi_setup(spi);
if(retval < 0)
return retval;

/* reset lcd controller */
at91_set_gpio_output(AT91_PIN_PB4, 1);
mdelay(10);
at91_set_gpio_value(AT91_PIN_PB4, 0);
mdelay(1);
at91_set_gpio_value(AT91_PIN_PB4, 1);
mdelay(10);

for(i = 0; i < sizeof(lcd_init_data); i += 3)
lcd_command(spi, &lcd_init_data[i]);

retval = -ENOMEM;

info = framebuffer_alloc(sizeof(struct lph88fb_par), &spi->dev);
if(!info)
return retval;

par = info->par;
par->spi = spi;

par->fb_virt = dma_alloc_coherent(NULL, (MEM_LEN + 1) << 1, &par->fb_phys,
GFP_KERNEL | __GFP_ZERO);
if(!par->fb_virt)
goto err;

info->screen_base = (void __iomem *)par->fb_virt;
info->fbops = &lph88fb_ops;
info->var = lph88fb_var;
info->fix = lph88fb_fix;
info->fix.smem_len = MEM_LEN;
info->fix.smem_start = par->fb_phys;
info->screen_size = MEM_LEN;
info->flags = FBINFO_FLAG_DEFAULT;
info->pseudo_palette = par->pseudo_palette;

retval = fb_alloc_cmap(&(info->cmap), 256, 0);
if (retval < 0)
goto err1;

retval = register_framebuffer(info);
if (retval < 0)
goto err2;

dev_set_drvdata(&spi->dev, info);

m = &par->msg;
spi_message_init(m);
m->is_dma_mapped = 1;

x = &par->xfer1;
x->tx_buf = par->fb_virt + MEM_LEN;
x->tx_dma = par->fb_phys + MEM_LEN;
x->rx_buf = par->fb_virt + MEM_LEN + 1;
x->rx_dma = par->fb_phys + MEM_LEN + 1;
x->len = 1;
par->fb_virt[MEM_LEN] = 0x76;
spi_message_add_tail(x, m);

x = &par->xfer2;
x->tx_buf = par->fb_virt;
x->tx_dma = par->fb_phys;
x->rx_buf = par->fb_virt + MEM_LEN + 1;
x->rx_dma = par->fb_phys + MEM_LEN + 1;
x->len = MEM_LEN;
x->bits_per_word = 16;
spi_message_add_tail(x, m);

par->lph88fb_thread_task = kthread_run(lph88fb_thread, par, "lph88fb");
retval = -EIO;
if(IS_ERR(par->lph88fb_thread_task))
goto err3;

printk(KERN_INFO "fb%d: %s frame buffer device, %dK of video memory\n",
info->node, info->fix.id, info->fix.smem_len >> 10);

return 0;

err3:
unregister_framebuffer(info);
err2:
fb_dealloc_cmap(&info->cmap);
err1:
dma_free_coherent(NULL, (MEM_LEN + 1) << 1, par->fb_virt, par->fb_phys);
err:
framebuffer_release(info);

return retval;
}

static int __devexit lph88fb_remove(struct spi_device *spi)
{
struct fb_info *info = dev_get_drvdata(&spi->dev);

if (info) {
struct lph88fb_par *par = info->par;

kthread_stop(par->lph88fb_thread_task);
unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
dma_free_coherent(NULL, (MEM_LEN + 1) << 1, par->fb_virt, par->fb_phys);
framebuffer_release(info);
}
return 0;
}

/* Power down display on reboot, poweroff or halt */
static void lph88fb_shutdown(struct spi_device *spi)
{
at91_set_gpio_value(AT91_PIN_PB4, 0);
mdelay(1);
at91_set_gpio_value(AT91_PIN_PB4, 1);
mdelay(10);
}

static struct spi_driver lph88fb_driver = {
.driver = {
.name = "lph88fb",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = lph88fb_probe,
.remove = __devexit_p(lph88fb_remove),
.shutdown = lph88fb_shutdown,
};

static int __init lph88fb_init(void)
{
printk("lph88fb spi fb driver\n");
return spi_register_driver(&lph88fb_driver);
}

static void __exit lph88fb_exit(void)
{
spi_unregister_driver(&lph88fb_driver);
}

module_init(lph88fb_init);
module_exit(lph88fb_exit);

MODULE_AUTHOR("Alexander Kudjashev");
MODULE_DESCRIPTION("lph88 spi fb driver");
MODULE_LICENSE("GPL");

На ls020 можно сразу сделать spi->bits_per_word = 16; и не нужна поддержка вот этого x->bits_per_word = 16;
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 01.06.2009 14:01 Сообщение: 30
sasa
5

Регистрация: 20.05.2009
Начал писать новый драйвер без линуксового spi фреймворка - драйвер сам будет управлять spi. Собственно чего я так активировался :) - в промэлектронике есть lcd панелеи с тачскрином, 320х240 с контроллером работающим по spi, стоят от 500 руб. А это уже очень интересно :) Я посмотрел даташиты на контроллеры ихние - они практически один в один с моим lph88 - совсем небольшая разница. Если все оптимизировать - то будет вполне юзабельный экран да еще к тачскрину драйвер написать - вообще крастоа :) Теоретически скорости spi должно хватать, а без кривых атмеловских драйверов можно достич почти теории :)
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Embedded Linux