/* spi write a data frame,type mean command or data 
    3 wire 24 bit SPI interface
*/

static void spi_send_data(unsigned int data)
{
    unsigned int i;

    CS_SET();
    udelay(1);
    CLK_SET();
    TXD_SET();

    CS_CLR();
    udelay(1);

    for (i = 0; i < 24; i++)
    {
        //udelay(1); 
        CLK_CLR();
        udelay(1);
        if (data & 0x00800000) {
            TXD_SET();
        } else {
            TXD_CLR();
        }
        udelay(1);
        CLK_SET();
        udelay(1);
        data <<= 1;
    }

    TXD_SET();
    CS_SET();
}

static void spi_recv_data(unsigned int* data)
{
    unsigned int i = 0, temp = 0x73;   //read data

    CS_SET();
    udelay(1);
    CLK_SET();
    TXD_SET();

    CS_CLR();
    udelay(1);

    for(i = 0; i < 8; i++) // 8 bits Data
    {
        udelay(1); 
        CLK_CLR();
        if (temp & 0x80)
           TXD_SET();
        else
           TXD_CLR();
        temp <<= 1;
        udelay(1); 
        CLK_SET();
        udelay(1); 
    }
    udelay(1);
    temp = 0;
    for(i = 0; i < 16; i++) // 16 bits Data
    {
        udelay(1); 
        CLK_CLR();
        udelay(1); 
        CLK_SET();
        udelay(1); 
        temp <<= 1;
        if(RXD_GET() == GPIO_HIGH)
           temp |= 0x01;
        
    }

    TXD_SET();
    CS_SET();
    *data = temp;
}

#define DEVIE_ID (0x70 << 16)
void send_ctrl_cmd(unsigned int cmd)
{
    unsigned int out = (DEVIE_ID | cmd );
    spi_send_data(out);
}

static void send_data_cmd(unsigned int data)
{
    unsigned int out = (DEVIE_ID | (0x2 << 16) | data );
    spi_send_data(out);
}

unsigned int ssd_read_register(unsigned int reg) {
    unsigned int data = 0;
    send_ctrl_cmd(reg);
    spi_recv_data(&data);
    return data;
}

void ssd_set_register(unsigned int reg_and_value)
{
    send_ctrl_cmd(reg_and_value >> 16);
    send_data_cmd(reg_and_value & 0x0000ffff);
}

int ssd_set_registers(unsigned int reg_array[], int n) {

    int i = 0;
    for(i = 0; i < n; i++) {
        if(reg_array[i] < 0x00b00000) {      //the lowest address is 0xb0 of ssd2828
            if(reg_array[i] < 20000)
            	udelay(reg_array[i]);
            else {
            	mdelay(reg_array[i]/1000);
            }
        } else {
            ssd_set_register(reg_array[i]);
        }
    }
    return 0;
}

int ssd_mipi_dsi_send_dcs_packet(unsigned char regs[], u32 n) {
    //unsigned int data = 0, i = 0;
    ssd_set_register(0x00B70363);
    ssd_set_register(0x00B80000);
    ssd_set_register(0x00Bc0001);
    
    ssd_set_register(0x00Bf0000 | regs[0]);
    msleep(1);

    return 0;
}


int _ssd2828_send_packet(unsigned char type, unsigned char regs[], u32 n) {

    
    return 0;
}

int ssd2828_send_packet(unsigned char type, unsigned char regs[], u32 n) {
    return _ssd2828_send_packet(type, regs, n);
}

int ssd_mipi_dsi_read_dcs_packet(unsigned char *data, u32 n) {
    //DCS READ 
    unsigned int i = 0;
    
    i = ssd_read_register(0xc6);
    printk("read mipi slave error:%04x\n", i);
    ssd_set_register(0x00B70382);
    ssd_set_register(0x00BB0008);
    ssd_set_register(0x00C1000A);
    ssd_set_register(0x00C00001);
    ssd_set_register(0x00Bc0001);
    ssd_set_register(0x00Bf0000 | *data);
    msleep(10);
    i = ssd_read_register(0xc6);
    printk("read mipi slave error:%04x\n", i);
    
    if(i & 1) {
        i = ssd_read_register(0xff);
        printk("read %02x:%04x\n", *data, i);
        i = ssd_read_register(0xff);
        printk("read %02x:%04x\n", *data, i);
        i = ssd_read_register(0xff);
        printk("read %02x:%04x\n", *data, i);
    
    } 
        
    return 0;
}


int ssd2828_get_id(void) {
    
    int id = -1;
    ssd2828_power_up();
    id = ssd_read_register(0xb0);
    
    return id;
}