📄 adcm2650_hw.c
字号:
/* * mt9d011_hw.c * * mt9d011 Camera Module driver. * * Copyright (C) 2005, Nanwang Corporation * * Author: nanwang Inc. * yulu * * */ #include <linux/types.h>#include <asm/mach-types.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/hardware.h>#include <asm/mach-types.h>#include <asm/dma.h>#include <asm/irq.h>#include <linux/types.h>#include <linux/module.h>#include <linux/init.h>#include <linux/wrapper.h>#include <linux/delay.h>#include <linux/i2c.h>#include "adcm2650_hw.h"#include "pxa_camera.h"void adcm2650_wait( int ms ){ mdelay( ms );}/****************************************************************************** ** I2C Management ** ******************************************************************************/void i2c_init(void){ //reset = 0 ,udelay GPCR0 |= (1<<11); udelay(20); nw_set_clock(1,1,7); udelay(20); //reset = 1 GPSR0 |= (1<<11); //iic_test(); //configure i2c communication nw_i2c_init(); //initialize camera sensor registers nw_camera_init(); printk("\n yul adcm2650_hw:i2c init ok!!!");}void i2c_deinit(void){ }//初始化camera sensor 的寄存器int nw_camera_init(void){ u16 value = 0; u16 regValue = 0; int i; //reset mcu adcm2650_write(PAGE_REG, 1); adcm2650_write(0xc3,0x0001); mdelay(10); adcm2650_write(0xc3,0x0000); adcm2650_write(PAGE_REG, 0); adcm2650_write(RESET, 0x1); mdelay(10); adcm2650_write(RESET, 0x0); // for(i=0;i<100;i++)// udelay(1000); mdelay(10);#if 0 /*pll registers*/ //program pll adcm2650_write(PLL_CTRL_1, 0x1000); //m 0x28 n 0x9 adcm2650_write(PLL_CTRL_2, 0x0002); //p 0x2 //power up pll adcm2650_write(CLK_CTRL, 0xa000); //use pll udelay(300); adcm2650_write(CLK_CTRL, 0x2000); //use pll printk("\n p0 PLL_CTRL_1 = 0x%x",adcm2650_read(PLL_CTRL_1,®Value)); printk("\n p0 PLL_CTRL_2 = 0x%x",adcm2650_read(PLL_CTRL_2,®Value)); printk("\n p0 CLK_CTRL = 0x%x",adcm2650_read(CLK_CTRL,®Value));#endif /*context A, PREVIEW*/ var_write8(1,0x20,0x0000);//SEQ_CAP_MODE var_write8(1,0x03,0x0001);//SEQ_CMD #if 0 /*resize contextA 240*320*/ var_write16(7,0x27,0x0000);//MODE_CROP_X0_A var_write16(7,0x29,0x0320);//MODE_CROP_X1_A var_write16(7,0x2b,0x0000);//MODE_CROP_Y0_A var_write16(7,0x2d,0x0258);//MODE_CROP_Y1_A var_write16(7,0x03,0x00f0);//MODE_OUTPUT_WIDTH_A var_write16(7,0x05,0x0140);//MODE_OUTPUT_HEIGHT_A var_write8(1,0x03,0x0005);//SEQ_CMD mdelay(100);#endif /*resize*/ adcm2650_write(PAGE_REG, 1); adcm2650_write(0xC6, 0x2727);//MODE_CROP_X0_A adcm2650_write(0xC8, 0x0); //MODE_CROP_X0_A adcm2650_write(0xC6, 0x2729);//MODE_CROP_X1_A adcm2650_write(0xC8, 0x0320);//MODE_CROP_X1_A adcm2650_write(0xC6, 0x272B);//MODE_CROP_Y0_A adcm2650_write(0xC8, 0x0000);//MODE_CROP_Y0_A adcm2650_write(0xC6, 0x272D);//MODE_CROP_Y1_A adcm2650_write(0xC8, 0x0258);//MODE_CROP_Y1_A adcm2650_write(0xC6, 0x2703);//MODE_OUTPUT_WIDTH_A adcm2650_write(0xC8, 0x00f0);//MODE_OUTPUT_WIDTH_A adcm2650_write(0xC6, 0x2705);//MODE_OUTPUT_HEIGHT_A adcm2650_write(0xC8, 0x0140);//MODE_OUTPUT_HEIGHT_A adcm2650_write(0xC6, 0xA103);//SEQ_CMD adcm2650_write(0xC8, 0x0005);//SEQ_CMD #if 0 //yuv420 output adcm2650_read(0x15,®Value); printk("\n yuv 420 = 0x%x",regValue); regValue |= 1<<4; adcm2650_write(0x15, regValue);//YUV420 ENABLE //printk("\n yuv 420 = 0x%x",regValue); //printk("\n yuv 420 = 0x%x",adcm2650_read(0x15,®Value)); #endif#if 0 /*disable cr ab */ adcm2650_read(0x98,®Value); regValue |= 0x05; adcm2650_write(0x98, regValue); adcm2650_write(0x97,0x20); var_write16(7,0x7F,0x6443);//MODE_SPEC_EFFECTS_A var_write8(1,0x03,0x0005);//SEQ_CMD refresh adcm2650_write(PAGE_REG,0x1); adcm2650_write(0xA4, 0x6441); /************print size related reg&VAR****************/ adcm2650_write(PAGE_REG,0x1); printk("\n weight x = 0x%x",adcm2650_read(0x16,®Value)); printk("\n weight y = 0x%x",adcm2650_read(0x17,®Value)); adcm2650_write(PAGE_REG,0x0); printk("\n p0 ROW_WIDTH = 0x%x",adcm2650_read(ROW_WIDTH,®Value)); printk("\n p0 COL_WIDTH = 0x%x",adcm2650_read(COL_WIDTH,®Value)); printk("\n p0 0x0D = 0x%x",adcm2650_read(0x0D,®Value)); adcm2650_write(PAGE_REG,0x2); printk("\n p2,0x16 = 0x%x",adcm2650_read(0x16,®Value)); printk("\n p2,0x17 = 0x%x",adcm2650_read(0x17,®Value)); printk("\n p2,0x10 = 0x%x",adcm2650_read(0x10,®Value)); printk("\n p2,0x11 = 0x%x",adcm2650_read(0x11,®Value)); /************print mode related reg&VAR****************/ adcm2650_write(PAGE_REG,0x0); printk("\n p0 CONTEXT CONTROL = 0x%x",adcm2650_read(0xF2,®Value)); adcm2650_write(PAGE_REG,0x1); printk("\n p1 0XC3 MCU RESET = 0x%x",adcm2650_read(0xC3,®Value)); /************print effect related reg&VAR****************/ adcm2650_write(PAGE_REG,0x1); printk("\n p0 0xA4 Special Effect= 0x%x",adcm2650_read(0xA4,®Value)); printk("\n 7,0x7F Spec_effects_A= 0x%x",var_read16(7,0x7F)); /*************SFP REG VALUE******/ adcm2650_write(PAGE_REG,0x1); adcm2650_write(198,0x9046); printk("\n SFP LineCnt 0x1046 = 0x%x",adcm2650_read(200,®Value)); adcm2650_write(198,0x9047); printk("\n SFP LineCnt 0x1047 = 0x%x",adcm2650_read(200,®Value)); adcm2650_write(198,0x1048); printk("\n SFP ClockCnt 0x1048/9= 0x%x",adcm2650_read(200,®Value)); adcm2650_write(198,0x104A); printk("\n SFP ClockCnt 0x104A/B= 0x%x",adcm2650_read(200,®Value)); adcm2650_write(PAGE_REG,0x0); printk("\n CHIP_VER = 0x%x",adcm2650_read(CHIP_VER,®Value)); printk("\n G1_GAIN = 0x%x",adcm2650_read(G1_GAIN,®Value)); printk("\n B_GAIN = 0x%x",adcm2650_read(B_GAIN,®Value)); printk("\n R_GAIN = 0x%x",adcm2650_read(R_GAIN,®Value)); printk("\n G2_GAIN = 0x%x",adcm2650_read(G2_GAIN,®Value)); printk("\n PLL_CTRL_1 = 0x%x",adcm2650_read(PLL_CTRL_1,®Value)); printk("\n PLL_CTRL_2 = 0x%x",adcm2650_read(PLL_CTRL_2,®Value)); printk("\n CLK_CTRL = 0x%x",adcm2650_read(CLK_CTRL,®Value)); printk("\n ROW_START = 0x%x",adcm2650_read(ROW_START,®Value)); printk("\n COL_START = 0x%x",adcm2650_read(COL_START,®Value)); printk("\n ROW_WIDTH = 0x%x",adcm2650_read(ROW_WIDTH,®Value)); printk("\n COL_WIDTH = 0x%x",adcm2650_read(COL_WIDTH,®Value)); printk("\n SHUT_WIDTH = 0x%x",adcm2650_read(SHUT_WIDTH,®Value)); printk("\n 0XF2 = 0x%x",adcm2650_read(0xF2,®Value)); printk("\n 0X21 = 0x%x",adcm2650_read(0x21,®Value)); adcm2650_write(PAGE_REG,0x1); printk("\n 0XA4 = 0x%x",adcm2650_read(0xA4,®Value)); printk("\n 7,0x03 = 0x%x",var_read16(7,0x03)); printk("\n 7,0x05 = 0x%x",var_read16(7,0x05)); printk("\n 7,0x27 = 0x%x",var_read16(7,0x27)); printk("\n 7,0x29 = 0x%x",var_read16(7,0x29)); printk("\n 7,0x2b = 0x%x",var_read16(7,0x2b)); printk("\n 7,0x2d = 0x%x",var_read16(7,0x2d)); printk("\n 7,0x79 = 0x%x",var_read16(7,0x79)); printk("\n 7,0x7b = 0x%x",var_read16(7,0x7b)); printk("\n 7,0x37 = 0x%x",var_read16(7,0x37)); printk("\n 7,0x3b = 0x%x",var_read16(7,0x3b)); printk("\n 7,0x7F = 0x%x",var_read16(7,0x7F)); printk("\n 7,0x02 = 0x%x",var_read8(7,0x02)); printk("\n 1,0x03 = 0x%x",var_read8(1,0x03)); printk("\n 1,0x20 = 0x%x",var_read8(1,0x20)); printk("\n 1,0x04 = 0x%x",var_read8(1,0x04)); printk("\n 1,0x07 = 0x%x",var_read8(1,0x07)); printk("\n 1,0x08 = 0x%x",var_read8(1,0x08)); printk("\n 1,0x09 = 0x%x",var_read8(1,0x09)); printk("\n p1,0x97 = 0x%x",adcm2650_read(0x97,®Value)); adcm2650_write(PAGE_REG,0x2); printk("\n p2,0x16 = 0x%x",adcm2650_read(0x16,®Value)); printk("\n p2,0x17 = 0x%x",adcm2650_read(0x17,®Value)); #endif return 0;}int adcm2650_set_size( adcm_window_size * window ){ if((window->height > 1600) || ( window->width > 1200)) { printk("\n adcm2650_hw: window is out of the max!!!"); return ADCM_ERR_PARAMETER; } adcm2650_write(PAGE_REG, 0); //input row width adcm2650_write(ROW_WIDTH, window->height); //input col width adcm2650_write(COL_WIDTH, window->width); //row start,column start /*adcm2650_write(ROW_START, 0x1c); adcm2650_write(COL_START, 0x3c);*/ return ADCM_ERR_NONE;}/*i2c的读写接口*/int adcm2650_read(u16 addr, u16 *pvalue){ u16 res = 0; res = iic_read(READ_SLAVE_ADDR,addr); *pvalue = (u16)res; return res;}int adcm2650_write(u16 addr, u16 value){ return iic_write(WRITE_SLAVE_ADDR,addr, value);}#if 1int var_write16(u8 id, u16 offset, u16 value){ adcm2650_write(PAGE_REG,0x1); adcm2650_write(VAR_ADDR,((id<<8) | offset | VAR_LOGIC_ACCESS )); adcm2650_write(VAR_DATA,value);}int var_write8(u8 id, u16 offset, u16 value){ adcm2650_write(PAGE_REG,0x1); adcm2650_write(VAR_ADDR,((id<<8) | offset | VAR_LOGIC_ACCESS | VAR_8_ACCESS)); adcm2650_write(VAR_DATA,value);}int var_read8(u8 id, u16 offset){ u16 value; adcm2650_write(PAGE_REG,0x1); adcm2650_write(VAR_ADDR,((id<<8) | offset | VAR_LOGIC_ACCESS | VAR_8_ACCESS)); adcm2650_read(VAR_DATA,&value); return value;}int var_read16(u8 id, u16 offset ){ u16 value; adcm2650_write(PAGE_REG,0x1); adcm2650_write(VAR_ADDR,((id<<8) | offset | VAR_LOGIC_ACCESS)); adcm2650_read(VAR_DATA,&value); return value;}#endif/*配置i2c初始化*/static int nw_i2c_init(){ //printk("\nnanwang iic init here\n"); CKEN |= CKEN14_I2C; set_GPIO_mode(117 | GPIO_ALT_FN_1_IN); set_GPIO_mode(118 | GPIO_ALT_FN_1_IN); ICR |= ICR_UR; udelay(1000); ICR &= ~ICR_UR; udelay(1000); ICR &= ~ICR_IUE; ISAR = 0xff; ISR = 0; ICR = ICR_IUE | ICR_SCLE | ICR_GCD; udelay(100); return 0;}static int iic_read(unsigned char dev_addr,unsigned char reg_addr){ int i; u16 value = 0; unsigned char data1 = 0; unsigned char data2 = 0; //printk(" dev_addr = 0x%x, reg_addr = 0x%x\n",dev_addr,reg_addr); //send start signal and device addr here IDBR = (unsigned int)dev_addr; ICR &= ~(ICR_STOP | ICR_ALDIE | ICR_TB); ICR |= ICR_START | ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); printk("IDBR = 0x%x\n",IDBR); printk("ICR = 0x%x\n",ICR); printk("ISR = 0x%x\n",ISR); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //send slaveaddr here IDBR = (unsigned int)reg_addr; ICR &= ~(ICR_TB | ICR_START | ICR_STOP | ICR_ALDIE); ICR |= ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //send start signal and dev_addr read IDBR = (unsigned int)dev_addr | 0x01; ICR &= ~(ICR_TB | ICR_STOP | ICR_ALDIE); ICR |= ICR_TB | ICR_START; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //init read ICR &= ~(ICR_START | ICR_STOP | ICR_TB | ICR_ACKNAK | ICR_ALDIE); ICR |= ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_IRF) == ISR_IRF) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); } ISR &= ISR_IRF; //while(ISR & ISR_ACKNAK); data1 = (unsigned char)IDBR; ICR &= ~(ICR_STOP | ICR_ACKNAK); udelay(2); ICR &= ~(ICR_START | ICR_TB | ICR_ALDIE | ICR_ACKNAK); ICR |= ICR_TB | ICR_STOP | ICR_ACKNAK; for(i=0;i<0x100000;i++) { if((ISR & ISR_IRF) == ISR_IRF) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); } ISR &= ISR_IRF; //while(ISR & ISR_ACKNAK); data2 = (unsigned char)IDBR; ICR &= ~(ICR_STOP | ICR_ACKNAK); //data = (unsigned char)IDBR | (data << 8); udelay(20); value = (data1 << 8) | data2; return (value);}static int iic_write(unsigned char dev_addr,unsigned char reg_addr,unsigned short value){ int i; u8 data1,data2 = 0; data1 = (value & 0xff00) >> 8; data2 = value & 0xff; //printk("\niic write here dev_addr = 0x%x,reg_addr = 0x%x, data1 = 0x%x, data2 = 0x%x\n",dev_addr,reg_addr,data1,data2);// mdelay(10); for(i=0;i<100;i++) udelay(1000); IDBR = (unsigned int)dev_addr; ICR &= ~(ICR_STOP | ICR_ALDIE | ICR_TB); ICR |= ICR_START | ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //send slaveaddr here IDBR = (unsigned int)reg_addr; ICR &= ~(ICR_TB | ICR_START | ICR_STOP | ICR_ALDIE); ICR |= ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at reg_addr\n"); } //while((ISR & ISR_ITE ) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //send data here IDBR = (unsigned int)data1; ICR &= ~(ICR_TB | ICR_START | ICR_STOP | ICR_ALDIE); ICR |= ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at data1\n"); } //while((ISR & ISR_ITE ) == 0); ISR &= ISR_ITE; //while(PWRISR & ISR_ACKNAK); udelay(2); IDBR = (unsigned int)data2; ICR &= ~(ICR_TB | ICR_START | ICR_ALDIE); ICR |= ICR_TB | ICR_STOP; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at data2\n"); } //while((ISR & ISR_ITE ) == 0); ISR &= ISR_ITE; udelay(20); return 0;}static void nw_set_clock(int pclk_enable, int mclk_enable, unsigned int mclk_khz){ unsigned int ciclk, value, div, cccr_l, K; // determine the LCLK frequency programmed into the CCCR. cccr_l = (CCCR & 0x0000001F); if (cccr_l < 8) K = 1; else if (cccr_l < 17) K = 2; else K = 3; ciclk = (13 * cccr_l) / K; //div = ciclk / ( 2 * mclk_khz ) - 1 ; div = 0; //not div by yul // write cicr4 value = CICR4; value &= ~(CI_CICR4_PCLK_EN | CI_CICR4_MCLK_EN | CI_CICR4_DIV_SMASK<<CI_CICR4_DIV_SHIFT); value |= (pclk_enable) ? CI_CICR4_PCLK_EN : 0; value |= (mclk_enable) ? CI_CICR4_MCLK_EN : 0; value |= div << CI_CICR4_DIV_SHIFT; //value |= 0x2; CICR4 = value; return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -