如何编写显示驱动程序

时间:2015-04-27 07:17:56

标签: driver linux-device-driver i2c omap

我正在为微型oled编写显示驱动程序。 board是dart4460(omap4460),提供dss(显示子系统)。 所以我正在使用dss编写驱动程序。

但我不知道我写的是对还是

oled display使用dpi接口和i2c命令

我提到了使用dpi和i2c的pico dlp投影机驱动源。

这里是数据表

dart4460:http://www.variscite.com/images/DART-4460-DS_107.pdf

微观显示:https://www.dropbox.com/s/ixpws4qzo3ttj6e/SVGA050.pdf?dl=0

代码:

面板svga.c

function checkMobile(){
                var strHtml="";
              if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
                strHtml='<a href="studyAreas.html">'
                        + 'Wifi Study Areas</a>'
                        + '<a href="displayspeeds.html">'
                        + 'View all Speeds</a>'
                        + '<a href="bestlocation.html">'
                        + 'Best Speed Near You</a>'
                        + '<a href="squadfree/index.html">'
                        + 'About Us</a>';
              }
              else{
               strHtml= '<a href="studyAreas.html">'
                        + 'Wifi Study Areas</a>'
                        + '<a href="displayspeeds.html">'
                        + 'View all Speeds</a>'
                        + '<a href="bestlocation.html">'
                        + 'Best Speed Near You</a>'
                        + '<a href="userEnterInfo.html">'
                        + 'Add Speed Data</a>'
                        + '<a href="squadfree/index.html">'
                        + 'About Us</a>';
              }

               document.getElementById("linkContainer").innerHTML=strHtml;
            }

//finally call the function.
checkMobile();

Board.c

#define SLAVE_ADDR_READ     0x1F
#define SLAVW_ADDR_WRITE    0x1E

struct svga050_i2c_data {
struct mutex xfer_lock;
};

struct svga050_data {
struct i2c_client *client;
struct mutex lock;
};

static struct i2c_board_info svga050_i2c_board_info = {
I2C_BOARD_INFO("svga050_i2c_drive",SLAVE_ADDR_WRITE);
}

static struct omap_video_timings svga050_timings = {
   .x_res = 800,
   .y_res = 600,

   .pixel_clock = 40000,

   .hsw     = 128,
   .hfp     = 40,
   .hbp     = 88,

   .vsw     = 4,
   .vfp     = 1,
   .vbp     = 23,
};

static int svga050_panel_power_on(struct omap_dss_device *dssdev)
{
    int r;

if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
    return 0;

r = omapdss_dpi_display_enable(dssdev);
if (r)
    goto err0;

if (dssdev->platform_enable) {
    r = dssdev->platform_enable(dssdev);
    if (r)
        goto err1;
}

    return 0;
    err1:
       omapdss_dpi_display_disable(dssdev);
    err0:
       return r;
 }

 static void svga050_panel_power_off(struct omap_dss_device *dssdev)
{
    if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
        return;

    if (dssdev->platform_disable)
        dssdev->platform_disable(dssdev);

     omapdss_dpi_display_disable(dssdev);
 }

 static inline struct svga050_panel_data *get_panel_data(const struct  omap_dss_device *dssdev)
 {
     return (struct svga050_panel_data *)dssdev->data;
 }

  static int svga050_panel_probe(struct omap_dss_device *dssdev)
 {
    struct svga050_data *svga_data;
    struct i2c_adapter *adapter;
    struct i2c_client *svga_i2c_client;
    struct svga050_panel_data *svga_pdata=get_panel_data(dssdev);
    int r;

    dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
       OMAP_DSS_LCD_IHS;
    dssdev->panel.timings = svga050_timings;

    svga_data = devm_kzalloc(&dssdev->dev,sizeof(*svga_data), GFP_KERNEL);
    if (!svga_data) {
       r = -ENOMEM;
    goto err;
    }
    mutex_init(&ld->lock);
    dev_set_drvdata(&dssdev->dev, ld);
    return 0;
      err:
      return r;
    }

   static void svga050_panel_remove(struct omap_dss_device *dssdev)
  {
     struct svga050_data *ld = dev_get_drvdata(&dssdev->dev);

     kfree(ld);
   }

  static int svga050_panel_enable(struct omap_dss_device *dssdev)
 {
     struct svga050_data *ld = dev_get_drvdata(&dssdev->dev);
     int r;

      mutex_lock(&ld->lock);

     r = svga050_panel_power_on(dssdev);
     if (r)
    goto err;
    dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;

    mutex_unlock(&ld->lock);
    return 0;
    err:
      mutex_unlock(&ld->lock);
    return r;
 }

static void svga050_panel_disable(struct omap_dss_device *dssdev)
{
    struct svga050_data *ld = dev_get_drvdata(&dssdev->dev);

    mutex_lock(&ld->lock);

    svga050_panel_power_off(dssdev);
    dssdev->state = OMAP_DSS_DISPLAY_DISABLED;

    mutex_unlock(&ld->lock);
 }

 static int svga050_panel_suspend(struct omap_dss_device *dssdev)
{
    struct svga050_data *ld = dev_get_drvdata(&dssdev->dev);

    mutex_lock(&ld->lock);

    svga050_panel_power_off(dssdev);
    dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;

    mutex_unlock(&ld->lock);
    return 0;
}

