WhyCan Forum

人过留名,雁过留声,感谢各位朋友不离不弃地支持。 QQ: 516333132 (挖坑网/填坑网) admin@whycan.cn

您尚未登录。

#1 2019-03-11 11:10:50

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

哪款芯片能同时接摄像头和LCD?

我想做个能实时采集视频并显示的东西,全志有什么芯片合适?最好是像F1C100s这样集成DRAM的。F1C100s的CSI和LCD复用了一些引脚,没法同时使用。

离线

#2 2019-03-11 11:58:28

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 8,175

Re: 哪款芯片能同时接摄像头和LCD?

BGA的S3可以:   https://whycan.cn/t_2227.html

离线

#3 2019-03-11 11:59:58

超级萌新
会员
注册时间: 2018-05-04
累计积分: 300

Re: 哪款芯片能同时接摄像头和LCD?

V3  S3 应该是H3的阉割并且sip dram的版本,我看了外设都是基本子集关系。

离线

#4 2019-03-11 16:57:09

dgtg
会员
注册时间: 2017-11-08
累计积分: 129

Re: 哪款芯片能同时接摄像头和LCD?

F1C100s也可以csi摄像头+RGB666输出的啊,看到过的

离线

#5 2019-03-11 17:09:51

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

Re: 哪款芯片能同时接摄像头和LCD?

晕哥 说:

BGA的S3可以:   https://whycan.cn/t_2227.html

不错,S3很强悍啊。唯一的障碍是BGA封装,还没画过更没焊过BGA呢……

离线

#6 2019-03-11 17:12:21

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

Re: 哪款芯片能同时接摄像头和LCD?

dgtg 说:

F1C100s也可以csi摄像头+RGB666输出的啊,看到过的

那有可能是SPI屏吧,带宽受限,做不到高刷新率。

离线

#7 2019-03-11 17:27:25

mango
会员
注册时间: 2017-12-02
累计积分: 368

Re: 哪款芯片能同时接摄像头和LCD?

Quotation 说:
晕哥 说:

BGA的S3可以:   https://whycan.cn/t_2227.html

不错,S3很强悍啊。唯一的障碍是BGA封装,还没画过更没焊过BGA呢……

搞吧,4mil/4mil,0.2/0.4通孔,华强嘉立创走起

离线

#8 2019-03-11 20:06:00

微凉VeiLiang
会员
注册时间: 2018-10-28
累计积分: 164

Re: 哪款芯片能同时接摄像头和LCD?

Quotation 说:
dgtg 说:

F1C100s也可以csi摄像头+RGB666输出的啊,看到过的

那有可能是SPI屏吧,带宽受限,做不到高刷新率。

F1C100S接口不冲突,低两位才和摄像头共用引脚,不像v3s

离线

#9 2019-03-12 09:08:11

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

Re: 哪款芯片能同时接摄像头和LCD?

微凉VeiLiang 说:

F1C100S接口不冲突,低两位才和摄像头共用引脚,不像v3s

从datasheet上看这几位都是和CSI冲突的,LCD的这几位实际用不到吗?

Screen-Shot-2019-03-12-at-08_57_54.png

离线

#10 2019-03-12 09:22:15

微凉VeiLiang
会员
注册时间: 2018-10-28
累计积分: 164

Re: 哪款芯片能同时接摄像头和LCD?

Quotation 说:
微凉VeiLiang 说:

F1C100S接口不冲突,低两位才和摄像头共用引脚,不像v3s

从datasheet上看这几位都是和CSI冲突的,LCD的这几位实际用不到吗?

https://whycan.cn/files/members/1163/Screen-Shot-2019-03-12-at-08_57_54.png

这些是RGB的低两位,显示屏这些位接地就行了。

离线

#11 2019-03-12 09:22:56

Gentlepig
会员
注册时间: 2018-10-24
累计积分: 230

Re: 哪款芯片能同时接摄像头和LCD?

用mipi接口的摄像头不行吗?
嘉立创不接受来料加工吧?还有,嘉利创SMT接收BGA封装的吗?

离线

#12 2019-03-12 09:38:11

dgtg
会员
注册时间: 2017-11-08
累计积分: 129

Re: 哪款芯片能同时接摄像头和LCD?

微凉VeiLiang 说:
Quotation 说:
微凉VeiLiang 说:

