Ник:
Пароль:

Контакты

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

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

Ник:
Пароль:

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

ОбновитьПодробнееВсегоВсего:6
Форум » starterkit.ru » Embedded Linux
lcd siemens s65 & linux
rw9uao
Добавлено 01.06.2009 15:55 Сообщение: 31
rw9uao
Ранг
5

Группа: Клиенты
Пункты: 6973
Регистрация: 26.03.2009
Саш, я не туда смотрю? что-то дешевле $80-$100 не вижу. ткни ссылку. и заодно поболее разрешением.
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 01.06.2009 18:43 Сообщение: 32
sasa
5

Регистрация: 20.05.2009
http://www.promelec.ru/catalog/409/454/1750/0/
Правда такое ощущение что с моего последнего посещения там поменялось.. Например TFT MI0220PT правда он без тачскрина, TFT MI0240PT - с тачскрином но их нет в наличии.
Спуститься к концу Подняться к началу
Персональная информация
Lavin (Guest)
Добавлено 01.06.2009 19:27 Сообщение: 33
Lavin (Guest)

Если я правильно понял для lp020
spi->max_speed_hz = 12 * 1000 * 1000;
spi->bits_per_word = 16;//8
spi->mode = SPI_MODE_0;
и переписать инициализацию и команда\данные на GPIO повесить.
Драйвер можно потом будет с карточки подгрузить из консоли или его обязательно с ядром собирать?
Спуститься к концу Подняться к началу
sasa
Добавлено 01.06.2009 19:48 Редактировалось 01.06.2009 19:51 Сообщение: 34
sasa
5

Регистрация: 20.05.2009
Я в исходниках ядра все делаю, модуль компилится после изменений за считанные секунды, а spi привязан в файле board-... который в ядре, так что не вижу смысла выносить сборку из исходников ядра. Потом если модуль глючит - не думаю что его можно безболезненно выгрузить в режиме force а потом снова погрузить измененный. На деле если прошла probe и видно что lcd откликается на управление - то почти все сделано :)
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 02.06.2009 23:15 Редактировалось 02.06.2009 23:20 Сообщение: 35
sasa
5

Регистрация: 20.05.2009
Вот моя первая рабочая версия драйвера без линуксового фреймворка spi :) загрузка процессора от системы в среднем 0,5 % тогда как раньше один только драйвер съедал 10 %. Теперь не нужно драйвер прописывать в таблице spi. Я совсем отключил у себя поддержку spi в ядре, скорей всего можно будет включить но отключить драйверы которые прописаны в board-... на первом канале spi - оставить только нулевой канал (там у нас dataflash - так что фактически только она и будет работать :) При инициализации паросматривается таблица spi-slave устройств и инициализируются только те каналы на которых есть устройства. Пока есть обнаруженная проблема - не работает как подгружаемый модуль - что-то я не так с дма видимо делаю (ругается на dma_map), пока не знаю как это поправить и вообще что не так - вроде все как в других драйверах делал... Я пока что собираю статически, но если честно мне как модуль он и не нужен. #include "lph88.h" - это переименованный файл atmel_spi.h - не буду его сюда постить - он у всех есть в исходниках - просто скопируйте в директорию драйвера и переименуйте в lph88.h

