基于DragonBoard 410c的彩灯设计(二)

        在博客http://blog.csdn.net/weixin_40109283/article/details/79399304中给出了基于DragonBoard 410c的彩灯设计的硬件介绍,驱动代码如下:

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/sysfs.h>

#include <linux/delay.h>

#include <linux/platform_device.h>

#include <linux/err.h>

#include <linux/device.h>

#include <linux/of_gpio.h>

#include <asm/uaccess.h>

#include <linux/kdev_t.h>

#include <linux/slab.h>

#define nws 16

unsigned long blue = 0x00ff00;

unsigned long red = 0xff0000;

unsigned long green = 0x0000ff;

unsigned long white = 0xffffff;

unsigned long orange= 0xff7f00;

unsigned long indigo= 0xff00ff;

unsigned long purple= 0x00ffff;

unsigned long black = 0x000000;

struct ws2801_data {

   struct platform_device *pdev;

   int ws2801_ck;

   int ws2801_si;

};

static struct ws2801_data* data;

static void send0(void)

{

   gpio_set_value(data->ws2801_si, 0);

   gpio_set_value(data->ws2801_ck, 0);

   ndelay(500);

   gpio_set_value(data->ws2801_ck, 1);

   ndelay(500);

}

static void send1(void)

{

   gpio_set_value(data->ws2801_si, 1);

   gpio_set_value(data->ws2801_ck, 0);

   ndelay(500);

   gpio_set_value(data->ws2801_ck, 1);

   ndelay(500);

}

static void ws_reset(void)

{

   gpio_set_value(data->ws2801_ck, 0);

   udelay(500);

}

static void sendbyte(unsigned long dat)

{

   unsigned char i;

   for (i = 0; i < 24; i++) {

      if (0x800000 == (dat & 0x800000))

         send1();

      else

         send0();

      dat <<= 1;

  }

}

static void sendws(unsigned long wsdata)

{

    unsigned char j;

    for (j = 0; j < nws; j++)

       sendbyte(wsdata);

    ws_reset();

}

static void ws2801_init(void)

{

    sendws(red);

    ssleep(1);

    sendws(green);

}

static void sendrgb(void)

{

    unsigned char i;

    for (i = 0; i < 5; i++) {

        sendbyte(red);

        sendbyte(green);

        sendbyte(blue);

    }

    ws_reset();

}

static void sendbrg(void)

{

    unsigned char i;

    for (i = 0; i < 5; i++) {

        sendbyte(blue);

        sendbyte(red);

        sendbyte(green);

    }

    ws_reset();

}

static void sendgbr(void)

{

    unsigned char i;

    for (i = 0; i < 5; i++) {

        sendbyte(green);

        sendbyte(blue);

        sendbyte(red);

    }

    ws_reset();

}

static ssize_t ws2801_store_value(struct device *dev, struct device_attribute* attr,

const char *buf, size_t len)

{

    int ret;

    unsigned long v;

    ret = kstrtoul(buf, 10, &v);

    switch (v) {

    case 0:

      sendws(black);

      break;

    case 1:

      sendws(red);

      break;

    case 2:

      sendws(green);

      break;

    case 3:

      sendws(blue);

      break;

    case 4:

      sendws(white);

      break;

    case 5:

      sendws(orange);

      break;

    case 6:

      sendws(purple);

      break;

    case 7:

      sendws(indigo);

      break;

    case 8:

      sendrgb();

      break;

    case 9:

      sendbrg();

      break;

    case 10:

      sendgbr();

      break;

    default:

      return -EINVAL;

    }

    return len;

}

static DEVICE_ATTR(value, 0664, NULL, ws2801_store_value);

static int ws2801_probe(struct platform_device *pdev)

{

    int result;

    struct device_node* node = pdev->dev.of_node;

    printk("ws2801 probe enter\n");

    data = devm_kzalloc(&pdev->dev, sizeof(struct ws2801_data), GFP_KERNEL);

    if (!data) {

       pr_err("%s kzalloc error\n", __FUNCTION__);

       return -ENOMEM;

    }

    dev_set_drvdata(&pdev->dev, data);

    data->ws2801_ck = of_get_named_gpio(node, "thundersoft,ws2801_ck", 0);

    if (!gpio_is_valid(data->ws2801_ck)) {

       pr_err("ws2801 ck not specified\n");

       goto err1;

     } else {

       result = gpio_request(data->ws2801_ck, "ws2801_ck");

       if (result < 0) {

           pr_err("Unable to request ws2801 ck\n");

           goto err1;

        } else {

           gpio_direction_output(data->ws2801_ck, 0);

        }

     }

     data->ws2801_si = of_get_named_gpio(node, "thundersoft,ws2801_si", 0);

     if (!gpio_is_valid(data->ws2801_si)) {

        pr_err("ws2801 si not specified\n");

        goto err2;

      } else {

        result = gpio_request(data->ws2801_si, "ws2801_si");

        if (result < 0) {

           pr_err("Unable to request ws2801 si\n");

           goto err2;

        } else {

           gpio_direction_output(data->ws2801_si, 0);

        }

     }

     result = sysfs_create_file(&pdev->dev.kobj, &dev_attr_value.attr);

     if (result < 0) {

        printk("sysfs create file failed\n");

        goto err3;

     }

     ws2801_init();

     printk(KERN_INFO "ws2801 probe success\n");

     return 0;

err3:

   gpio_free(data->ws2801_si);

err2:

   gpio_free(data->ws2801_ck);

err1:

   kfree(data);

   printk(KERN_ERR "ws2801 probe failed\n");

   return -EINVAL;

}

static int ws2801_remove(struct platform_device *pdev)

{

    gpio_free(data->ws2801_si);

    gpio_free(data->ws2801_ck);

    kfree(data);

    return 0;

}

static struct of_device_id ws2801_match_table[] = {

{   .compatible = "thundersoft,ws2801"},

    { },

};

static struct platform_driver ws2801_driver = {

   .probe = ws2801_probe,

   .remove = ws2801_remove,

   .driver = {

   .owner = THIS_MODULE,

   .name = "ws2801",

   .of_match_table = ws2801_match_table,

   },

};

module_platform_driver(ws2801_driver);

MODULE_AUTHOR("heql0703@thundersoft.com");

MODULE_LICENSE("GPL");


阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