/* ****************************************************************************** * @file seeed5inch.c * @author StarFive Technology * @version V1.0 * @date 01/07/2021 * @brief ****************************************************************************** * @copy * * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2021 Shanghai StarFive Technology Co., Ltd.

*/ #include #include #include #include #include #include #include #include #include #include #include #include #include /* I2C registers of the Atmel microcontroller. */ enum REG_ADDR { REG_ID = 0x80, REG_PORTA, /* BIT(2) for horizontal flip, BIT(3) for vertical flip */ REG_PORTB, REG_PORTC, REG_PORTD, REG_POWERON, REG_PWM, REG_DDRA, REG_DDRB, REG_DDRC, REG_DDRD, REG_TEST, REG_WR_ADDRL, REG_WR_ADDRH, REG_READH, REG_READL, REG_WRITEH, REG_WRITEL, REG_ID2, }; struct seeed_panel_dev { struct i2c_client *client; struct device *dev; int irq; }; struct dcs_buffer { u32 len; union { u32 val32; char val8[4]; }; }; static int seeed_panel_i2c_write(struct i2c_client *client, u8 reg, u8 val) { struct i2c_msg msg; u8 buf[2]; int ret; buf[0] = reg; buf[1] = val; msg.addr = client->addr; msg.flags = 0; msg.buf = buf; msg.len = 2; ret = i2c_transfer(client->adapter, &msg, 1); if (ret >= 0) return 0; dev_err(&client->dev, "seeed panel i2c write reg(0x%x val:0x%x) failed !\n", reg, val); return ret; } static int seeed_panel_i2c_read(struct i2c_client *client, u8 reg, u8 *val) { struct i2c_msg msg[2]; u8 buf[2]; int ret; buf[0] = reg; msg[0].addr = client->addr; msg[0].flags = 0; msg[0].buf = buf; msg[0].len = 1; msg[1].addr = client->addr; msg[1].flags = I2C_M_RD; msg[1].buf = val; msg[1].len = 1; ret = i2c_transfer(client->adapter, msg, 2); if (ret >= 0) { return 0; } dev_err(&client->dev, "seeed panel i2c read reg(0x%x val:0x%x) failed,ret = %d !\n", reg, *val, ret); return ret; } #if 0 static int seeed_panel_disable(struct i2c_client *client) { seeed_panel_i2c_write(client, REG_PWM, 0); seeed_panel_i2c_write(client, REG_POWERON, 0); udelay(1); return 0; } #endif enum dsi_rgb_pattern_t { RGB_PAT_WHITE, RGB_PAT_BLACK, RGB_PAT_RED, RGB_PAT_GREEN, RGB_PAT_BLUE, RGB_PAT_HORIZ_COLORBAR, RGB_PAT_VERT_COLORBAR, RGB_PAT_NUM }; static int seeed_panel_probe(struct i2c_client *client, const struct i2c_device_id *id) { u8 reg_value = 0; // int ret = 0; int i; struct seeed_panel_dev *seeed_panel; // struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_warn(&client->dev, "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); return -EIO; } seeed_panel = devm_kzalloc(&client->dev,sizeof(struct seeed_panel_dev), GFP_KERNEL); if (!seeed_panel) return -ENOMEM; seeed_panel->client = client; i2c_set_clientdata(client, seeed_panel); seeed_panel_i2c_read(client, REG_ID, ®_value); dev_info(&client->dev, "%s[%d],reg[0x80] = 0x%x\n", __func__, __LINE__, reg_value); switch (reg_value) { case 0xde: /* ver 1 */ case 0xc3: /* ver 2 */ break; default: dev_err(&client->dev, "Unknown Atmel firmware revision: 0x%02x\n", reg_value); return -ENODEV; } seeed_panel_i2c_write(client, REG_POWERON, 1); mdelay(5); /* Wait for nPWRDWN to go low to indicate poweron is done. */ for (i = 0; i < 100; i++) { seeed_panel_i2c_read(client, REG_PORTB, ®_value); if (reg_value & 1) break; } seeed_panel_i2c_write(client, REG_PWM, 255); seeed_panel_i2c_write(client, REG_PORTA, BIT(2)); return 0; } static int seeed_panel_remove(struct i2c_client *client) { return 0; } static const struct i2c_device_id seeed_panel_id[] = { { "seeed_panel", 0 }, { } }; static const struct of_device_id seeed_panel_dt_ids[] = { { .compatible = "seeed_panel", }, { /* sentinel */ } }; static struct i2c_driver seeed_panel_driver = { .driver = { .owner = THIS_MODULE, .name = "seeed_panel", .of_match_table = seeed_panel_dt_ids, }, .probe = seeed_panel_probe, .remove = seeed_panel_remove, .id_table = seeed_panel_id, }; static __init int init_seeed_panel(void) { int err; err = i2c_add_driver(&seeed_panel_driver); if (err != 0) printk("i2c driver registration failed, error=%d\n", err); return err; } static __exit void exit_seeed_panel(void) { i2c_del_driver(&seeed_panel_driver); } //module_init(init_seeed_panel); fs_initcall(init_seeed_panel); module_exit(exit_seeed_panel); MODULE_DESCRIPTION("A driver for seeed_panel"); MODULE_LICENSE("GPL");