Цитата
/*
* 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/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <mach/gpio.h>

#include "lph88.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)

#define SPI_SPEED (120000)

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

static u8 prefix[] = {0x74,0x00,0x21, 0x76,0x00,0x00, 0x74,0x00,0x22, 0x76};

struct transfer {
unsigned len;
dma_addr_t tx_dma;
unsigned cs_active:1;
u8 bits_per_word;
};

struct lph88fb_par {
struct platform_device *pdev;
struct clk *clk;
void __iomem *regs;
u8 *fb_virt;
dma_addr_t fb_phys;
dma_addr_t prefix_dma;
u32 pseudo_palette[16];
u32 csr;
struct transfer tr[5];
u8 index;
};

static struct fb_fix_screeninfo lph88fb_fix __initdata = {
.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 __initdata = {
.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 irqreturn_t
spi_interrupt(int irq, void *param)
{
struct lph88fb_par *par = (struct lph88fb_par *)param;
struct transfer *t;
u32 csr = par->csr;
u32 status, len;

spi_writel(par, IDR, SPI_BIT(TXBUFE) | SPI_BIT(ENDTX));
spi_writel(par, PTCR, SPI_BIT(TXTDIS));

status = spi_readl(par, SR);

par->index++;
if(par->index > 4)
par->index = 0;

t = &par->tr[par->index];

csr |= SPI_BF(BITS, t->bits_per_word - 8) | SPI_BF(CSAAT, t->cs_active);
spi_writel(par, CSR0, csr);

len = t->len;
if(t->bits_per_word > 8)
len >>= 1;

spi_writel(par, TPR, t->tx_dma);
spi_writel(par, TCR, len);

spi_writel(par, IER, SPI_BIT(TXBUFE) | SPI_BIT(ENDTX));
spi_writel(par, PTCR, SPI_BIT(TXTEN));

return IRQ_HANDLED;
}

static int __init spi_init(struct lph88fb_par *par)
{
unsigned long bus_hz;
u32 scbr;

/* Initialize the hardware */
at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI1_MISO */
at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI1_MOSI */
at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI1_SPCK */
at91_set_A_periph(AT91_PIN_PB3, 0); /* SPI1_NPCS0 */

spi_writel(par, CR, SPI_BIT(SWRST));
spi_writel(par, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
spi_writel(par, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS) | SPI_BF(PCS, 0x0e));
spi_writel(par, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
spi_writel(par, CR, SPI_BIT(SPIEN));

bus_hz = clk_get_rate(par->clk);
scbr = DIV_ROUND_UP(bus_hz, SPI_SPEED);

par->csr = SPI_BF(SCBR, scbr) | SPI_BIT(NCPHA);

spi_writel(par, CSR0, par->csr);

return 0;
}

static int __init spi_send_poll(struct lph88fb_par *par,
dma_addr_t buff, unsigned len)
{
u32 status;

spi_writel(par, PTCR, SPI_BIT(TXTDIS));
status = spi_readl(par, SR);

spi_writel(par, TPR, buff);
spi_writel(par, TCR, len);

spi_writel(par, PTCR, SPI_BIT(TXTEN));
while(!(spi_readl(par, SR) & (SPI_BIT(ENDTX) | SPI_BIT(TXBUFE))));

return 0;
}

static int __init lcd_init(struct lph88fb_par *par)
{
int i;
dma_addr_t tx_dma;

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

tx_dma = dma_map_single(NULL, (void *)&lcd_init_data[0],
sizeof(lcd_init_data), DMA_TO_DEVICE);

for(i = 0; i < sizeof(lcd_init_data); i += 3) {
spi_send_poll(par, tx_dma + i, 3);
mdelay(40);
}
dma_unmap_single(NULL, tx_dma, sizeof(lcd_init_data), DMA_TO_DEVICE);

return 0;
}

static int __init start_refresh(struct lph88fb_par *par)
{
struct transfer *t = par->tr;
int i;
u32 status;

spi_writel(par, PTCR, SPI_BIT(TXTDIS));
status = spi_readl(par, SR);

for(i = 0; i < 4; i++) {
t[i].tx_dma = par->prefix_dma + 3 * i;
t[i].bits_per_word = 8;
if(i == 3) {
t[i].len = 1;
t[i].cs_active = 1;
} else {
t[i].len = 3;
t[i].cs_active = 0;
}
}

t[i].tx_dma = par->fb_phys;
t[i].bits_per_word = 16;
t[i].len = MEM_LEN;
t[i].cs_active = 0;

par->index = 4;
spi_interrupt(AT91SAM9260_ID_SPI1, par);

return 0;
}