F1C100S接口不冲突,低两位才和摄像头共用引脚,不像v3s

从datasheet上看这几位都是和CSI冲突的,LCD的这几位实际用不到吗?

https://whycan.cn/files/members/1163/Screen-Shot-2019-03-12-at-08_57_54.png

这些是RGB的低两位,显示屏这些位接地就行了。

微微凉正解!RGB666的接法,低两位也还可以并接到高两位。

离线

#13 2019-03-12 09:39:26

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 8,175

Re: 哪款芯片能同时接摄像头和LCD?

看下 荔枝派 nano 的原理图.pdf

LCD用了 RGB666 模式, 没有用 PE0 - PE5, 可以留给 CSI-DVP 摄像头用。

离线

#14 2019-03-12 09:46:11

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

Re: 哪款芯片能同时接摄像头和LCD?

懂了,谢谢各位!不用很高级的屏幕,RGB666够了。

离线

#15 2019-03-12 09:58:37

山无棱
会员
注册时间: 2017-10-23
累计积分: 116

Re: 哪款芯片能同时接摄像头和LCD?

Quotation 说:

懂了,谢谢各位!不用很高级的屏幕,RGB666够了。

坐等大神把 C100 的 DVP 摄像头调通。

离线

#16 2019-03-12 13:28:09

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

Re: 哪款芯片能同时接摄像头和LCD?

山无棱 说:
Quotation 说:

懂了,谢谢各位!不用很高级的屏幕,RGB666够了。

坐等大神把 C100 的 DVP 摄像头调通。

DVP摄像头已经在XBoot上调通了。不过我只做了我目前需要的功能,代码不通用。所以先不分享了。

离线

#17 2019-03-12 19:57:39

九霄云外
会员
注册时间: 2019-01-09
累计积分: 60

Re: 哪款芯片能同时接摄像头和LCD?

F1C100S其实只支持666,不支持888的

离线

#18 2019-06-10 20:13:21

tianjjff
会员
注册时间: 2018-12-24
累计积分: 27

Re: 哪款芯片能同时接摄像头和LCD?

Quotation 说:
山无棱 说:
Quotation 说:

懂了,谢谢各位!不用很高级的屏幕,RGB666够了。

坐等大神把 C100 的 DVP 摄像头调通。

DVP摄像头已经在XBoot上调通了。不过我只做了我目前需要的功能,代码不通用。所以先不分享了。

DVP驱动可否参考一下,正在驱动摄像头

离线

#19 2019-06-10 23:25:51

Quotation
会员
注册时间: 2018-10-04
累计积分: 113

Re: 哪款芯片能同时接摄像头和LCD?

tianjjff 说:

DVP驱动可否参考一下,正在驱动摄像头

CSI部分驱动如下。没有考虑什么通用性,只是针对我需要的数据格式。(UYVY -> YUV422)
只有捕捉单张图像,没有视频。

/*
 * driver/csi-f1c100s.c
 */

#include <xboot.h>
#include <clk/clk.h>
#include <reset/reset.h>
#include <gpio/gpio.h>
#include <csi/csi.h>

enum {
    CSI_EN				= 0x000,
    CSI_CFG				= 0x004,
    CSI_CAP 			= 0x008,
    CSI_SCALE			= 0x00c,
    CSI_FIFO0_BUFA		= 0x010,
    CSI_FIFO0_BUFB		= 0x014,
    CSI_FIFO1_BUFA		= 0x018,
    CSI_FIFO1_BUFB		= 0x01c,
    CSI_FIFO2_BUFA		= 0x020,
    CSI_FIFO2_BUFB		= 0x024,
    CSI_BUF_CTL			= 0x028,
    CSI_BUF_STA			= 0x02c,
    CSI_INT_EN			= 0x030,
    CSI_INT_STA			= 0x034,
    CSI_HSIZE			= 0x040,
    CSI_VSIZE			= 0x044,
    CSI_BUF_LEN			= 0x048,
};

enum {
    CSI_SIZE_MASK		= 0x1fff,	// 13 bits
};

struct csi_f1c100s_pdata_t {
    virtual_addr_t virt;
    char * clk;
    char * dramclk;
    int reset;
    int hsync;
    int hsynccfg;
    int vsync;
    int vsynccfg;
    int pclk;
    int pclkcfg;
    int database;
    int datacfg;
    int databits;
};

static void csi_f1c100s_get_size(struct csi_t * csi, int* width, int* height)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    if (width) {
        *width = (read32(pdat->virt + CSI_HSIZE) >> 16) & CSI_SIZE_MASK;
    }
    if (height) {
        *height = (read32(pdat->virt + CSI_VSIZE) >> 16) & CSI_SIZE_MASK;
    }
}

static void csi_f1c100s_set_size(struct csi_t * csi, int width, int height)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    uint32_t hsize = read32(pdat->virt + CSI_HSIZE);
    hsize &= ~(CSI_SIZE_MASK << 16) & ~(CSI_SIZE_MASK << 0);
    hsize |= ((width * 2) & CSI_SIZE_MASK) << 16;  // YUV每像素2字节
    write32(pdat->virt + CSI_HSIZE, hsize);

    uint32_t vsize = read32(pdat->virt + CSI_VSIZE);
    vsize &= ~(CSI_SIZE_MASK << 16) & ~(CSI_SIZE_MASK << 0);
    vsize |= (height & CSI_SIZE_MASK) << 16;
    write32(pdat->virt + CSI_VSIZE, vsize);

    // buffer len
    uint32_t buflen = read32(pdat->virt + CSI_BUF_LEN);
    buflen &= ~(CSI_SIZE_MASK << 0);
    buflen |= (width & CSI_SIZE_MASK);  // Y最长,每像素1字节
    write32(pdat->virt + CSI_BUF_LEN, buflen);
}

static void csi_f1c100s_set_buffer(struct csi_t * csi, void* buffer, int len)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    // 只用BUFA,3个FIFO必须都设置上
    write32(pdat->virt + CSI_FIFO0_BUFA, (uint32_t)buffer);
    write32(pdat->virt + CSI_FIFO1_BUFA, (uint32_t)buffer + len * 2 / 4);
    write32(pdat->virt + CSI_FIFO2_BUFA, (uint32_t)buffer + len * 3 / 4);
    write32(pdat->virt + CSI_BUF_CTL, read32(pdat->virt + CSI_BUF_CTL) & ~(1 << 0));
}

static int csi_f1c100s_capture_still(struct csi_t * csi)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    // begin capture
    write32(pdat->virt + CSI_CAP, read32(pdat->virt + CSI_CAP) | (1 << 0));
    // clear int status
    write32(pdat->virt + CSI_INT_STA, read32(pdat->virt + CSI_INT_STA));

    // wait for capture start then stop
    ktime_t timeout = ktime_add_ms(ktime_get(), 2000);
    int captured = 0;
    do {
        if(read32(pdat->virt + CSI_INT_STA) & (1 << 0)) {
            captured = 1;
            break;
        }
    } while(ktime_before(ktime_get(), timeout));

    return captured;
}

static struct device_t * csi_f1c100s_probe(struct driver_t * drv, struct dtnode_t * n)
{
    struct csi_f1c100s_pdata_t * pdat;
    struct csi_t * csi;
    struct device_t * dev;
    virtual_addr_t virt = phys_to_virt(dt_read_address(n));
    char * clk = dt_read_string(n, "clock-name", NULL);
    char * dramclk = dt_read_string(n, "dram-clock-name", NULL);

    pdat = malloc(sizeof(struct csi_f1c100s_pdata_t));
    if(!pdat)
        return FALSE;

    csi = malloc(sizeof(struct csi_t));
    if(!csi)
    {
        free(pdat);
        return FALSE;
    }

    pdat->virt = virt;
    pdat->clk = strdup(clk);
    pdat->dramclk = strdup(dramclk);
    pdat->reset = dt_read_int(n, "reset", -1);
    pdat->hsync = dt_read_int(n, "hsync-gpio", -1);
    pdat->hsynccfg = dt_read_int(n, "hsync-gpio-config", -1);
    pdat->vsync = dt_read_int(n, "vsync-gpio", -1);
    pdat->vsynccfg = dt_read_int(n, "vsync-gpio-config", -1);
    pdat->pclk = dt_read_int(n, "pclk-gpio", -1);
    pdat->pclkcfg = dt_read_int(n, "pclk-gpio-config", -1);
    pdat->database = dt_read_int(n, "data-gpio-base", -1);
    pdat->datacfg = dt_read_int(n, "data-gpio-config", -1);
    pdat->databits = dt_read_int(n, "data-bits", -1);