static int svga050_panel_resume(struct omap_dss_device *dssdev)
{
   struct svga050_data *ld = dev_get_drvdata(&dssdev->dev);
   int r;

   mutex_lock(&ld->lock);

   r = svga050_panel_power_on(dssdev);
   if (r)
       goto err;
   dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;

   mutex_unlock(&ld->lock);
   return 0;
  err:
      mutex_unlock(&ld->lock);
  return r;
}

 static struct omap_dss_driver svga050_driver = {
     .probe     = svga050_panel_probe,
     .remove        = svga050_panel_remove,

     .enable        = svga050_panel_enable,
     .disable   = svga050_panel_disable,
     .suspend   = svga050_panel_suspend,
     .resume        = svga050_panel_resume,

     .driver         = {
        .name   = "svga050",
        .owner  = THIS_MODULE,
     },
  };

  static int svga050_i2c_read(struct i2c_client *client, u8 reg)
 {
    u8 read_cmd[] = { SLAVE_ADDR_READ, reg }, data;
    struct svga050_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
    struct i2c_msg msg[2];
    mutex_lock(&svga050_i2c_data->xfer_lock);
    msg[0].addr = client->addr;
    msg[0].flags = 0;
    msg[0].len = 2;
    msg[0].buf = read_cmd;
    msg[1].addr = client->addr;
    msg[1].flags = I2C_M_RD;
    msg[1].len = 2;
    msg[1].buf = data;
    i2c_transfer(client->adapter, msg, 2);
    mutex_unlock(&svga050_i2c_data->xfer_lock);
    return data;
 }

 static int svga050_i2c_write(struct i2c_client *client, u8 reg, u8 value)
 {
    u8 data[2];
    int i;
    struct i2c_msg msg;
    int i, r, msg_count = 1;
    struct svga050_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);

    data[0] = reg;
    data[1] = value;

    mutex_lock(&svga050_i2c_data->xfer_lock);
    msg.addr = client->addr;
    msg.flags = 0;
    msg.len = 2;
    msg.buf = data;
    r = i2c_transfer(client->adapter, &msg, msg_count);
    mutex_unlock(&svga050_i2c_data->xfer_lock);
    /*
     * i2c_transfer returns:
     * number of messages sent in case of success
     * a negative error number in case of failure
     */
    if (r != msg_count)
        goto err;
    /* In case of success */
    for (i = 0; i < 2; i++)
        dev_dbg(&client->dev,
                "addr %x bw 0x%02x[%d]: 0x%02x\n",
                client->addr, data[0] + i, i, data[i]);
    return 0;
   err:
    dev_err(&client->dev, "svga050_i2c_write error\n");
    return r;
 }
 static int svga050_i2c_write_array(struct i2c_client *client,
    const struct svga050_i2c_command commands[],
    int count)
 {
     int i, r = 0;
    for (i = 0; i < count; i++) {
        r = svga050_i2c_write(client, commands[i].reg,
            commands[i].value);
        if (r)
            return r;
     }
   return r;
   }

 static void init_svga050_panel(struct spi_device *spi)
 {
 }

 static int __devinit svga050_panel_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
 {
     struct svga050_i2c_data *svga_i2c_data;

     svga_i2c_data=kzalloc(sizeof(struct svga050_i2c_data),GFP_KERNEL);
     if(svga_i2c_data == NULL)
         return -ENOMEM;

     i2c_set_clientdata(client,svga_i2c_data);

     mutex_init(&svga_i2c_data->xfer_lock);
     dev_err(&client->dev,"svga i2c initialized\n");
     return 0;
 }

 static int __devexit svga050_panel_i2c_remove(struct i2c_client *client)
 {
     struct svga050_i2c_data *sd1= i2c_get_clientdata(client);

     i2c_set_clientdata(client,NULL);
     kfree(sd1);
     return 0;
 }

 static const struct i2c_device_id svga050_i2c_idtable[]={
     {"svga050_i2c_driver",0},
     {},
 };

 static struct i2c_driver svga050_i2c_driver = {
     .driver        = {
     .name  = "svga050_i2c",
     .owner = THIS_MODULE,
},
     .probe     = svga050_panel_i2c_probe,
     .remove        = __exit_p(svga050_panel_i2c_remove),
     .id_table  = svga050_i2c_idtable,
 };

 static int __init svga050_panel_drv_init(void)
 {
     int r;
     r= i2c_add_driver(&svga050_i2c_driver);
     if(r < 0){
         printk(KERN_WARNING "svga050 i2c driver registration failed\n");
         return r;
      }
   r=omap_dss_register_driver(&svga050_driver);
   if(r < 0){
       printk(KERN_WARNING "svga050 dss driver registration failed\n");
       i2c_del_driver(&svga050_i2c_driver);
    }
    return r;
 }

 static void __exit svga050_panel_drv_exit(void)
 {
     omap_dss_unregister_driver(&svga050_driver);
     i2c_del_driver(&svga050_i2c_driver);
 }

 module_init(svga050_panel_drv_init);
 module_exit(svga050_panel_drv_exit);
 MODULE_LICENSE("GPL");

我的问题是:

  1. 我的代码是对的?

  2. 我不知道如何通过查看数据表来编写显示static struct omap_dss_device svga050_device = { .name = "svga050", .driver_name = "svga050", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, .channel = OMAP_DSS_CHANNEL_LCD2, .platform_enable = svga050_panel_enable_picodlp, .platform_disable = svga050_panel_disable_picodlp, .data = &svga050_pdata, }; static struct omap_dss_device *svga050_dss_devices[] = { &svga050_device, }; static struct picodlp_panel_data sdp4430_picodlp_pdata = { .svga050_adapter_id = 2, }; 代码。

    我可以通过查看此数据表来编写显示init代码吗?

  3. 在panel_probe函数中,如何获取适配器ID? 如何选择适配器I?

  4. 我应该在面板代码中只编写i2c slave驱动程序代码吗?

  5. 如何选择I2C主控?我想将I2C3或I2C4用于显示命令

0 个答案:

没有答案