static int __init lph88fb_probe(struct platform_device *pdev)
{
struct lph88fb_par *par;
struct fb_info *info;
int retval;

retval = -ENOMEM;

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

par = info->par;
par->pdev = pdev;

par->clk = clk_get(NULL, "spi1_clk");
if (IS_ERR(par->clk))
goto err;

clk_enable(par->clk);

par->regs = ioremap(AT91SAM9260_BASE_SPI1, SZ_16K);
if (!par->regs)
goto err1;

spi_init(par);

lcd_init(par);

retval = request_irq(AT91SAM9260_ID_SPI1, spi_interrupt, 0,
pdev->name, par);
if (retval)
goto err2;

retval = -ENOMEM;

par->prefix_dma = dma_map_single(NULL, (void *)&prefix[0],
sizeof(prefix), DMA_TO_DEVICE);

if (dma_mapping_error(NULL, par->prefix_dma))
goto err3;

par->fb_virt = dma_alloc_coherent(NULL, PAGE_ALIGN(MEM_LEN),
&par->fb_phys, GFP_KERNEL);
if(!par->fb_virt)
goto err4;

/* Clear (turn to black) the framebuffer */
memset_io((void __iomem *)par->fb_virt, 0, MEM_LEN);

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 err5;

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

platform_set_drvdata(pdev, info);

start_refresh(par);

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;

err6:
fb_dealloc_cmap(&info->cmap);
err5:
dma_free_coherent(NULL, MEM_LEN, par->fb_virt, par->fb_phys);
err4:
dma_unmap_single(NULL, par->prefix_dma, sizeof(prefix), DMA_TO_DEVICE);
err3:
free_irq(AT91SAM9260_ID_SPI1, par);
err2:
iounmap(par->regs);
err1:
clk_disable(par->clk);
err:
framebuffer_release(info);

return retval;
}

static int lph88fb_remove(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);

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

unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
free_irq(AT91SAM9260_ID_SPI1, par);
dma_free_coherent(NULL, MEM_LEN, par->fb_virt, par->fb_phys);
dma_unmap_single(NULL, par->prefix_dma, sizeof(prefix), DMA_TO_DEVICE);
iounmap(par->regs);
clk_disable(par->clk);
framebuffer_release(info);
}
return 0;
}

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

static struct platform_driver lph88fb_driver = {
.probe = lph88fb_probe,
.remove = lph88fb_remove,
.shutdown = lph88fb_shutdown,
.driver = {
.name = "lph88fb",
},

};

static struct platform_device *lph88fb_device;

static int __init lph88fb_init(void)
{
int ret = 0;

ret = platform_driver_register(&lph88fb_driver);

if (!ret) {
lph88fb_device = platform_device_alloc("lph88fb", 0);

if (lph88fb_device)
ret = platform_device_add(lph88fb_device);
else
ret = -ENOMEM;

if (ret) {
platform_device_put(lph88fb_device);
platform_driver_unregister(&lph88fb_driver);
}
}

return ret;
}

static void __exit lph88fb_exit(void)
{
platform_device_unregister(lph88fb_device);
platform_driver_unregister(&lph88fb_driver);
}

module_init(lph88fb_init);
module_exit(lph88fb_exit);

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

Регистрация: 20.05.2009
Обновленная версия, решена проблема - теперь может работать и как подгружаемый модуль (обнаружился баг в ядре), немного поменял инициализацию - так стабильней стартует lcd.
Код
/*
* 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 lph88 lcd
*/

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

#include "atmel_spi.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)

#define SPI_SPEED (12*1000*1000)

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

static u8 prefix[] __initdata = {0x74,0x00,0x21, 0x76,0x00,0x00, 0x74,0x00,0x22, 0x76};

struct transfer {
unsigned len;
dma_addr_t tx_dma;
/* stay active after transfer */
unsigned cs_active:1;
u8 bits_per_word;
};

struct lph88fb_par {
struct clk *clk;
void __iomem *regs;
u8 *fb_virt;
dma_addr_t fb_phys;
u32 pseudo_palette[16];
u32 csr;
struct transfer tr[5];
u8 index;
};