    csi->name = alloc_device_name(dt_read_name(n), -1);
    csi->get_size = csi_f1c100s_get_size;
    csi->set_size = csi_f1c100s_set_size;
    csi->set_buffer = csi_f1c100s_set_buffer;
    csi->capture_still = csi_f1c100s_capture_still;
    csi->priv = pdat;

    clk_enable(pdat->clk);
    clk_enable(pdat->dramclk);
    if(pdat->reset >= 0) {
        reset_deassert(pdat->reset);
    }
    if(pdat->hsync >= 0) {
        if(pdat->hsynccfg >= 0) {
            gpio_set_cfg(pdat->hsync, pdat->hsynccfg);
        }
        gpio_set_pull(pdat->hsync, GPIO_PULL_UP);
    }
    if(pdat->vsync >= 0) {
        if(pdat->vsynccfg >= 0) {
            gpio_set_cfg(pdat->vsync, pdat->vsynccfg);
        }
        gpio_set_pull(pdat->vsync, GPIO_PULL_UP);
    }
    if(pdat->pclk >= 0) {
        if(pdat->pclkcfg >= 0) {
            gpio_set_cfg(pdat->pclk, pdat->pclkcfg);
        }
        gpio_set_pull(pdat->pclk, GPIO_PULL_UP);
    }
    if (pdat->database) {
        for (int i = 0; i < pdat->databits; i++) {
            if(pdat->datacfg >= 0) {
                gpio_set_cfg(pdat->database + i, pdat->datacfg);
            }
            gpio_set_pull(pdat->database + i, GPIO_PULL_UP);
        }
    }

    // input format: YUV422
    // input sequence: UYVY
    // output format: planar YUV 422
    // vref polarity: high
    // href polarity: low
    // pclk polarity: high
    write32(pdat->virt + CSI_CFG,
            (3 << 20) | (0 << 16) | (2 << 8)  // YUV
            | (1 << 2) | (1 << 1) | (0 << 0));
    write32(pdat->virt + CSI_EN, read32(pdat->virt + CSI_EN) | (1 << 0));

    if(!register_csi(&dev, csi))
    {
        clk_disable(pdat->clk);
        free(pdat->clk);

        clk_disable(pdat->dramclk);
        free(pdat->dramclk);

        free_device_name(csi->name);
        free(csi->priv);
        free(csi);
        return NULL;
    }
    dev->driver = drv;

    return dev;
}

static void csi_f1c100s_remove(struct device_t * dev)
{
    struct csi_t * csi = (struct csi_t *)dev->priv;
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    if(csi && unregister_csi(csi))
    {
        clk_disable(pdat->clk);
        free(pdat->clk);

        clk_disable(pdat->dramclk);
        free(pdat->dramclk);

        free_device_name(csi->name);
        free(csi->priv);
        free(csi);
    }
}

static void csi_f1c100s_suspend(struct device_t * dev)
{
}

static void csi_f1c100s_resume(struct device_t * dev)
{
}

static struct driver_t csi_f1c100s = {
    .name		= "csi-f1c100s",
    .probe		= csi_f1c100s_probe,
    .remove		= csi_f1c100s_remove,
    .suspend	= csi_f1c100s_suspend,
    .resume		= csi_f1c100s_resume,
};

static __init void csi_f1c100s_driver_init(void)
{
    register_driver(&csi_f1c100s);
}

static __exit void csi_f1c100s_driver_exit(void)
{
    unregister_driver(&csi_f1c100s);
}

driver_initcall(csi_f1c100s_driver_init);
driver_exitcall(csi_f1c100s_driver_exit);

以下为SCCB部分,SCCB只是I2C的特例,所以就在I2C驱动里加了2个函数:

int i2c_sccb_write(const struct i2c_device_t * dev, uint8_t reg, uint8_t data)
{
	uint8_t msg_data[2] = { reg, data };
	struct i2c_msg_t msg[1];

	msg[0].addr = dev->addr;
	msg[0].flags = 0;
	msg[0].len = 2;
	msg[0].buf = msg_data;

	int ret = i2c_transfer(dev->i2c, msg, 1);
	return (ret == 1) ? 1 : 0;
}

