/*s3c2440_ov9650.c*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/semaphore.h>
#include <mach/regs-gpio.h>
#include "sccb.h"
#include "s3c2440camif.h"
#define OV9650_SCCB_ADDR 0x60
#define OV9650_MANUFACT_ID 0x7FA2
#define OV9650_PRODUCT_ID 0x9650
/*
09032004
OV9650
VGA YUV
15fps when 24MHz input clock
Device Address(Hex)/Register(Hex)/Value(Hex)
*/
static struct ov9650_reg
{
u8 subaddr;
u8 value;
}regs[] = {
{0x12, 0x80},
{0x11, 0x81},
{0x6b, 0x0a},
{0x6a, 0x3e},
{0x3b, 0x09},
{0x13, 0xe0},
{0x01, 0x80},
{0x02, 0x80},
{0x00, 0x00},
{0x10, 0x00},
{0x13, 0xe5},
/*{0x39, 0x50},*/ /*30 fps*/
{0x39, 0x43}, /*15fps*/
/*{0x38, 0x92},*/ /*30fps*/
{0x38, 0x12}, /*15fps*/
{0x37, 0x00},
/*{0x35, 0x81},*/ /*30 fps*/
{0x35, 0x91}, /*15 fps*/
{0x0e, 0x20},
{0x1e, 0x04},
{0xa8, 0x80},
{0x12, 0x40},
{0x04, 0x00},
{0x0c, 0x04},
{0x0d, 0x80},
{0x18, 0xc6},
{0x17, 0x26},
{0x32, 0xad},
{0x03, 0x00},
{0x1a, 0x3d},
{0x19, 0x01},
{0x3f, 0xa6},
{0x14, 0x2e},
{0x15, 0x02},
{0x41, 0x02},
{0x42, 0x08},
{0x1b, 0x00},
{0x16, 0x06},
{0x33, 0xe2}, /*c0 for internal regulator*/
{0x34, 0xbf},
{0x96, 0x04},
{0x3a, 0x00},
{0x8e, 0x00},
{0x3c, 0x77},
{0x8B, 0x06},
{0x94, 0x88},
{0x95, 0x88},
{0x40, 0xc1},
{0x29, 0x3f}, /*2f for internal regulator*/
{0x0f, 0x42},
{0x3d, 0x92},
{0x69, 0x40},
{0x5c, 0xb9},
{0x5d, 0x96},
{0x5e, 0x10},
{0x59, 0xc0},
{0x5a, 0xaf},
{0x5b, 0x55},
{0x43, 0xf0},
{0x44, 0x10},
{0x45, 0x68},
{0x46, 0x96},
{0x47, 0x60},
{0x48, 0x80},
{0x5f, 0xe0},
{0x60, 0x8c}, /*0c for advanced AWB (related to lens)*/
{0x61, 0x20},
{0xa5, 0xd9},
{0xa4, 0x74},
{0x8d, 0x02},
{0x13, 0xe7},
{0x4f, 0x3a},
{0x50, 0x3d},
{0x51, 0x03},
{0x52, 0x12},
{0x53, 0x26},
{0x54, 0x38},
{0x55, 0x40},
{0x56, 0x40},
{0x57, 0x40},
{0x58, 0x0d},
{0x8C, 0x23},
{0x3e, 0x02},
{0xa9, 0xb8},
{0xaa, 0x92},
{0xab, 0x0a},
{0x8f, 0xdf},
{0x90, 0x00},
{0x91, 0x00},
{0x9f, 0x00},
{0xa0, 0x00},
{0x3a, 0x0d}, /*UYVY, Digital BLC enable*/
{0x24, 0x70},
{0x25, 0x64},
{0x26, 0xc3},
{0x2a, 0x00}, /*10 for 50Hz*/
{0x2b, 0x00}, /*40 for 50Hz*/
{0x6c, 0x40},
{0x6d, 0x30},
{0x6e, 0x4b},
{0x6f, 0x60},
{0x70, 0x70},
{0x71, 0x70},
{0x72, 0x70},
{0x73, 0x70},
{0x74, 0x60},
{0x75, 0x60},
{0x76, 0x50},
{0x77, 0x48},
{0x78, 0x3a},
{0x79, 0x2e},
{0x7a, 0x28},
{0x7b, 0x22},
{0x7c, 0x04},
{0x7d, 0x07},
{0x7e, 0x10},
{0x7f, 0x28},
{0x80, 0x36},
{0x81, 0x44},
{0x82, 0x52},
{0x83, 0x60},
{0x84, 0x6c},
{0x85, 0x78},
{0x86, 0x8c},
{0x87, 0x9e},
{0x88, 0xbb},
{0x89, 0xd2},
{0x8a, 0xe6}
};
#if 0
static struct ov9650_reg
{
u8 subaddr;
u8 value;
}regs[] = {
/* OV9650 intialization parameter table for SXGA application */
{0x12, 0x80}, {0x39, 0x43}, {0x38, 0x12}, {0x37, 0x00}, {0x0e, 0x20},
{0x1e, 0x0c}, {0x01, 0x80}, {0x02, 0x80}, {0x00, 0x00}, {0x10, 0xf0},
{0x04, 0x00}, {0x0c, 0x00}, {0x0d, 0x00}, {0x11, 0x80}, {0x12, 0x40},
{0x14, 0x2e}, {0x15, 0x00}, {0x18, 0xbd}, {0x17, 0x1d}, {0x32, 0xbf},
{0x03, 0x12}, {0x1a, 0x81}, {0x19, 0x01}, {0x3f, 0xa6}, {0x41, 0x02},
{0x42, 0x08}, {0x1b, 0x00}, {0x16, 0x06}, {0x33, 0xc0}, {0x34, 0xbf},
{0xa8, 0x80}, {0x96, 0x04}, {0x3a, 0x00}, {0x8e, 0x00}, {0x3c, 0x77},
{0x8b, 0x06}, {0x35, 0x91}, {0x94, 0x88}, {0x95, 0x88}, {0x40, 0xc1},
{0x29, 0x3f}, {0x0f, 0x42}, {0x13, 0xe5}, {0x3d, 0x92}, {0x69, 0x80},
{0x5c, 0x96}, {0x5d, 0x96}, {0x5e, 0x10}, {0x59, 0xeb}, {0x5a, 0x9c},
{0x5b, 0x55}, {0x43, 0xf0}, {0x44, 0x10}, {0x45, 0x55}, {0x46, 0x86},
{0x47, 0x64}, {0x48, 0x86}, {0x5f, 0xe0}, {0x60, 0x8c}, {0x61, 0x20},
{0xa5, 0xd9}, {0xa4, 0x74}, {0x8d, 0x02}, {0x13, 0xe7}, {0x4f, 0x3a},
{0x50, 0x3d}, {0x51, 0x03}, {0x52, 0x12}, {0x53, 0x26}, {0x54, 0x38},
{0x55, 0x40}, {0x56, 0x40}, {0x57, 0x40}, {0x58, 0x0d}, {0x8c, 0x23},
{0x3e, 0x02}, {0xa9, 0xb8}, {0xaa, 0x92}, {0xab, 0x0a}, {0x8f, 0xdf},
{0x90, 0x00}, {0x91, 0x00}, {0x9f, 0x00}, {0x3a, 0x0c}, {0x24, 0x70},
{0x25, 0x64}, {0x26, 0xc3}, {0x2a, 0x12}, {0x2b, 0x46}, {0x3b, 0x19},
{0x6c, 0x40}, {0x6d, 0x30}, {0x6e, 0x4b}, {0x6f, 0x60},
{0x70, 0x70}, {0x71, 0x70}, {0x72, 0x70}, {0x73, 0x70},
{0x74, 0x60}, {0x75, 0x60}, {0x76, 0x50}, {0x77, 0x48},
{0x78, 0x3a}, {0x79, 0x2e}, {0x7a, 0x28}, {0x7b, 0x22},
{0x7c, 0x04}, {0x7d, 0x07}, {0x7e, 0x10}, {0x7f, 0x28},
{0x80, 0x36}, {0x81, 0x44}, {0x82, 0x52}, {0x83, 0x60},
{0x84, 0x6c}, {0x85, 0x78}, {0x86, 0x8c}, {0x87, 0x9e},
{0x88, 0xbb}, {0x89, 0xd2}, {0x8a, 0xe6},
{0x6a, 0x41}, {0x66, 0x00},
{0x3e, 0x00}, {0x3f, 0xa4}
};
#endif
DECLARE_MUTEX(regs_mutex);
static void __inline__ ov9650_poweron(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_OUTP);
s3c2410_gpio_setpin(S3C2410_GPG12, 0);
mdelay(20);
}
static void __inline__ ov9650_poweroff(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_OUTP);
s3c2410_gpio_setpin(S3C2410_GPG12, 1);
mdelay(20);
}
static int __inline__ ov9650_check(void)
{
u32 mid;
mid = sccb_read(OV9650_SCCB_ADDR, 0x1c)<<8;
mid |= sccb_read(OV9650_SCCB_ADDR, 0x1d);
printk("SCCB address 0x%02X, manufacture ID 0x%04X, expect 0x%04X\n", OV9650_SCCB_ADDR, mid, OV9650_MANUFACT_ID);
return (mid==OV9650_MANUFACT_ID)?1:0;
}
static u32 __inline__ show_ov9650_product_id(void)
{
u32 pid;
pid = sccb_read(OV9650_SCCB_ADDR, 0x0a)<<8;
pid |= sccb_read(OV9650_SCCB_ADDR, 0x0b);
printk("SCCB address 0x%02X, product ID 0x%04X, expect 0x%04X\n", OV9650_SCCB_ADDR, pid, OV9650_PRODUCT_ID);
return pid;
}
static void ov9650_init_regs(void)
{
int i;
down(®s_mutex);
for (i=0; i<ARRAY_SIZE(regs); i++)
{
if (regs[i].subaddr == 0xff)
{
mdelay(regs[i].value);
continue;
}
sccb_write(OV9650_SCCB_ADDR, regs[i].subaddr, regs[i].value);
}
up(®s_mutex);
}
int s3c2440_ov9650_init(void)
{
printk(KERN_ALERT"Loading OV9650 driver.........\n");
/* power on. */
ov9650_poweron();
mdelay(100);
/* check device. */
if (ov9650_check() == 0 && ov9650_check() == 0)
{
printk(KERN_ERR"No OV9650 found!!!\n");
return -ENODEV;
}
show_ov9650_product_id();
ov9650_init_regs();
printk("ov9650 init done!\n");
return 0;
}
#if 0
module_init(ov9650_init);
module_exit(ov9650_cleanup);
MODULE_LICENSE("GPL");
#endif
/*s3c2440camif.h*/
#ifndef __S3C2440CAMIF_H__
#define __S3C2440CAMIF_H__
#define MIN_C_WIDTH 32
#define MAX_C_WIDTH 320
#define MIN_C_HEIGHT 48
#define MAX_C_HEIGHT 240
#define MIN_P_WIDTH 32
#define MAX_P_WIDTH 640
#define MIN_P_HEIGHT 48
#define MAX_P_HEIGHT 480
enum
{
CAMIF_BUFF_INVALID = 0,
CAMIF_BUFF_RGB565 = 1,
CAMIF_BUFF_RGB24 = 2,
CAMIF_BUFF_YCbCr420 = 3,
CAMIF_BUFF_YCbCr422 = 4
};
/* image buffer for s3c2440 camif. */
struct s3c2440camif_buffer
{
int state;
ssize_t img_size;
struct device *dev;
unsigned int order;
unsigned long virt_base;
unsigned long phy_base;
unsigned long offset;
};
/* for s3c2440camif_dev->state field. */
enum
{
CAMIF_STATE_FREE = 0, // not openned
CAMIF_STATE_READY = 1, // openned, but standby
CAMIF_STATE_PREVIEWING = 2, // in previewing
CAMIF_STATE_CODECING = 3 // in capturing
};
/* for s3c2440camif_dev->cmdcode field. */
enum
{
CAMIF_CMD_NONE = 0,
CAMIF_CMD_SFMT = 1<<0, // source image format changed.
CAMIF_CMD_WND = 1<<1, // window offset changed.
CAMIF_CMD_ZOOM = 1<<2, // zoom picture in/out
CAMIF_CMD_TFMT = 1<<3, // target image format changed.
CAMIF_CMD_P2C = 1<<4, // need camif switches from p-path to c-path
CAMIF_CMD_C2P = 1<<5, // neet camif switches from c-path to p-path
CAMIF_CMD_REGS = 1<<6, // Update regs
CAMIF_CMD_START = 1<<15, // stop capture
CAMIF_CMD_STOP = 1<<16 // stop capture
};
enum
{
CAMIF_PATH_NONE = 0,
CAMIF_PATH_PREVIEW = 1<<0,
CAMIF_PATH_CODEC = 1<<1
};
/* main s3c2440 camif structure. */
struct s3c2440camif_dev
{
/* hardware clock. */
struct clk * clk;
/* source(input) image size. */
int srcHsize;
int srcVsize;
/* windowed image size. */
int wndHsize;
int wndVsize;
/* codec-path target(output) image size. */
int coTargetHsize;
int coTargetVsize;
/* preview-path target(preview) image size. */
int preTargetHsize;
int preTargetVsize;
/* the camera interface state. */
int state; // CMAIF_STATE_FREE, CAMIF_STATE_PREVIEWING, CAMIF_STATE_CAPTURING.
/* for executing camif commands. */
int cmdcode; // command code, CAMIF_CMD_START, CAMIF_CMD_CFG, etc.
wait_queue_head_t wait; // wait queue for waiting untile command completed (if in preview or in capturing).
/* For V4L2 data */
__u32 pixelformat;
int path; /*output path*/
spinlock_t lock;
int open_count;
int frame; /*frame index*/
int rdy;
};
#if 0
/* opened file handle.*/
struct s3c2440camif_fh
{
/* the camif */
struct s3c2440camif_dev * dev;
/* master flag, only master openner could execute 'set' ioctls. */
int master;
};
#endif
struct s3c2440camif_res
{
int width;
int height;
};
#define S3C244X_CAMIFREG(x) ((x) + camif_base_addr)
/* CAMIF control registers */
#define S3C244X_CISRCFMT S3C244X_CAMIFREG(0x00)
#define S3C244X_CIWDOFST S3C244X_CAMIFREG(0x04)
#define S3C244X_CIGCTRL S3C244X_CAMIFREG(0x08)
#define S3C244X_CICOYSA1 S3C244X_CAMIFREG(0x18)
#define S3C244X_CICOYSA2 S3C244X_CAMIFREG(0x1C)
#define S3C244X_CICOYSA3 S3C244X_CAMIFREG(0x20)
#define S3C244X_CICOYSA4 S3C244X_CAMIFREG(0x24)
#define S3C244X_CICOCBSA1 S3C244X_CAMIFREG(0x28)
#define S3C244X_CICOCBSA2 S3C244X_CAMIFREG(0x2C)
#define S3C244X_CICOCBSA3 S3C244X_CAMIFREG(0x30)
#define S3C244X_CICOCBSA4 S3C244X_CAMIFREG(0x34)
#define S3C244X_CICOCRSA1 S3C244X_CAMIFREG(0x38)
#define S3C244X_CICOCRSA2 S3C244X_CAMIFREG(0x3C)
#define S3C244X_CICOCRSA3 S3C244X_CAMIFREG(0x40)
#define S3C244X_CICOCRSA4 S3C244X_CAMIFREG(0x44)
#define S3C244X_CICOTRGFMT S3C244X_CAMIFREG(0x48)
#define S3C244X_CICOCTRL S3C244X_CAMIFREG(0x4C)
#define S3C244X_CICOSCPRERATIO S3C244X_CAMIFREG(0x50)
#define S3C244X_CICOSCPREDST S3C244X_CAMIFREG(0x54)
#define S3C244X_CICOSCCTRL S3C244X_CAMIFREG(0x58)
#define S3C244X_CICOTAREA S3C244X_CAMIFREG(0x5C)
#define S3C244X_CICOSTATUS S3C244X_CAMIFREG(0x64)
#define S3C244X_CIPRCLRSA1 S3C244X_CAMIFREG(0x6C)
#define S3C244X_CIPRCLRSA2 S3C244X_CAMIFREG(0x70)
#define S3C244X_CIPRCLRSA3 S3C244X_CAMIFREG(0x74)
#define S3C244X_CIPRCLRSA4 S3C244X_CAMIFREG(0x78)
#define S3C244X_CIPRTRGFMT S3C244X_CAMIFREG(0x7C)
#define S3C244X_CIPRCTRL S3C244X_CAMIFREG(0x80)
#define S3C244X_CIPRSCPRERATIO S3C244X_CAMIFREG(0x84)
#define S3C244X_CIPRSCPREDST S3C244X_CAMIFREG(0x88)
#define S3C244X_CIPRSCCTRL S3C244X_CAMIFREG(0x8C)
#define S3C244X_CIPRTAREA S3C244X_CAMIFREG(0x90)
#define S3C244X_CIPRSTATUS S3C244X_CAMIFREG(0x98)
#define S3C244X_CIIMGCPT S3C244X_CAMIFREG(0xA0)
#define S3C244X_CICOSTAY(i) S3C244X_CAMIFREG((0x18+(i)*4))
#define S3C244X_CICOSTACb(i) S3C244X_CAMIFREG((0x28+(i)*4))
#define S3C244X_CICOSTACr(i) S3C244X_CAMIFREG((0x38+(i)*4))
#define S3C244X_CIPRSTARGB(i) S3C244X_CAMIFREG((0x6C+(i)*4))
#endif
/*s3c2440camif.c*/
/*
* Video for Linux 2 - Camera interface on S3C2440
*
* Copyright (C) 2009
*
* 2009/06/19 :
* ported by Steve Chang
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef CONFIG_VIDEO_V4L1_COMPAT
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "s3c2440camif.h"
/* debug print macro. */
/* hardware & driver name, version etc. */
#define CARD_NAME "camera"
static unsigned has_ov9650;
unsigned long camif_base_addr;
#if 1
int __init sccb_init(void);
void __exit sccb_cleanup(void);
int __init s3c2440_ov9650_init(void);
void __exit s3c2440_ov9650_cleanup(void);
#endif
/* camera device(s) */
static struct s3c2440camif_dev camera;
/* image buffer for previewing. */
struct s3c2440camif_buffer img_buff[] =
{
{
.state = CAMIF_BUFF_INVALID,
.img_size = 0,
.order = 0,
.virt_base = (unsigned long)NULL,
.phy_base = (unsigned long)NULL,
.offset = 0
},
{
.state = CAMIF_BUFF_INVALID,
.img_size = 0,
.order = 0,
.virt_base = (unsigned long)NULL,
.phy_base = (unsigned long)NULL,
.offset = 0
},
{
.state = CAMIF_BUFF_INVALID,
.img_size = 0,
.order = 0,
.virt_base = (unsigned long)NULL,
.phy_base = (unsigned long)NULL,
.offset = 0
},
{
.state = CAMIF_BUFF_INVALID,
.img_size = 0,
.order = 0,
.virt_base = (unsigned long)NULL,
.phy_base = (unsigned long)NULL,
.offset = 0
}
};
/* software reset camera interface. */
static void __inline__ soft_reset_camif(void)
{
u32 cigctrl;
u32 cisrcfmt;
cisrcfmt = ioread32(S3C244X_CISRCFMT);
cisrcfmt |= (1<<31); // ITU-R BT.601 YCbCr 8-bit mode
iowrite32(cisrcfmt, S3C244X_CISRCFMT); /*Recommand by datasheet p.532*/
cigctrl = (1<<31)|(1<<29);
iowrite32(cigctrl, S3C244X_CIGCTRL);
mdelay(10);
cigctrl = (1<<29);
iowrite32(cigctrl, S3C244X_CIGCTRL);
mdelay(10);
}
/* software reset camera interface. */
static void __inline__ hw_reset_camif(void)
{
u32 cigctrl;
cigctrl = (1<<30)|(1<<29);
iowrite32(cigctrl, S3C244X_CIGCTRL);
mdelay(10);
cigctrl = (1<<29);
iowrite32(cigctrl, S3C244X_CIGCTRL);
mdelay(10);
}
/* switch camif from codec path to preview path. */
static void __inline__ camif_c2p(struct s3c2440camif_dev * pdev)
{
/* 1. stop codec. */
{
u32 cicoscctrl;
cicoscctrl = ioread32(S3C244X_CICOSCCTRL);
cicoscctrl &= ~(1<<15); // stop codec scaler.
iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);
}
/* 2. soft-reset camif. */
soft_reset_camif();
/* 3. clear all overflow. */
{
u32 ciwdofst;
ciwdofst = ioread32(S3C244X_CIWDOFST);
ciwdofst |= (1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12);
iowrite32(ciwdofst, S3C244X_CIWDOFST);
ciwdofst &= ~((1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12));
iowrite32(ciwdofst, S3C244X_CIWDOFST);
}
pdev->path = CAMIF_PATH_PREVIEW;
}
/* switch camif from codec path to preview path. */
static void __inline__ camif_p2c(struct s3c2440camif_dev * pdev)
{
/* 1. stop preview. */
{
u32 ciprscctrl;
ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);
ciprscctrl &= ~(1<<15); // stop preview scaler.
iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);
}
/* 2. soft-reset camif. */
soft_reset_camif();
/* 3. clear all overflow. */
{
u32 ciwdofst;
ciwdofst = ioread32(S3C244X_CIWDOFST);
ciwdofst |= (1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12);
iowrite32(ciwdofst, S3C244X_CIWDOFST);
ciwdofst &= ~((1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12));
iowrite32(ciwdofst, S3C244X_CIWDOFST);
}
pdev->path = CAMIF_PATH_CODEC;
}
/* calculate main burst size and remained burst size. */
static void __inline__ calc_burst_size(u32 pixperword,u32 hSize, u32 *mainBurstSize, u32 *remainedBurstSize)
{
u32 tmp;
tmp = (hSize/pixperword)%16;
switch(tmp)
{
case 0:
*mainBurstSize = 16;
*remainedBurstSize = 16;
break;
case 4:
*mainBurstSize = 16;
*remainedBurstSize = 4;
break;
case 8:
*mainBurstSize=16;
*remainedBurstSize = 8;
break;
default:
tmp=(hSize/pixperword)%8;
switch(tmp)
{
case 0:
*mainBurstSize = 8;
*remainedBurstSize = 8;
break;
case 4:
*mainBurstSize = 8;
*remainedBurstSize = 4;
default:
*mainBurstSize = 4;
tmp = (hSize/pixperword)%4;
*remainedBurstSize = (tmp)?tmp:4;
break;
}
break;
}
}
/* calculate prescaler ratio and shift. */
static void __inline__ calc_prescaler_ratio_shift(u32 SrcSize, u32 DstSize, u32 *ratio, u32 *shift)
{
if(SrcSize>=32*DstSize)
{
*ratio=32;
*shift=5;
}
else if(SrcSize>=16*DstSize)
{
*ratio=16;
*shift=4;
}
else if(SrcSize>=8*DstSize)
{
*ratio=8;
*shift=3;
}
else if(SrcSize>=4*DstSize)
{
*ratio=4;
*shift=2;
}
else if(SrcSize>=2*DstSize)
{
*ratio=2;
*shift=1;
}
else
{
*ratio=1;
*shift=0;
}
}
/* update CISRCFMT only. */
static void __inline__ update_source_fmt_regs(struct s3c2440camif_dev *pdev)
{
u32 cisrcfmt;
cisrcfmt = (1<<31) // ITU-R BT.601 YCbCr 8-bit mode
|(0<<30) // CB,Cr value offset cntrol for YCbCr
|(pdev->srcHsize<<16) // source image width
// |(0<<14) // input order is YCbYCr
// |(1<<14) // input order is YCrYCb
|(2<<14) // input order is CbYCrY
// |(3<<14) // input order is CrYCbY
|(pdev->srcVsize<<0); // source image height
iowrite32(cisrcfmt, S3C244X_CISRCFMT);
}
/* update registers:
* PREVIEW path:
* CIPRCLRSA1 ~ CIPRCLRSA4
* CIPRTRGFMT
* CIPRCTRL
* CIPRSCCTRL
* CIPRTAREA
* CODEC path:
* CICOYSA1 ~ CICOYSA4
* CICOCBSA1 ~ CICOCBSA4
* CICOCRSA1 ~ CICOCRSA4
* CICOTRGFMT
* CICOCTRL
* CICOTAREA
*/
static void __inline__ update_target_fmt_regs(struct s3c2440camif_dev * pdev)
{
u32 ciprtrgfmt, cicotrgfmt = 0;
u32 ciprctrl, cicoctrl;
u32 ciprscctrl, cicoscctrl;
u32 mainBurstSize, remainedBurstSize;
switch(pdev->path) {
case CAMIF_PATH_PREVIEW:
/* CIPRCLRSA1 ~ CIPRCLRSA4. */
iowrite32(img_buff[0].phy_base, S3C244X_CIPRCLRSA1);
iowrite32(img_buff[1].phy_base, S3C244X_CIPRCLRSA2);
iowrite32(img_buff[2].phy_base, S3C244X_CIPRCLRSA3);
iowrite32(img_buff[3].phy_base, S3C244X_CIPRCLRSA4);
/* CIPRTRGFMT. */
ciprtrgfmt = (pdev->preTargetHsize<<16) // horizontal pixel number of target image
|(0<<14) // don't mirror or rotation.
|(pdev->preTargetVsize<<0); // vertical pixel number of target image
iowrite32(ciprtrgfmt, S3C244X_CIPRTRGFMT);
/* CIPRCTRL. */
calc_burst_size(2, pdev->preTargetHsize, &mainBurstSize, &remainedBurstSize);
ciprctrl = (mainBurstSize<<19)|(remainedBurstSize<<14);
iowrite32(ciprctrl, S3C244X_CIPRCTRL);
/* CIPRSCCTRL. */
ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);
ciprscctrl &= 1<<15; // clear all other info except 'preview scaler start'.
ciprscctrl |= 0<<30; // 16-bits RGB
iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL); // 16-bit RGB
/* CIPRTAREA. */
iowrite32(pdev->preTargetHsize * pdev->preTargetVsize, S3C244X_CIPRTAREA);
break;
case CAMIF_PATH_CODEC:
/* CICOYSA1 ~ CICOYSA4. */
iowrite32(img_buff[0].phy_base, S3C244X_CICOYSA1);
iowrite32(img_buff[1].phy_base, S3C244X_CICOYSA2);
iowrite32(img_buff[2].phy_base, S3C244X_CICOYSA3);
iowrite32(img_buff[3].phy_base, S3C244X_CICOYSA4);
/* CICOCBSA1 ~ CICOCBSA4. */
iowrite32(img_buff[0].phy_base + (pdev->coTargetHsize * pdev->coTargetVsize), S3C244X_CICOCBSA1);
iowrite32(img_buff[1].phy_base + (pdev->coTargetHsize * pdev->coTargetVsize), S3C244X_CICOCBSA2);
iowrite32(img_buff[2].phy_base + (pdev->coTargetHsize * pdev->coTargetVsize), S3C244X_CICOCBSA3);
iowrite32(img_buff[3].phy_base + (pdev->coTargetHsize * pdev->coTargetVsize), S3C244X_CICOCBSA4);
switch(pdev->pixelformat) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YUV422P:
/* CICOCRSA1 ~ CICOCRSA4. */
iowrite32(img_buff[0].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 3 / 2), S3C244X_CICOCRSA1);
iowrite32(img_buff[1].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 3 / 2), S3C244X_CICOCRSA2);
iowrite32(img_buff[2].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 3 / 2), S3C244X_CICOCRSA3);
iowrite32(img_buff[3].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 3 / 2), S3C244X_CICOCRSA4);
cicotrgfmt = (1<<31)|(1<<30); /**/
break;
case V4L2_PIX_FMT_YUV420:
/* CICOCRSA1 ~ CICOCRSA4. */
iowrite32(img_buff[0].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 5 / 4), S3C244X_CICOCRSA1);
iowrite32(img_buff[1].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 5 / 4), S3C244X_CICOCRSA2);
iowrite32(img_buff[2].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 5 / 4), S3C244X_CICOCRSA3);
iowrite32(img_buff[3].phy_base + ((pdev->coTargetHsize * pdev->coTargetVsize) * 5 / 4), S3C244X_CICOCRSA4);
cicotrgfmt = (1<<31); /**/
break;
}
/* CICOTRGFMT. */
cicotrgfmt |= (pdev->coTargetHsize<<16) // horizontal pixel number of target image
|(0<<14) // don't mirror or rotation.
|(pdev->coTargetVsize<<0); // vertical pixel number of target image
iowrite32(cicotrgfmt, S3C244X_CICOTRGFMT);
/* CICOCTRL. */
calc_burst_size(1, pdev->coTargetHsize, &mainBurstSize, &remainedBurstSize); /*y frame*/
cicoctrl = (mainBurstSize<<19)|(remainedBurstSize<<14);
calc_burst_size(1, (pdev->coTargetHsize / 2), &mainBurstSize, &remainedBurstSize); /*CbCr frame*/
cicoctrl |= (mainBurstSize<<9)|(remainedBurstSize<<4);
iowrite32(cicoctrl, S3C244X_CICOCTRL);
/* CICOSCCTRL. */
cicoscctrl = ioread32(S3C244X_CICOSCCTRL);
cicoscctrl &= 1<<15; // clear all other info except 'codec scaler start'.
iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);
/* CICOTAREA. */
iowrite32(pdev->coTargetHsize * pdev->coTargetVsize, S3C244X_CICOTAREA);
break;
}
}
/* update CIWDOFST only. */
static void __inline__ update_target_wnd_regs(struct s3c2440camif_dev * pdev)
{
u32 ciwdofst;
u32 winHorOfst, winVerOfst;
winHorOfst = (pdev->srcHsize - pdev->wndHsize)>>1;
winVerOfst = (pdev->srcVsize - pdev->wndVsize)>>1;
winHorOfst &= 0xFFFFFFF8;
winVerOfst &= 0xFFFFFFF8;
if ((winHorOfst == 0)&&(winVerOfst == 0))
{
ciwdofst = 0; // disable windows offset.
}
else
{
ciwdofst = (1<<31) // window offset enable
|(1<<30) // clear the overflow ind flag of input CODEC FIFO Y
|(winHorOfst<<16) // windows horizontal offset
|(1<<15) // clear the overflow ind flag of input CODEC FIFO Cb
|(1<<14) // clear the overflow ind flag of input CODEC FIFO Cr
|(1<<13) // clear the overflow ind flag of input PREVIEW FIFO Cb
|(1<<12) // clear the overflow ind flag of input PREVIEW FIFO Cr
|(winVerOfst<<0); // window vertical offset
}
iowrite32(ciwdofst, S3C244X_CIWDOFST);
}
/* update registers:
* PREVIEW path:
* CIPRSCPRERATIO
* CIPRSCPREDST
* CIPRSCCTRL
* CODEC path:
* CICOSCPRERATIO
* CICOSCPREDST
* CICOSCCTRL
*/
static void __inline__ update_target_zoom_regs(struct s3c2440camif_dev *pdev)
{
u32 preHratio, preVratio;
u32 coHratio, coVratio;
u32 Hshift, Vshift;
u32 shfactor;
u32 preDstWidth, preDstHeight;
u32 Hscale, Vscale;
u32 mainHratio, mainVratio;
u32 ciprscpreratio, cicoscpreratio;
u32 ciprscpredst, cicoscpredst;
u32 ciprscctrl, cicoscctrl;
switch(pdev->path) {
case CAMIF_PATH_PREVIEW:
/* CIPRSCPRERATIO. */
calc_prescaler_ratio_shift(pdev->srcHsize, pdev->preTargetHsize,
&preHratio, &Hshift);
calc_prescaler_ratio_shift(pdev->srcVsize, pdev->preTargetVsize,
&preVratio, &Vshift);
shfactor = 10 - (Hshift + Vshift);
ciprscpreratio = (shfactor<<28) // shift factor for preview pre-scaler
|(preHratio<<16) // horizontal ratio of preview pre-scaler
|(preVratio<<0); // vertical ratio of preview pre-scaler
iowrite32(ciprscpreratio, S3C244X_CIPRSCPRERATIO);
/* CIPRSCPREDST. */
preDstWidth = pdev->srcHsize / preHratio;
preDstHeight = pdev->srcVsize / preVratio;
ciprscpredst = (preDstWidth<<16) // destination width for preview pre-scaler
|(preDstHeight<<0); // destination height for preview pre-scaler
iowrite32(ciprscpredst, S3C244X_CIPRSCPREDST);
/* CIPRSCCTRL. */
Hscale = (pdev->srcHsize >= pdev->preTargetHsize)?0:1;
Vscale = (pdev->srcVsize >= pdev->preTargetVsize)?0:1;
mainHratio = (pdev->srcHsize<<8)/(pdev->preTargetHsize<
mainVratio = (pdev->srcVsize<<8)/(pdev->preTargetVsize<
ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);
ciprscctrl &= ~(1<<30); //keep preview image format RGB565
// ciprscctrl &= (1<<15); //preview scaler start.
ciprscctrl |= (1<<31) // this bit should be always 1.
|(Hscale<<29) // ???, horizontal scale up/down.
|(Vscale<<28) // ???, vertical scale up/down.
|(mainHratio<<16) // horizontal scale ratio for preview main-scaler
|(mainVratio<<0); // vertical scale ratio for preview main-scaler
iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);
break;
case CAMIF_PATH_CODEC:
/* CICOSCPRERATIO. */
calc_prescaler_ratio_shift(pdev->srcHsize, pdev->coTargetHsize,
&coHratio, &Hshift);
calc_prescaler_ratio_shift(pdev->srcVsize, pdev->coTargetVsize,
&coVratio, &Vshift);
shfactor = 10 - (Hshift + Vshift);
cicoscpreratio = (shfactor<<28) // shift factor for preview pre-scaler
|(coHratio<<16) // horizontal ratio of preview pre-scaler
|(coVratio<<0); // vertical ratio of preview pre-scaler
iowrite32(cicoscpreratio, S3C244X_CICOSCPRERATIO);
/* CICOSCPREDST. */
preDstWidth = pdev->srcHsize / coHratio;
preDstHeight = pdev->srcVsize / coVratio;
cicoscpredst = (preDstWidth<<16) // destination width for preview pre-scaler
|(preDstHeight<<0); // destination height for preview pre-scaler
iowrite32(cicoscpredst, S3C244X_CICOSCPREDST);
/* CICOSCCTRL. */
Hscale = (pdev->srcHsize >= pdev->coTargetHsize)?0:1;
Vscale = (pdev->srcVsize >= pdev->coTargetVsize)?0:1;
mainHratio = (pdev->srcHsize<<8)/(pdev->coTargetHsize<
mainVratio = (pdev->srcVsize<<8)/(pdev->coTargetVsize<
cicoscctrl = ioread32(S3C244X_CICOSCCTRL);
// cicoscctrl &= (1<<15); //codec scaler start.
cicoscctrl |=
(Hscale<<30) // ???, horizontal scale up/down.
|(Vscale<<29) // ???, vertical scale up/down.
|(mainHratio<<16) // horizontal scale ratio for preview main-scaler
|(mainVratio<<0); // vertical scale ratio for preview main-scaler
iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);
break;
}
}
/* update camif registers, called only when camif ready, or ISR. */
static void __inline__ update_camif_regs(struct s3c2440camif_dev * pdev)
{
if (!in_irq())
{
while(1) // wait until VSYNC is 'L'
{
barrier();
if ((ioread32(S3C244X_CICOSTATUS)&(1<<28)) == 0)
break;
}
}
/* WARNING: don't change the statement sort below!!! */
update_source_fmt_regs(pdev);
update_target_wnd_regs(pdev);
update_target_fmt_regs(pdev);
update_target_zoom_regs(pdev);
}
/* start image capture.
*
* param 'stream' means capture pictures streamly or capture only one picture.
*/
static int start_capture(struct s3c2440camif_dev * pdev)
{
int ret;
u32 ciwdofst;
u32 ciprscctrl, cicoscctrl;
u32 ciimgcpt;
if(pdev->path == CAMIF_PATH_NONE)
return 0;
ciwdofst = ioread32(S3C244X_CIWDOFST);
ciwdofst |= (1<<30) // Clear the overflow indication flag of input CODEC FIFO Y
|(1<<15) // Clear the overflow indication flag of input CODEC FIFO Cb
|(1<<14) // Clear the overflow indication flag of input CODEC FIFO Cr
|(1<<13) // Clear the overflow indication flag of input PREVIEW FIFO Cb
|(1<<12); // Clear the overflow indication flag of input PREVIEW FIFO Cr
iowrite32(ciwdofst, S3C244X_CIWDOFST);
switch(pdev->path) {
case CAMIF_PATH_PREVIEW:
//printk("Preview Start...\n");
ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);
ciprscctrl |= 1<<15; // preview scaler start
iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);
ciimgcpt = (1<<31) // camera interface global capture enable
|(1<<29); // capture enable for preview scaler.
iowrite32(ciimgcpt, S3C244X_CIIMGCPT);
pdev->state = CAMIF_STATE_PREVIEWING;
break;
case CAMIF_PATH_CODEC:
//printk("Codec Start...\n");
cicoscctrl = ioread32(S3C244X_CICOSCCTRL);
cicoscctrl |= (1<<15); // codec scaler start
iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);
ciimgcpt = (1<<31) // camera interface global capture enable
|(1<<30); // capture enable for codec scaler.
iowrite32(ciimgcpt, S3C244X_CIIMGCPT);
pdev->state = CAMIF_STATE_CODECING;
break;
}
ret = 0;
#if 0
if (stream == 0)
{
pdev->cmdcode = CAMIF_CMD_STOP;
ret = wait_event_interruptible(pdev->wait, pdev->cmdcode == CAMIF_CMD_NONE);
}
#endif
return ret;
}
/* stop image capture, always called in ISR.
* P-path regs:
* CIPRSCCTRL
* CIPRCTRL
* C-path regs:
* CICOSCCTRL.
* CICOCTRL
* Global regs:
* CIIMGCPT
*/
static void stop_capture(struct s3c2440camif_dev * pdev)
{
u32 ciprscctrl, cicoscctrl;
u32 ciprctrl, cicoctrl;
switch(pdev->state)
{
case CAMIF_STATE_PREVIEWING:
/* CIPRCTRL. */
ciprctrl = ioread32(S3C244X_CIPRCTRL);
ciprctrl |= 1<<2; // enable last IRQ at the end of frame capture.
iowrite32(ciprctrl, S3C244X_CIPRCTRL);
/* CIPRSCCTRL. */
ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);
ciprscctrl &= ~(1<<15); // clear preview scaler start bit.
iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);
break;
case CAMIF_STATE_CODECING:
/* CICOCTRL. */
cicoctrl = ioread32(S3C244X_CICOCTRL);
cicoctrl |= 1<<2; // enable last IRQ at the end of frame capture.
iowrite32(cicoctrl, S3C244X_CICOCTRL);
/* CICOSCCTRL. */
cicoscctrl = ioread32(S3C244X_CICOSCCTRL);
cicoscctrl &= ~(1<<15); // clear codec scaler start bit.
iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);
break;
}
/* CIIMGCPT. */
iowrite32(0, S3C244X_CIIMGCPT);
pdev->state = CAMIF_STATE_READY;
}
/* update camera interface with the new config. */
static void update_camif_config (struct s3c2440camif_dev *pdev, u32 cmdcode)
{
switch(pdev->state)
{
case CAMIF_STATE_READY:
if(cmdcode == CAMIF_CMD_REGS)
{
update_camif_regs(pdev); // config the regs directly.
break;
}
#if 0
/* source image format. */
if (cmdcode & CAMIF_CMD_SFMT)
{
// ignore it, nothing to do now.
}
/* target image format. */
if (cmdcode & CAMIF_CMD_TFMT)
{
/* change target image format only. */
}
/* target image window offset. */
if (cmdcode & CAMIF_CMD_WND)
{
}
/* target image zoomi & zoomout. */
if (cmdcode & CAMIF_CMD_ZOOM)
{
}
#endif
if (cmdcode == CAMIF_CMD_P2C)
{
camif_p2c(pdev);
break;
}
if (cmdcode == CAMIF_CMD_C2P)
{
camif_c2p(pdev);
break;
}
if (cmdcode == CAMIF_CMD_START)
{
start_capture(pdev);
}
break;
case CAMIF_STATE_PREVIEWING:
/* camif is previewing image. */
disable_irq(IRQ_S3C2440_CAM_P); // disable cam-preview irq.
/* stop previewing. */
if (cmdcode & CAMIF_CMD_STOP)
{
pdev->cmdcode |= CAMIF_CMD_STOP;
}
enable_irq(IRQ_S3C2440_CAM_P); // enable cam-preview irq.
wait_event(pdev->wait, (pdev->cmdcode==CAMIF_CMD_NONE)); // wait until the ISR completes command.
break;
case CAMIF_STATE_CODECING:
/* camif is previewing image. */
disable_irq(IRQ_S3C2440_CAM_C); // disable cam-codec irq.
/* stop previewing. */
if (cmdcode & CAMIF_CMD_STOP)
{
pdev->cmdcode |= CAMIF_CMD_STOP;
}
enable_irq(IRQ_S3C2440_CAM_C); // enable cam-codec irq.
wait_event(pdev->wait, (pdev->cmdcode==CAMIF_CMD_NONE)); // wait until the ISR completes command.
break;
default:
break;
}
}
static void __inline__ invalid_image_buffer(void)
{
img_buff[0].state = CAMIF_BUFF_INVALID;
img_buff[1].state = CAMIF_BUFF_INVALID;
img_buff[2].state = CAMIF_BUFF_INVALID;
img_buff[3].state = CAMIF_BUFF_INVALID;
}
/* init image buffer (only when the camif is first open). */
static int __inline__ init_image_buffer(struct s3c2440camif_dev *pdev)
{
int size1, size2;
unsigned long size = 0;
unsigned int order = 0;
/* size1 is the max image size of codec path. */
size1 = MAX_C_WIDTH * MAX_C_HEIGHT * 2;
/* size2 is the max image size of preview path. */
size2 = MAX_P_WIDTH * MAX_P_HEIGHT * 2;
size = (size1 > size2) ? size1 : size2;
printk("dma_alloc_coherent <0> size : 0x%08x\n", size);
order = get_order(size);
img_buff[0].order = order;
img_buff[0].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[0].order);
if (img_buff[0].virt_base == (unsigned long)NULL)
{
goto error0;
}
img_buff[0].img_size = size;
img_buff[0].phy_base = img_buff[0].virt_base - PAGE_OFFSET + PHYS_OFFSET; // the DMA address.
img_buff[0].offset = 0;
printk("dma_alloc_coherent <1> size : 0x%08x\n", size);
img_buff[1].order = order;
img_buff[1].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[1].order);
if (img_buff[1].virt_base == (unsigned long)NULL)
{
goto error1;
}
img_buff[1].img_size = size;
img_buff[1].phy_base = img_buff[1].virt_base - PAGE_OFFSET + PHYS_OFFSET; // the DMA address.
img_buff[1].offset = PAGE_SIZE << order;
printk("dma_alloc_coherent <2> size : 0x%08x\n", size);
img_buff[2].order = order;
img_buff[2].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[2].order);
if (img_buff[2].virt_base == (unsigned long)NULL)
{
goto error2;
}
img_buff[2].img_size = size;
img_buff[2].phy_base = img_buff[2].virt_base - PAGE_OFFSET + PHYS_OFFSET; // the DMA address.
img_buff[2].offset = (PAGE_SIZE << order) * 2;
printk("dma_alloc_coherent <3> size : 0x%08x\n", size);
img_buff[3].order = order;
img_buff[3].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[3].order);
if (img_buff[3].virt_base == (unsigned long)NULL)
{
goto error3;
}
img_buff[3].img_size = size;
img_buff[3].phy_base = img_buff[3].virt_base - PAGE_OFFSET + PHYS_OFFSET; // the DMA address.
img_buff[3].offset = (PAGE_SIZE << order) * 3;
invalid_image_buffer();
return 0;
error3:
free_pages(img_buff[2].virt_base, order);
img_buff[2].phy_base = (unsigned long)NULL;
error2:
free_pages(img_buff[1].virt_base, order);
img_buff[1].phy_base = (unsigned long)NULL;
error1:
free_pages(img_buff[0].virt_base, order);
img_buff[0].phy_base = (unsigned long)NULL;
error0:
return -ENOMEM;
}
/* free image buffers (only when the camif is latest close). */
static void __inline__ free_image_buffer(struct s3c2440camif_dev *pdev)
{
free_pages(img_buff[0].virt_base, img_buff[0].order);
free_pages(img_buff[1].virt_base, img_buff[1].order);
free_pages(img_buff[2].virt_base, img_buff[2].order);
free_pages(img_buff[3].virt_base, img_buff[3].order);
img_buff[0].order = 0;
img_buff[0].virt_base = (unsigned long)NULL;
img_buff[0].phy_base = (unsigned long)NULL;
img_buff[0].offset = 0;
img_buff[1].order = 0;
img_buff[1].virt_base = (unsigned long)NULL;
img_buff[1].phy_base = (unsigned long)NULL;
img_buff[1].offset = 0;
img_buff[2].order = 0;
img_buff[2].virt_base = (unsigned long)NULL;
img_buff[2].phy_base = (unsigned long)NULL;
img_buff[2].offset = 0;
img_buff[3].order = 0;
img_buff[3].virt_base = (unsigned long)NULL;
img_buff[3].phy_base = (unsigned long)NULL;
img_buff[3].offset = 0;
}
static void __inline__ update_image_buffer(struct s3c2440camif_dev *pdev)
{
unsigned long size = 0;
switch(pdev->pixelformat) {
case V4L2_PIX_FMT_RGB565:
size = pdev->preTargetHsize * pdev->preTargetVsize * 2;
2009年6月30日 星期二
2009年6月18日 星期四
YUV to RGB optimization
1.Color space conversion
光是公式偶就找到至少三種,但是其中的差異並不清楚.
R = 1.164 * (Y-16) + + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
R = Y + 1.370705 (V-128)
G = Y - 0.698001 (V-128) - 0.337633 (U-128)
B = Y + 1.732446 (U-128)
R = Y + 1.4075 * (V-128)
G = Y – 0.3455 * (U –128) – 0.7169 * (V –128)
B = Y + 1.779 * (U – 128)
根據http://www.fourcc.org/indexyuv.htm
第三種"似乎"才是正確的.
由以上公式可看出都需要作浮點運算,而偶的target platform剛好沒有FPU.
直接運算將會是場災難.
2.選擇公式一作轉換.
YUV is 8 bits data. RGB format is RGB565
R = 1.164 * (Y-16) + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
***Set variables***
YY = 1.164 * (Y-16)
RV = 1.596 * (V-128)
GU = 0.391 * (U-128)
GV = 0.813 * (V-128)
BU = 2.018 * (U-128)
So we got
R = YY + RV
G = YY - GU - GV
B = YY + BU
***Remove floating point by left shift 15***
YY = (YY << 15) = 38142(y-16)
RV = (RV << 15) = 52298(V-128)
GU = (GU << 15) = 12813(U-128)
GV = (GV << 15) = 26641(V-128)
BU = (BU << 15) = 66126(U-128)
Right shift R,G,B to get result
R = (YY + RV) >> 15
G = (YY - GU - GV) >> 15
B = (YY + BU) >> 15
***Create yuv coefficient tables***
由於YUV為8bits,以上的公式只需要5 * 2^8的表格即可.
int yy[256];
for(i=0;i<256;i++)
yy[i] = 38142(i-16)
...
...
***Handle RGB565***
B G R
|-----|------|-----| 16bits
5 6 5
So
R = R >> 3
G = (G & 0xFC) << 3
B = B << 8
***Create RGB result tables***
According to cacluation we know
481 >= R >= -223
432 >= G >= -172
534 >= B >= -277
We'd like RGB value from 0 to 255, so create tables to map the final value.
Also consider RGB 565 into the tables .
unsigned short rt[481+223];
diffcoef = (double) 481 / 256; /*Ignore value less than zero*/
for(i=0;i<704;i++) {
if((i + min) < 0)
rt[i] = 0; /*Ignore value less than zero by setting it to zero*/
else
rt[i] = (unsigned short)(i / diffcoef);
rt[i] >>= 3; /*Handle RGB565*/
}
...
...
Finally we got
RGB565 = bt[((yy[y]+bu[u]) >> 15) - 277] |
gt[((yy[y]+gv[v]+gu[u]) >> 15) -172] |
rt[((yy[y]+rv[v]) >> 15) - 223]
***Reference***
http://realchecko.blogspot.com/2009/02/yuv420-rgb565.html
http://rgbbones.googlepages.com/yuv2rgb
http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
http://multimedia.cx/yuv-3d-rgb.txt
***Example code***
#define precision 32768
typedef struct _ColorSpaceConversion {
int yy[256];
int rv[256];
int gu[256], gv[256];
int bu[256];
unsigned short *_rt, *_gt, *_bt;
unsigned short *rt, *gt, *bt;
} ColorSpaceConversion;
static ColorSpaceConversion csc;
/*
R = 1.164 * (Y-16) + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
*/
static const int cy = 38142; //(int)(1.164 * precision);
static const int crv = 52298; //(int)(1.596 * precision);
static const int cgu = 12813; //(int)(0.391 * precision);
static const int cgv = 26641; //(int)(0.813 * precision);
static const int cbu = 66126; //(int)(2.018 * precision);
void ColorSpaceConversion_Init()
{
int y, u, v;
for(y=0;y<256;y++)
csc.yy[y] = cy * (y - 16);
for(v=0;v<256;v++)
csc.rv[v] = crv * (v - 128);
for(u=0;u<256;u++)
csc.gu[u] = -cgu * (u - 128);
for(v=0;v<256;v++)
csc.gv[v] = -cgv * (v - 128);
for(u=0;u<256;u++)
csc.bu[u] = cbu * (u - 128);
/*
R : [ 481, -223 ] -> (481 + 223) / 256 = 2.75
G : [ 432, -172 ] -> (432 + 172) / 256 = 2.359375
B : [ 534, -277 ] -> (534 + 277) / 256 = 3.16796857
*/
int i;
int max, min, interval;
double diffcoef;
max = (csc.yy[255] + csc.rv[255]) >> 15;
min = (csc.yy[0] + csc.rv[0]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("R : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._rt = malloc(interval * sizeof(unsigned short));
csc.rt = csc._rt - min;
for(i=0;i
// csc._rt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._rt[i] = 0;
else
csc._rt[i] = (unsigned short)((i+min) / diffcoef);
csc._rt[i] >>= 3;
}
/**/
max = (csc.yy[255] + csc.gu[0] + csc.gv[0]) >> 15;
min = (csc.yy[0] + csc.gu[255] + csc.gv[255]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("G : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._gt = malloc(interval * sizeof(unsigned short));
csc.gt = csc._gt - min;
for(i=0;i
// csc._gt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._gt[i] = 0;
else
csc._gt[i] = (unsigned short)((i+min) / diffcoef);
csc._gt[i] &= 0xfc;
csc._gt[i] <<= 3;
}
/**/
max = (csc.yy[255] + csc.bu[255]) >> 15;
min = (csc.yy[0] + csc.bu[0]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("B : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._bt = malloc(interval * sizeof(unsigned short));
csc.bt = csc._bt - min;
for(i=0;i
// csc._bt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._bt[i] = 0;
else
csc._bt[i] = (unsigned short)((i+min) / diffcoef);
csc._bt[i] &= 0xf8;
csc._bt[i] <<= 8;
}
}
void ColorSpaceConversion_Deinit()
{
free(csc.rt);
free(csc.gt);
free(csc.bt);
}
光是公式偶就找到至少三種,但是其中的差異並不清楚.
R = 1.164 * (Y-16) + + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
R = Y + 1.370705 (V-128)
G = Y - 0.698001 (V-128) - 0.337633 (U-128)
B = Y + 1.732446 (U-128)
R = Y + 1.4075 * (V-128)
G = Y – 0.3455 * (U –128) – 0.7169 * (V –128)
B = Y + 1.779 * (U – 128)
根據http://www.fourcc.org/indexyuv.htm
第三種"似乎"才是正確的.
由以上公式可看出都需要作浮點運算,而偶的target platform剛好沒有FPU.
直接運算將會是場災難.
2.選擇公式一作轉換.
YUV is 8 bits data. RGB format is RGB565
R = 1.164 * (Y-16) + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
***Set variables***
YY = 1.164 * (Y-16)
RV = 1.596 * (V-128)
GU = 0.391 * (U-128)
GV = 0.813 * (V-128)
BU = 2.018 * (U-128)
So we got
R = YY + RV
G = YY - GU - GV
B = YY + BU
***Remove floating point by left shift 15***
YY = (YY << 15) = 38142(y-16)
RV = (RV << 15) = 52298(V-128)
GU = (GU << 15) = 12813(U-128)
GV = (GV << 15) = 26641(V-128)
BU = (BU << 15) = 66126(U-128)
Right shift R,G,B to get result
R = (YY + RV) >> 15
G = (YY - GU - GV) >> 15
B = (YY + BU) >> 15
***Create yuv coefficient tables***
由於YUV為8bits,以上的公式只需要5 * 2^8的表格即可.
int yy[256];
for(i=0;i<256;i++)
yy[i] = 38142(i-16)
...
...
***Handle RGB565***
B G R
|-----|------|-----| 16bits
5 6 5
So
R = R >> 3
G = (G & 0xFC) << 3
B = B << 8
***Create RGB result tables***
According to cacluation we know
481 >= R >= -223
432 >= G >= -172
534 >= B >= -277
We'd like RGB value from 0 to 255, so create tables to map the final value.
Also consider RGB 565 into the tables .
unsigned short rt[481+223];
diffcoef = (double) 481 / 256; /*Ignore value less than zero*/
for(i=0;i<704;i++) {
if((i + min) < 0)
rt[i] = 0; /*Ignore value less than zero by setting it to zero*/
else
rt[i] = (unsigned short)(i / diffcoef);
rt[i] >>= 3; /*Handle RGB565*/
}
...
...
Finally we got
RGB565 = bt[((yy[y]+bu[u]) >> 15) - 277] |
gt[((yy[y]+gv[v]+gu[u]) >> 15) -172] |
rt[((yy[y]+rv[v]) >> 15) - 223]
***Reference***
http://realchecko.blogspot.com/2009/02/yuv420-rgb565.html
http://rgbbones.googlepages.com/yuv2rgb
http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
http://multimedia.cx/yuv-3d-rgb.txt
***Example code***
#define precision 32768
typedef struct _ColorSpaceConversion {
int yy[256];
int rv[256];
int gu[256], gv[256];
int bu[256];
unsigned short *_rt, *_gt, *_bt;
unsigned short *rt, *gt, *bt;
} ColorSpaceConversion;
static ColorSpaceConversion csc;
/*
R = 1.164 * (Y-16) + 1.596 * (V-128)
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128)
B = 1.164 * (Y-16) + 2.018 * (U-128)
*/
static const int cy = 38142; //(int)(1.164 * precision);
static const int crv = 52298; //(int)(1.596 * precision);
static const int cgu = 12813; //(int)(0.391 * precision);
static const int cgv = 26641; //(int)(0.813 * precision);
static const int cbu = 66126; //(int)(2.018 * precision);
void ColorSpaceConversion_Init()
{
int y, u, v;
for(y=0;y<256;y++)
csc.yy[y] = cy * (y - 16);
for(v=0;v<256;v++)
csc.rv[v] = crv * (v - 128);
for(u=0;u<256;u++)
csc.gu[u] = -cgu * (u - 128);
for(v=0;v<256;v++)
csc.gv[v] = -cgv * (v - 128);
for(u=0;u<256;u++)
csc.bu[u] = cbu * (u - 128);
/*
R : [ 481, -223 ] -> (481 + 223) / 256 = 2.75
G : [ 432, -172 ] -> (432 + 172) / 256 = 2.359375
B : [ 534, -277 ] -> (534 + 277) / 256 = 3.16796857
*/
int i;
int max, min, interval;
double diffcoef;
max = (csc.yy[255] + csc.rv[255]) >> 15;
min = (csc.yy[0] + csc.rv[0]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("R : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._rt = malloc(interval * sizeof(unsigned short));
csc.rt = csc._rt - min;
for(i=0;i
// csc._rt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._rt[i] = 0;
else
csc._rt[i] = (unsigned short)((i+min) / diffcoef);
csc._rt[i] >>= 3;
}
/**/
max = (csc.yy[255] + csc.gu[0] + csc.gv[0]) >> 15;
min = (csc.yy[0] + csc.gu[255] + csc.gv[255]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("G : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._gt = malloc(interval * sizeof(unsigned short));
csc.gt = csc._gt - min;
for(i=0;i
// csc._gt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._gt[i] = 0;
else
csc._gt[i] = (unsigned short)((i+min) / diffcoef);
csc._gt[i] &= 0xfc;
csc._gt[i] <<= 3;
}
/**/
max = (csc.yy[255] + csc.bu[255]) >> 15;
min = (csc.yy[0] + csc.bu[0]) >> 15;
interval = max - min;
// diffcoef = (double) interval / 256;
diffcoef = (double) max / 256;
printf("B : [ %d, %d ] = %d (%f)\n", max, min, interval, diffcoef);
csc._bt = malloc(interval * sizeof(unsigned short));
csc.bt = csc._bt - min;
for(i=0;i
// csc._bt[i] = (unsigned short)(i / diffcoef);
if((i + min) < 0)
csc._bt[i] = 0;
else
csc._bt[i] = (unsigned short)((i+min) / diffcoef);
csc._bt[i] &= 0xf8;
csc._bt[i] <<= 8;
}
}
void ColorSpaceConversion_Deinit()
{
free(csc.rt);
free(csc.gt);
free(csc.bt);
}
2009年6月1日 星期一
PATCH microwindows-0.91 to support tslib-1.4
diff -Naur VT300/microwindows-0.91/src/config S3C2440/microwindows-0.91/src/config
--- VT300/microwindows-0.91/src/config 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/config 2009-06-01 13:11:51.000000000 +0800
@@ -37,7 +37,7 @@
# note: ELKS can't build client/server nano-X, nor widget lib
#
####################################################################
-ARCH = LINUX-MIPS
+ARCH = LINUX-ARM
BIGENDIAN = N
NATIVETOOLSPREFIX =
ARMTOOLSPREFIX = arm-linux-
@@ -137,7 +137,7 @@
####################################################################
HAVE_JPEG_SUPPORT = Y
INCJPEG = .
-LIBJPEG = /usr/local/MIPSEL_UCLIBC/lib/libjpeg.a
+LIBJPEG = /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib/libjpeg.so
####################################################################
# PNG support via libpng and libz
@@ -145,7 +145,7 @@
HAVE_PNG_SUPPORT = Y
INCPNG = .
#LIBPNG = /usr/lib/libpng.a
-LIBPNG = /usr/local/MIPSEL_UCLIBC/lib/libpng.so
+LIBPNG = /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/libpng.so
LIBZ = -lz
####################################################################
@@ -192,7 +192,7 @@
####################################################################
HAVE_PCF_SUPPORT = Y
HAVE_PCFGZ_SUPPORT = N
-PCF_FONT_DIR = "/phone/lib/X11/fonts/misc"
+PCF_FONT_DIR = "/lib/X11/fonts/misc"
####################################################################
# Chinese Han Zi Ku loadable font support
@@ -316,7 +316,7 @@
GPMMOUSE = N
SERMOUSE = N
SUNMOUSE = N
-NOMOUSE = Y
+NOMOUSE = N
IPAQMOUSE = N
ZAURUSMOUSE = N
TUXMOUSE = N
@@ -329,15 +329,19 @@
YOPYMOUSE = N
HARRIERMOUSE = N
LIRCMOUSE = N
+TSLIBMOUSE = Y
+
+INCTSLIB = /home/gigijoe/S3C2440/tslib/src
+LIBTS = /home/gigijoe/S3C2440/tslib/src/.libs/libts.so
# keyboard or null kbd driver
TTYKBD = N
SCANKBD = N
-AC494KBD = Y
+AC494KBD = N
PIPEKBD = N
IPAQKBD = N
LIRCKBD = N
-NOKBD = N
+NOKBD = Y
endif
diff -Naur VT300/microwindows-0.91/src/drivers/mou_touchscreen.c S3C2440/microwindows-0.91/src/drivers/mou_touchscreen.c
--- VT300/microwindows-0.91/src/drivers/mou_touchscreen.c 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/drivers/mou_touchscreen.c 2009-06-01 14:52:17.000000000 +0800
@@ -46,15 +46,22 @@
#include "touchscreen_ucb1x00.h"
#endif
+#ifdef TOUCHSCREEN_TSLIB
+#include "touchscreen_tslib.h"
+#endif
+
+extern SCREENDEVICE scrdev;
+
+#ifndef TOUCHSCREEN_TSLIB
+
#ifndef TS_DEVICE
#error "You didn't define a device for the generic touchscreen driver!"
#endif
static int pd_fd = -1;
-extern SCREENDEVICE scrdev;
static int PD_Open(MOUSEDEVICE *pmd)
-{
+{
if((pd_fd = open(TS_DEVICE_FILE, O_NONBLOCK)) < 0) {
EPRINTF("Error %d opening %s touchscreen device [%s]\n",
errno, TS_DEVICE, TS_DEVICE_FILE);
@@ -123,6 +130,84 @@
return 2;
}
+#else
+
+static struct tsdev *ts = 0;
+
+static int PD_Open(MOUSEDEVICE *pmd)
+{
+ char *tsdevice=NULL;
+
+ if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
+ ts = ts_open(tsdevice,0);
+ } else {
+ if (!(ts = ts_open("/dev/input/event0", 0)))
+ ts = ts_open("/dev/touchscreen/ucb1x00", 0);
+ }
+
+ if (!ts) {
+ perror("ts_open");
+ return -1;
+ }
+
+ if (ts_config(ts)) {
+ perror("ts_config");
+ ts_close(ts);
+ ts = 0;
+ return -1;
+ }
+
+ GdHideCursor(&scrdev);
+
+ return ts_fd(ts);
+}
+
+static void PD_Close(void)
+{
+ if(ts)
+ ts_close(ts);
+ ts = 0;
+}
+
+static int PD_GetButtonInfo(void)
+{
+ /* get "mouse" buttons supported */
+ return MWBUTTON_L;
+}
+
+static void PD_GetDefaultAccel(int *pscale,int *pthresh)
+{
+ *pscale = 3;
+ *pthresh = 5;
+}
+
+static int PD_Read(MWCOORD *px, MWCOORD *py, MWCOORD *pz, int *pb, int mode)
+{
+ struct ts_sample samp;
+ int ret;
+
+ ret = ts_read(ts, &samp, 1);
+
+ if (ret < 0) {
+ perror("ts_read");
+ return 0;
+ }
+
+ if(ret != 1) /*EAGAIN*/
+ return 0;
+printf("%ld.%06ld: %6d %6d %6d\n", samp.tv.tv_sec, samp.tv.tv_usec, samp.x, samp.y, samp.pressure);
+ *px = samp.x;
+ *py = samp.y;
+ *pb = (samp.pressure) ? MWBUTTON_L : 0;
+ *pz = samp.pressure;
+
+ if(!*pb)
+ return 3;
+ return 2;
+}
+
+#endif
+
MOUSEDEVICE mousedev = {
PD_Open,
PD_Close,
diff -Naur VT300/microwindows-0.91/src/drivers/Objects.rules S3C2440/microwindows-0.91/src/drivers/Objects.rules
--- VT300/microwindows-0.91/src/drivers/Objects.rules 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/drivers/Objects.rules 2009-05-27 22:36:54.000000000 +0800
@@ -221,6 +221,12 @@
MW_CORE_OBJS += $(MW_DIR_OBJ)/drivers/mou_null.o
endif
+### Touchscreen handle by tslib
+ifeq ($(TSLIBMOUSE), Y)
+CFLAGS += -DTOUCHSCREEN_TSLIB=1
+MW_CORE_OBJS += $(MW_DIR_OBJ)/drivers/mou_touchscreen.o
+endif
+
#
# Keyboard driver specific for every system
#
diff -Naur VT300/microwindows-0.91/src/drivers/touchscreen_tslib.h S3C2440/microwindows-0.91/src/drivers/touchscreen_tslib.h
--- VT300/microwindows-0.91/src/drivers/touchscreen_tslib.h 1970-01-01 08:00:00.000000000 +0800
+++ S3C2440/microwindows-0.91/src/drivers/touchscreen_tslib.h 2009-05-27 22:38:02.000000000 +0800
@@ -0,0 +1 @@
+#include "tslib.h"
diff -Naur VT300/microwindows-0.91/src/Makefile.rules S3C2440/microwindows-0.91/src/Makefile.rules
--- VT300/microwindows-0.91/src/Makefile.rules 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/Makefile.rules 2009-05-27 23:24:19.000000000 +0800
@@ -278,6 +278,14 @@
DEFINES += -DMW_LIRC_MOUSE=1
endif
+ifeq ($(TSLIBMOUSE), Y)
+ifneq ($(INCTSLIB),)
+INCLUDEDIRS += -I$(INCTSLIB)
+endif
+LDFLAGS += -lts
+MW_CORE_LIBS += $(LIBTS)
+endif
+
ifeq ($(LIRCKBD2), Y)
DEFINES += -DMW_FEATURE_TWO_KEYBOARDS=1
endif
@@ -332,7 +340,7 @@
ifneq ($(ARCH), TRIMEDIA)
ifeq ($(SHAREDLIBS), Y)
-CFLAGS += -fpic
+CFLAGS += -fomit-frame-pointer -march=armv4
endif
ifeq ($(OPTIMIZE), Y)
@@ -356,7 +364,7 @@
MAKEDEPCFLAGS :=
HOSTCFLAGS :=
CPPFLAGS += $(DEFINES)
-LDFLAGS += -L$(MW_DIR_LIB)
+LDFLAGS += -L$(MW_DIR_LIB) -lgcc_s
ifeq ($(ARCH), TRIMEDIA)
ARFLAGS = r
else
diff -Naur VT300/microwindows-0.91/src/nanox/clientfb.c S3C2440/microwindows-0.91/src/nanox/clientfb.c
--- VT300/microwindows-0.91/src/nanox/clientfb.c 2009-01-23 21:29:30.000000000 +0800
+++ S3C2440/microwindows-0.91/src/nanox/clientfb.c 2009-05-20 17:10:45.000000000 +0800
@@ -10,7 +10,9 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#if 0
#include <asm/page.h> /* For definition of PAGE_SIZE */
+#endif
#include <linux/fb.h>
#endif
#include "nano-X.h"
@@ -18,7 +20,7 @@
#define CG6_RAM 0x70016000 /* for Sun systems*/
-#ifdef LINUX-MIPS
+#ifdef LINUX-ARM
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
diff -Naur VT300/microwindows-0.91/src/nanox/nxutil.c S3C2440/microwindows-0.91/src/nanox/nxutil.c
--- VT300/microwindows-0.91/src/nanox/nxutil.c 2009-01-23 21:29:30.000000000 +0800
+++ S3C2440/microwindows-0.91/src/nanox/nxutil.c 2009-05-20 18:34:54.000000000 +0800
@@ -11,6 +11,19 @@
#include "nano-X.h"
#include "device.h"
+#if 0
+extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
+int __aeabi_idiv(int numerator, int denominator)
+ {
+ int neg_result = (numerator ^ denominator) & 0x80000000;
+ int result = __aeabi_uidivmod ((numerator < 0) ? -numerator : numerator, (denominator < 0) ? -denominator : denominator);
+ return neg_result ? -result : result; }
+unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
+ {
+ return __aeabi_uidivmod (numerator, denominator);
+ }
+#endif
+
/*
* Create new window with passed style, title and location.
*/
--- VT300/microwindows-0.91/src/config 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/config 2009-06-01 13:11:51.000000000 +0800
@@ -37,7 +37,7 @@
# note: ELKS can't build client/server nano-X, nor widget lib
#
####################################################################
-ARCH = LINUX-MIPS
+ARCH = LINUX-ARM
BIGENDIAN = N
NATIVETOOLSPREFIX =
ARMTOOLSPREFIX = arm-linux-
@@ -137,7 +137,7 @@
####################################################################
HAVE_JPEG_SUPPORT = Y
INCJPEG = .
-LIBJPEG = /usr/local/MIPSEL_UCLIBC/lib/libjpeg.a
+LIBJPEG = /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib/libjpeg.so
####################################################################
# PNG support via libpng and libz
@@ -145,7 +145,7 @@
HAVE_PNG_SUPPORT = Y
INCPNG = .
#LIBPNG = /usr/lib/libpng.a
-LIBPNG = /usr/local/MIPSEL_UCLIBC/lib/libpng.so
+LIBPNG = /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/libpng.so
LIBZ = -lz
####################################################################
@@ -192,7 +192,7 @@
####################################################################
HAVE_PCF_SUPPORT = Y
HAVE_PCFGZ_SUPPORT = N
-PCF_FONT_DIR = "/phone/lib/X11/fonts/misc"
+PCF_FONT_DIR = "/lib/X11/fonts/misc"
####################################################################
# Chinese Han Zi Ku loadable font support
@@ -316,7 +316,7 @@
GPMMOUSE = N
SERMOUSE = N
SUNMOUSE = N
-NOMOUSE = Y
+NOMOUSE = N
IPAQMOUSE = N
ZAURUSMOUSE = N
TUXMOUSE = N
@@ -329,15 +329,19 @@
YOPYMOUSE = N
HARRIERMOUSE = N
LIRCMOUSE = N
+TSLIBMOUSE = Y
+
+INCTSLIB = /home/gigijoe/S3C2440/tslib/src
+LIBTS = /home/gigijoe/S3C2440/tslib/src/.libs/libts.so
# keyboard or null kbd driver
TTYKBD = N
SCANKBD = N
-AC494KBD = Y
+AC494KBD = N
PIPEKBD = N
IPAQKBD = N
LIRCKBD = N
-NOKBD = N
+NOKBD = Y
endif
diff -Naur VT300/microwindows-0.91/src/drivers/mou_touchscreen.c S3C2440/microwindows-0.91/src/drivers/mou_touchscreen.c
--- VT300/microwindows-0.91/src/drivers/mou_touchscreen.c 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/drivers/mou_touchscreen.c 2009-06-01 14:52:17.000000000 +0800
@@ -46,15 +46,22 @@
#include "touchscreen_ucb1x00.h"
#endif
+#ifdef TOUCHSCREEN_TSLIB
+#include "touchscreen_tslib.h"
+#endif
+
+extern SCREENDEVICE scrdev;
+
+#ifndef TOUCHSCREEN_TSLIB
+
#ifndef TS_DEVICE
#error "You didn't define a device for the generic touchscreen driver!"
#endif
static int pd_fd = -1;
-extern SCREENDEVICE scrdev;
static int PD_Open(MOUSEDEVICE *pmd)
-{
+{
if((pd_fd = open(TS_DEVICE_FILE, O_NONBLOCK)) < 0) {
EPRINTF("Error %d opening %s touchscreen device [%s]\n",
errno, TS_DEVICE, TS_DEVICE_FILE);
@@ -123,6 +130,84 @@
return 2;
}
+#else
+
+static struct tsdev *ts = 0;
+
+static int PD_Open(MOUSEDEVICE *pmd)
+{
+ char *tsdevice=NULL;
+
+ if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
+ ts = ts_open(tsdevice,0);
+ } else {
+ if (!(ts = ts_open("/dev/input/event0", 0)))
+ ts = ts_open("/dev/touchscreen/ucb1x00", 0);
+ }
+
+ if (!ts) {
+ perror("ts_open");
+ return -1;
+ }
+
+ if (ts_config(ts)) {
+ perror("ts_config");
+ ts_close(ts);
+ ts = 0;
+ return -1;
+ }
+
+ GdHideCursor(&scrdev);
+
+ return ts_fd(ts);
+}
+
+static void PD_Close(void)
+{
+ if(ts)
+ ts_close(ts);
+ ts = 0;
+}
+
+static int PD_GetButtonInfo(void)
+{
+ /* get "mouse" buttons supported */
+ return MWBUTTON_L;
+}
+
+static void PD_GetDefaultAccel(int *pscale,int *pthresh)
+{
+ *pscale = 3;
+ *pthresh = 5;
+}
+
+static int PD_Read(MWCOORD *px, MWCOORD *py, MWCOORD *pz, int *pb, int mode)
+{
+ struct ts_sample samp;
+ int ret;
+
+ ret = ts_read(ts, &samp, 1);
+
+ if (ret < 0) {
+ perror("ts_read");
+ return 0;
+ }
+
+ if(ret != 1) /*EAGAIN*/
+ return 0;
+printf("%ld.%06ld: %6d %6d %6d\n", samp.tv.tv_sec, samp.tv.tv_usec, samp.x, samp.y, samp.pressure);
+ *px = samp.x;
+ *py = samp.y;
+ *pb = (samp.pressure) ? MWBUTTON_L : 0;
+ *pz = samp.pressure;
+
+ if(!*pb)
+ return 3;
+ return 2;
+}
+
+#endif
+
MOUSEDEVICE mousedev = {
PD_Open,
PD_Close,
diff -Naur VT300/microwindows-0.91/src/drivers/Objects.rules S3C2440/microwindows-0.91/src/drivers/Objects.rules
--- VT300/microwindows-0.91/src/drivers/Objects.rules 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/drivers/Objects.rules 2009-05-27 22:36:54.000000000 +0800
@@ -221,6 +221,12 @@
MW_CORE_OBJS += $(MW_DIR_OBJ)/drivers/mou_null.o
endif
+### Touchscreen handle by tslib
+ifeq ($(TSLIBMOUSE), Y)
+CFLAGS += -DTOUCHSCREEN_TSLIB=1
+MW_CORE_OBJS += $(MW_DIR_OBJ)/drivers/mou_touchscreen.o
+endif
+
#
# Keyboard driver specific for every system
#
diff -Naur VT300/microwindows-0.91/src/drivers/touchscreen_tslib.h S3C2440/microwindows-0.91/src/drivers/touchscreen_tslib.h
--- VT300/microwindows-0.91/src/drivers/touchscreen_tslib.h 1970-01-01 08:00:00.000000000 +0800
+++ S3C2440/microwindows-0.91/src/drivers/touchscreen_tslib.h 2009-05-27 22:38:02.000000000 +0800
@@ -0,0 +1 @@
+#include "tslib.h"
diff -Naur VT300/microwindows-0.91/src/Makefile.rules S3C2440/microwindows-0.91/src/Makefile.rules
--- VT300/microwindows-0.91/src/Makefile.rules 2009-01-23 21:29:29.000000000 +0800
+++ S3C2440/microwindows-0.91/src/Makefile.rules 2009-05-27 23:24:19.000000000 +0800
@@ -278,6 +278,14 @@
DEFINES += -DMW_LIRC_MOUSE=1
endif
+ifeq ($(TSLIBMOUSE), Y)
+ifneq ($(INCTSLIB),)
+INCLUDEDIRS += -I$(INCTSLIB)
+endif
+LDFLAGS += -lts
+MW_CORE_LIBS += $(LIBTS)
+endif
+
ifeq ($(LIRCKBD2), Y)
DEFINES += -DMW_FEATURE_TWO_KEYBOARDS=1
endif
@@ -332,7 +340,7 @@
ifneq ($(ARCH), TRIMEDIA)
ifeq ($(SHAREDLIBS), Y)
-CFLAGS += -fpic
+CFLAGS += -fomit-frame-pointer -march=armv4
endif
ifeq ($(OPTIMIZE), Y)
@@ -356,7 +364,7 @@
MAKEDEPCFLAGS :=
HOSTCFLAGS :=
CPPFLAGS += $(DEFINES)
-LDFLAGS += -L$(MW_DIR_LIB)
+LDFLAGS += -L$(MW_DIR_LIB) -lgcc_s
ifeq ($(ARCH), TRIMEDIA)
ARFLAGS = r
else
diff -Naur VT300/microwindows-0.91/src/nanox/clientfb.c S3C2440/microwindows-0.91/src/nanox/clientfb.c
--- VT300/microwindows-0.91/src/nanox/clientfb.c 2009-01-23 21:29:30.000000000 +0800
+++ S3C2440/microwindows-0.91/src/nanox/clientfb.c 2009-05-20 17:10:45.000000000 +0800
@@ -10,7 +10,9 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#if 0
#include <asm/page.h> /* For definition of PAGE_SIZE */
+#endif
#include <linux/fb.h>
#endif
#include "nano-X.h"
@@ -18,7 +20,7 @@
#define CG6_RAM 0x70016000 /* for Sun systems*/
-#ifdef LINUX-MIPS
+#ifdef LINUX-ARM
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
diff -Naur VT300/microwindows-0.91/src/nanox/nxutil.c S3C2440/microwindows-0.91/src/nanox/nxutil.c
--- VT300/microwindows-0.91/src/nanox/nxutil.c 2009-01-23 21:29:30.000000000 +0800
+++ S3C2440/microwindows-0.91/src/nanox/nxutil.c 2009-05-20 18:34:54.000000000 +0800
@@ -11,6 +11,19 @@
#include "nano-X.h"
#include "device.h"
+#if 0
+extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator);
+int __aeabi_idiv(int numerator, int denominator)
+ {
+ int neg_result = (numerator ^ denominator) & 0x80000000;
+ int result = __aeabi_uidivmod ((numerator < 0) ? -numerator : numerator, (denominator < 0) ? -denominator : denominator);
+ return neg_result ? -result : result; }
+unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
+ {
+ return __aeabi_uidivmod (numerator, denominator);
+ }
+#endif
+
/*
* Create new window with passed style, title and location.
*/
訂閱:
文章 (Atom)