static struct fb_fix_screeninfo lph88fb_fix __initdata = {
.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 __initdata = {
.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 irqreturn_t
spi_interrupt(int irq, void *param)
{
struct lph88fb_par *par = (struct lph88fb_par *)param;
struct transfer *t;
u32 csr = par->csr;
u32 status, len;

spi_writel(par, IDR, SPI_BIT(TXBUFE) | SPI_BIT(ENDTX));
spi_writel(par, PTCR, SPI_BIT(TXTDIS));

status = spi_readl(par, SR);

par->index++;
if(par->index > 4)
par->index = 0;

t = &par->tr[par->index];

csr |= SPI_BF(BITS, t->bits_per_word - 8) | SPI_BF(CSAAT, t->cs_active);
spi_writel(par, CSR0, csr);

len = t->len;
if(t->bits_per_word > 8)
len >>= 1;

spi_writel(par, TPR, t->tx_dma);
spi_writel(par, TCR, len);

spi_writel(par, IER, SPI_BIT(TXBUFE) | SPI_BIT(ENDTX));
spi_writel(par, PTCR, SPI_BIT(TXTEN));

return IRQ_HANDLED;
}

static int __init spi_init(struct lph88fb_par *par)
{
unsigned long bus_hz;
u32 scbr;

/* Initialize the hardware */
/* at91_set_A_periph(AT91_PIN_PB0, 0); SPI1_MISO */
at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI1_MOSI */
at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI1_SPCK */
at91_set_A_periph(AT91_PIN_PB3, 0); /* SPI1_NPCS0 */

spi_writel(par, CR, SPI_BIT(SWRST));
spi_writel(par, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
spi_writel(par, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS) | SPI_BF(PCS, 0x0e));
spi_writel(par, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
spi_writel(par, CR, SPI_BIT(SPIEN));

bus_hz = clk_get_rate(par->clk);
scbr = DIV_ROUND_UP(bus_hz, SPI_SPEED);

par->csr = SPI_BF(SCBR, scbr) | SPI_BIT(NCPHA);

spi_writel(par, CSR0, par->csr);

return 0;
}

static int __init spi_send_poll(struct lph88fb_par *par,
dma_addr_t buff, unsigned len)
{
u32 status;

spi_writel(par, PTCR, SPI_BIT(TXTDIS));
status = spi_readl(par, SR);

spi_writel(par, TPR, buff);
spi_writel(par, TCR, len);

spi_writel(par, PTCR, SPI_BIT(TXTEN));
while(!(spi_readl(par, SR) & (SPI_BIT(ENDTX) | SPI_BIT(TXBUFE))));

return 0;
}

static int __init lcd_init(struct lph88fb_par *par)
{
int i;
u8 *tx_buf = par->fb_virt;
dma_addr_t tx_dma = par->fb_phys;

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

memcpy(tx_buf, lcd_init_data, sizeof(lcd_init_data));

for(i = 0; i < sizeof(lcd_init_data); i += 3) {
spi_send_poll(par, tx_dma + i, 3);
mdelay(1);
if(tx_buf[i] == 0x76)
switch(tx_buf[i-1]) {
/* power control - need big delay */
case 0x03:
case 0x04:
case 0x0c:
case 0x0d:
case 0x0e:
mdelay(40);
}
}

mdelay(100);

return 0;
}

static int __init start_refresh(struct lph88fb_par *par)
{
struct transfer *t = par->tr;
dma_addr_t prefix_dma = par->fb_phys + MEM_LEN;
int i;

memcpy(par->fb_virt + MEM_LEN, prefix, sizeof(prefix));

for(i = 0; i < 4; i++) {
t[i].tx_dma = prefix_dma + 3 * i;
t[i].bits_per_word = 8;
if(i == 3) {
t[i].len = 1;
t[i].cs_active = 1;
} else {
t[i].len = 3;
t[i].cs_active = 0;
}
}

t[i].tx_dma = par->fb_phys;
t[i].bits_per_word = 16;
t[i].len = MEM_LEN;
t[i].cs_active = 0;

par->index = 4;
spi_interrupt(AT91SAM9260_ID_SPI1, par);

return 0;
}

static int __init lph88fb_probe(struct platform_device *pdev)
{
struct lph88fb_par *par;
struct fb_info *info;
int retval;

retval = -ENOMEM;

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

par = info->par;

par->clk = clk_get(NULL, "spi1_clk");
if (IS_ERR(par->clk))
goto err;

clk_enable(par->clk);

par->regs = ioremap(AT91SAM9260_BASE_SPI1, SZ_16K);
if (!par->regs)
goto err1;

retval = request_irq(AT91SAM9260_ID_SPI1, spi_interrupt, 0,
pdev->name, par);
if (retval)
goto err2;

retval = -ENOMEM;

par->fb_virt = dma_alloc_coherent(NULL, MEM_LEN + sizeof(prefix),
&par->fb_phys, GFP_KERNEL);
if(!par->fb_virt)
goto err3;

spi_init(par);
lcd_init(par);

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 err4;

memset(par->fb_virt, 0, MEM_LEN);

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

platform_set_drvdata(pdev, info);

start_refresh(par);

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:
fb_dealloc_cmap(&info->cmap);
err4:
dma_free_coherent(NULL, MEM_LEN + sizeof(prefix), par->fb_virt, par->fb_phys);
err3:
free_irq(AT91SAM9260_ID_SPI1, par);
err2:
iounmap(par->regs);
err1:
clk_disable(par->clk);
err:
framebuffer_release(info);

return retval;
}

static int lph88fb_remove(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);

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

unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
free_irq(AT91SAM9260_ID_SPI1, par);
clk_disable(par->clk);
dma_free_coherent(NULL, MEM_LEN + sizeof(prefix),
par->fb_virt, par->fb_phys);
iounmap(par->regs);
framebuffer_release(info);
}
return 0;
}

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

static struct platform_driver lph88fb_driver = {
.probe = lph88fb_probe,
.remove = lph88fb_remove,
.shutdown = lph88fb_shutdown,
.driver = {
.name = "lph88fb",
},

};

static struct platform_device *lph88fb_device;

static int __init lph88fb_init(void)
{
int ret = 0;

ret = platform_driver_register(&lph88fb_driver);

if (!ret) {
lph88fb_device = platform_device_alloc("lph88fb", 0);

if (lph88fb_device)
ret = platform_device_add(lph88fb_device);
else
ret = -ENOMEM;

if (ret) {
platform_device_put(lph88fb_device);
platform_driver_unregister(&lph88fb_driver);
}
}

return ret;
}

static void __exit lph88fb_exit(void)
{
platform_device_unregister(lph88fb_device);
platform_driver_unregister(&lph88fb_driver);
}

module_init(lph88fb_init);
module_exit(lph88fb_exit);

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

Регистрация: 20.05.2009
С последним драйвером попробовал mplayer - работает :) Пререкодировал видео c lavc в mpeg4 176х132 битрэйт 256 для видео и 96 для звука и тут странное дело - с опцией -nosound все летает, процессор загружен на динамичных сценах максимум на 40 % а в среднем 20-30 %, запускаю со звуком и сразу тормоза. Система загружена под завязку. Неужели декодирование mp3 потока так съедает процессор ? что-то мне не верится... madplay всего процентов 20 съедал - а тут все 60% и mplayer пишет что система слишком слаба для запуска этого ролика... Но в общем новый драйвер ведет себя отлично :) Я даже не ожидал что можно будет смотреть avi в mpeg4. К сожалению я сейчас на gprs - не смогу выложить видео, будет возможность - выложу. Да и звуком сейчас не могу насладться - аудиокодек не распаян пока что на новом переходнике, данные летят в пустоту :)
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 08.06.2009 13:03 Сообщение: 38
sasa
5

Регистрация: 20.05.2009
Какая-то ерунда - mplayer на воспроизведении звука съедает весь процессор... Для эксперимента взял обычный mp3 файл, madplay съедает 20-30 % а mplayer на том же файле грузит процессор под завязку - 100%.
Спуститься к концу Подняться к началу
Персональная информация
sasa
Добавлено 08.06.2009 15:27 Сообщение: 39
sasa
5

Регистрация: 20.05.2009
http://www.sasamy.narod.ru/8.avi

заснял видео немнога
Спуститься к концу Подняться к началу
Персональная информация
rw9uao
Добавлено 08.06.2009 16:00 Сообщение: 40
rw9uao
Ранг
5

Группа: Клиенты
Пункты: 6973
Регистрация: 26.03.2009
ай молодца!
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Embedded Linux