int i2c_sccb_read(const struct i2c_device_t * dev, uint8_t reg, uint8_t* out)
{
	uint8_t msg_data[2] = { reg, 0xee };
	struct i2c_msg_t msg[2];

	// write address
	msg[0].addr = dev->addr;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = msg_data;

	// read back
	msg[1].addr = dev->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = 1;
	msg[1].buf = msg_data + 1;

  	int ret = i2c_transfer(dev->i2c, msg, 2);
  	if (ret == 2) {
  		*out = msg_data[1];
  		return 1;
  	} else {
  		return 0;
  	}
}

离线

#20 2019-06-11 10:10:52

晕哥
Administrator
注册时间: 2017-09-06
累计积分: 8,175

Re: 哪款芯片能同时接摄像头和LCD?

多谢 @Quotation 分享

离线

#21 2019-06-11 10:25:52

tianjjff
会员
注册时间: 2018-12-24
累计积分: 27

Re: 哪款芯片能同时接摄像头和LCD?

Quotation 说:
tianjjff 说:

DVP驱动可否参考一下,正在驱动摄像头

CSI部分驱动如下。没有考虑什么通用性,只是针对我需要的数据格式。(UYVY -> YUV422)
只有捕捉单张图像,没有视频。

/*
 * driver/csi-f1c100s.c
 */

#include <xboot.h>
#include <clk/clk.h>
#include <reset/reset.h>
#include <gpio/gpio.h>
#include <csi/csi.h>

enum {
    CSI_EN				= 0x000,
    CSI_CFG				= 0x004,
    CSI_CAP 			= 0x008,
    CSI_SCALE			= 0x00c,
    CSI_FIFO0_BUFA		= 0x010,
    CSI_FIFO0_BUFB		= 0x014,
    CSI_FIFO1_BUFA		= 0x018,
    CSI_FIFO1_BUFB		= 0x01c,
    CSI_FIFO2_BUFA		= 0x020,
    CSI_FIFO2_BUFB		= 0x024,
    CSI_BUF_CTL			= 0x028,
    CSI_BUF_STA			= 0x02c,
    CSI_INT_EN			= 0x030,
    CSI_INT_STA			= 0x034,
    CSI_HSIZE			= 0x040,
    CSI_VSIZE			= 0x044,
    CSI_BUF_LEN			= 0x048,
};

enum {
    CSI_SIZE_MASK		= 0x1fff,	// 13 bits
};

struct csi_f1c100s_pdata_t {
    virtual_addr_t virt;
    char * clk;
    char * dramclk;
    int reset;
    int hsync;
    int hsynccfg;
    int vsync;
    int vsynccfg;
    int pclk;
    int pclkcfg;
    int database;
    int datacfg;
    int databits;
};

static void csi_f1c100s_get_size(struct csi_t * csi, int* width, int* height)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    if (width) {
        *width = (read32(pdat->virt + CSI_HSIZE) >> 16) & CSI_SIZE_MASK;
    }
    if (height) {
        *height = (read32(pdat->virt + CSI_VSIZE) >> 16) & CSI_SIZE_MASK;
    }
}

static void csi_f1c100s_set_size(struct csi_t * csi, int width, int height)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    uint32_t hsize = read32(pdat->virt + CSI_HSIZE);
    hsize &= ~(CSI_SIZE_MASK << 16) & ~(CSI_SIZE_MASK << 0);
    hsize |= ((width * 2) & CSI_SIZE_MASK) << 16;  // YUV每像素2字节
    write32(pdat->virt + CSI_HSIZE, hsize);

    uint32_t vsize = read32(pdat->virt + CSI_VSIZE);
    vsize &= ~(CSI_SIZE_MASK << 16) & ~(CSI_SIZE_MASK << 0);
    vsize |= (height & CSI_SIZE_MASK) << 16;
    write32(pdat->virt + CSI_VSIZE, vsize);

    // buffer len
    uint32_t buflen = read32(pdat->virt + CSI_BUF_LEN);
    buflen &= ~(CSI_SIZE_MASK << 0);
    buflen |= (width & CSI_SIZE_MASK);  // Y最长,每像素1字节
    write32(pdat->virt + CSI_BUF_LEN, buflen);
}

static void csi_f1c100s_set_buffer(struct csi_t * csi, void* buffer, int len)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    // 只用BUFA,3个FIFO必须都设置上
    write32(pdat->virt + CSI_FIFO0_BUFA, (uint32_t)buffer);
    write32(pdat->virt + CSI_FIFO1_BUFA, (uint32_t)buffer + len * 2 / 4);
    write32(pdat->virt + CSI_FIFO2_BUFA, (uint32_t)buffer + len * 3 / 4);
    write32(pdat->virt + CSI_BUF_CTL, read32(pdat->virt + CSI_BUF_CTL) & ~(1 << 0));
}

static int csi_f1c100s_capture_still(struct csi_t * csi)
{
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    // begin capture
    write32(pdat->virt + CSI_CAP, read32(pdat->virt + CSI_CAP) | (1 << 0));
    // clear int status
    write32(pdat->virt + CSI_INT_STA, read32(pdat->virt + CSI_INT_STA));

    // wait for capture start then stop
    ktime_t timeout = ktime_add_ms(ktime_get(), 2000);
    int captured = 0;
    do {
        if(read32(pdat->virt + CSI_INT_STA) & (1 << 0)) {
            captured = 1;
            break;
        }
    } while(ktime_before(ktime_get(), timeout));

    return captured;
}

static struct device_t * csi_f1c100s_probe(struct driver_t * drv, struct dtnode_t * n)
{
    struct csi_f1c100s_pdata_t * pdat;
    struct csi_t * csi;
    struct device_t * dev;
    virtual_addr_t virt = phys_to_virt(dt_read_address(n));
    char * clk = dt_read_string(n, "clock-name", NULL);
    char * dramclk = dt_read_string(n, "dram-clock-name", NULL);

    pdat = malloc(sizeof(struct csi_f1c100s_pdata_t));
    if(!pdat)
        return FALSE;

    csi = malloc(sizeof(struct csi_t));
    if(!csi)
    {
        free(pdat);
        return FALSE;
    }

    pdat->virt = virt;
    pdat->clk = strdup(clk);
    pdat->dramclk = strdup(dramclk);
    pdat->reset = dt_read_int(n, "reset", -1);
    pdat->hsync = dt_read_int(n, "hsync-gpio", -1);
    pdat->hsynccfg = dt_read_int(n, "hsync-gpio-config", -1);
    pdat->vsync = dt_read_int(n, "vsync-gpio", -1);
    pdat->vsynccfg = dt_read_int(n, "vsync-gpio-config", -1);
    pdat->pclk = dt_read_int(n, "pclk-gpio", -1);
    pdat->pclkcfg = dt_read_int(n, "pclk-gpio-config", -1);
    pdat->database = dt_read_int(n, "data-gpio-base", -1);
    pdat->datacfg = dt_read_int(n, "data-gpio-config", -1);
    pdat->databits = dt_read_int(n, "data-bits", -1);

    csi->name = alloc_device_name(dt_read_name(n), -1);
    csi->get_size = csi_f1c100s_get_size;
    csi->set_size = csi_f1c100s_set_size;
    csi->set_buffer = csi_f1c100s_set_buffer;
    csi->capture_still = csi_f1c100s_capture_still;
    csi->priv = pdat;

    clk_enable(pdat->clk);
    clk_enable(pdat->dramclk);
    if(pdat->reset >= 0) {
        reset_deassert(pdat->reset);
    }
    if(pdat->hsync >= 0) {
        if(pdat->hsynccfg >= 0) {
            gpio_set_cfg(pdat->hsync, pdat->hsynccfg);
        }
        gpio_set_pull(pdat->hsync, GPIO_PULL_UP);
    }
    if(pdat->vsync >= 0) {
        if(pdat->vsynccfg >= 0) {
            gpio_set_cfg(pdat->vsync, pdat->vsynccfg);
        }
        gpio_set_pull(pdat->vsync, GPIO_PULL_UP);
    }
    if(pdat->pclk >= 0) {
        if(pdat->pclkcfg >= 0) {
            gpio_set_cfg(pdat->pclk, pdat->pclkcfg);
        }
        gpio_set_pull(pdat->pclk, GPIO_PULL_UP);
    }
    if (pdat->database) {
        for (int i = 0; i < pdat->databits; i++) {
            if(pdat->datacfg >= 0) {
                gpio_set_cfg(pdat->database + i, pdat->datacfg);
            }
            gpio_set_pull(pdat->database + i, GPIO_PULL_UP);
        }
    }

    // input format: YUV422
    // input sequence: UYVY
    // output format: planar YUV 422
    // vref polarity: high
    // href polarity: low
    // pclk polarity: high
    write32(pdat->virt + CSI_CFG,
            (3 << 20) | (0 << 16) | (2 << 8)  // YUV
            | (1 << 2) | (1 << 1) | (0 << 0));
    write32(pdat->virt + CSI_EN, read32(pdat->virt + CSI_EN) | (1 << 0));

    if(!register_csi(&dev, csi))
    {
        clk_disable(pdat->clk);
        free(pdat->clk);

        clk_disable(pdat->dramclk);
        free(pdat->dramclk);

        free_device_name(csi->name);
        free(csi->priv);
        free(csi);
        return NULL;
    }
    dev->driver = drv;

    return dev;
}

static void csi_f1c100s_remove(struct device_t * dev)
{
    struct csi_t * csi = (struct csi_t *)dev->priv;
    struct csi_f1c100s_pdata_t * pdat = (struct csi_f1c100s_pdata_t *)csi->priv;

    if(csi && unregister_csi(csi))
    {
        clk_disable(pdat->clk);
        free(pdat->clk);

        clk_disable(pdat->dramclk);
        free(pdat->dramclk);

        free_device_name(csi->name);
        free(csi->priv);
        free(csi);
    }
}

static void csi_f1c100s_suspend(struct device_t * dev)
{
}

static void csi_f1c100s_resume(struct device_t * dev)
{
}

static struct driver_t csi_f1c100s = {
    .name		= "csi-f1c100s",
    .probe		= csi_f1c100s_probe,
    .remove		= csi_f1c100s_remove,
    .suspend	= csi_f1c100s_suspend,
    .resume		= csi_f1c100s_resume,
};

static __init void csi_f1c100s_driver_init(void)
{
    register_driver(&csi_f1c100s);
}

static __exit void csi_f1c100s_driver_exit(void)
{
    unregister_driver(&csi_f1c100s);
}

driver_initcall(csi_f1c100s_driver_init);
driver_exitcall(csi_f1c100s_driver_exit);

以下为SCCB部分,SCCB只是I2C的特例,所以就在I2C驱动里加了2个函数:

int i2c_sccb_write(const struct i2c_device_t * dev, uint8_t reg, uint8_t data)
{
	uint8_t msg_data[2] = { reg, data };
	struct i2c_msg_t msg[1];

	msg[0].addr = dev->addr;
	msg[0].flags = 0;
	msg[0].len = 2;
	msg[0].buf = msg_data;

	int ret = i2c_transfer(dev->i2c, msg, 1);
	return (ret == 1) ? 1 : 0;
}

int i2c_sccb_read(const struct i2c_device_t * dev, uint8_t reg, uint8_t* out)
{
	uint8_t msg_data[2] = { reg, 0xee };
	struct i2c_msg_t msg[2];

	// write address
	msg[0].addr = dev->addr;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = msg_data;

	// read back
	msg[1].addr = dev->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = 1;
	msg[1].buf = msg_data + 1;

  	int ret = i2c_transfer(dev->i2c, msg, 2);
  	if (ret == 2) {
  		*out = msg_data[1];
  		return 1;
  	} else {
  		return 0;
  	}
}

多谢大神,谢谢分享!!!@Quotation

离线

#22 2019-06-11 14:55:18

微凉VeiLiang
会员
注册时间: 2018-10-28
累计积分: 164

Re: 哪款芯片能同时接摄像头和LCD?

感谢分享

离线

#23 2019-10-28 15:21:18

zenghaibo
会员
注册时间: 2019-07-15
累计积分: 26

Re: 哪款芯片能同时接摄像头和LCD?

感谢,分享。

离线

#24 2019-10-28 15:22:07

zenghaibo
会员
注册时间: 2019-07-15
累计积分: 26

Re: 哪款芯片能同时接摄像头和LCD?

请问下这个文件在哪里可以下载到,

zenghaibo 说:

感谢,分享。

离线

#25 2019-10-28 18:23:47

mango
会员
注册时间: 2017-12-02
累计积分: 368

Re: 哪款芯片能同时接摄像头和LCD?

TQFP128封装的R11可以。手册坛子里应该也有了。
https://widora.io/zh/r11

离线

页脚