P3T3

FBTFT driver for the ZTE U733 3.5" LCD display

May 30th, 2013
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.30 KB | None | 0 0
  1. /*
  2.  * FB driver for the ZTE U733 3.5" LCD display
  3.  *
  4.  * Copyright (C) 2013 Petr Blaha
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <linux/module.h>
  22. #include <linux/kernel.h>
  23. #include <linux/init.h>
  24. #include <linux/gpio.h>
  25. #include <linux/spi/spi.h>
  26. #include <linux/delay.h>
  27.  
  28. #include "fbtft.h"
  29.  
  30. #define DRVNAME     "zteu733fb"
  31. #define WIDTH       400
  32. #define HEIGHT      240
  33.  
  34. /* Module Parameter: debug  (also available through sysfs) */
  35. MODULE_PARM_DEBUG;
  36.  
  37. /* Module Parameter: rotate */
  38. static unsigned rotate = 0;
  39. module_param(rotate, uint, 0);
  40. MODULE_PARM_DESC(rotate, "Rotate display (0=normal, 1=clockwise, 2=upside down, 3=counterclockwise)");
  41.  
  42. static inline int my_spi_write(struct fbtft_par *par, struct spi_device *spi, const void *buf, size_t len)
  43. {
  44.     struct spi_transfer t = {
  45.             .tx_buf     = buf,
  46.             .len        = len,
  47.         };
  48.     struct spi_message  m;
  49.     int ret=0;
  50.  
  51.     spi_message_init(&m);
  52.     spi_message_add_tail(&t, &m);
  53.     ret = spi_sync(spi, &m);
  54. fbtft_fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par, par->info->device, "%s: buffer size =%d return is=%d \n", __func__, len, ret);
  55.     return ret;
  56. }
  57.  
  58. static int zteu733fb_init_display(struct fbtft_par *par)
  59. {
  60.     fbtft_dev_dbg(DEBUG_INIT_DISPLAY, par->info->device, "%s()\n", __func__);
  61.  
  62.     par->fbtftops.reset(par);
  63.  
  64.     write_cmd(par, 0xE9);           // LSI Test Register
  65.     write_data(par, 0x20);
  66.     mdelay(20);
  67.  
  68.     write_cmd(par, 0x01);           // Sotf Reset
  69.     mdelay(150);
  70.  
  71.     write_cmd(par, 0x11);           // Exit Sleep mode
  72.     mdelay(500);
  73.  
  74.     write_cmd(par, 0x53);           // Write CTRL Display, Display Dimming = 1, Backlight = ON
  75.     write_data(par, 0x08);
  76.     write_cmd(par, 0x51);           // Write Display Brightness = 0xFF
  77.     write_data(par, 0xFF);
  78.  
  79.     write_cmd(par, 0xD1);
  80.     write_data(par, 0x00);
  81.     write_data(par, 0x71);
  82.     write_data(par, 0x19);
  83.  
  84.     write_cmd(par, 0xD0);
  85.     write_data(par, 0x07);
  86.     write_data(par, 0x01);
  87.     write_data(par, 0x08);
  88.  
  89.     write_cmd(par, 0x36);           // Set Address Mode :
  90.     write_data(par, 0x28);          // bit 3 0=RGB, 1=BGR
  91.  
  92.     write_cmd(par, 0x3A);           // Set Pixel Format : 0x11 = 8bpp, 0x55 = 16bpp, 0x66 = 18bpp
  93.     write_data(par, 0x55);
  94.  
  95.     write_cmd(par, 0xC1);
  96.     write_data(par, 0x10);
  97.     write_data(par, 0x10);
  98.     write_data(par, 0x02);
  99.     write_data(par, 0x02);
  100.  
  101.     write_cmd(par, 0xC0);
  102.     write_data(par, 0x00);
  103.     write_data(par, 0x35);
  104.     write_data(par, 0x00);
  105.     write_data(par, 0x00);
  106.     write_data(par, 0x01);
  107.     write_data(par, 0x02);
  108.  
  109.     write_cmd(par, 0xC5);
  110.     write_data(par, 0x04);
  111.  
  112.     write_cmd(par, 0xD2);
  113.     write_data(par, 0x01);
  114.     write_data(par, 0x44);
  115.  
  116.     // GAMA TODO
  117.  
  118.     write_cmd(par, 0x29);           // Display ON
  119.     write_cmd(par, 0x20);           // Exit Invert Mode
  120.  
  121.     return 0;
  122. }
  123.  
  124. void zteu733fb_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
  125. {
  126.     fbtft_fbtft_dev_dbg(DEBUG_SET_ADDR_WIN, par, par->info->device, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);
  127.  
  128.     /* Set Column Address */
  129.     write_cmd(par, 0x2A);
  130.     write_data(par, (xs >> 8) & 0xFF);
  131.     write_data(par, xs & 0xFF);
  132.     write_data(par, (xe >> 8) & 0xFF);
  133.     write_data(par, xe & 0xFF);
  134.  
  135.     /* Set Page Address */
  136.     write_cmd(par, 0x2B);
  137.     write_data(par, (ys >> 8) & 0xFF);
  138.     write_data(par, ys & 0xFF);
  139.     write_data(par, (ye >> 8) & 0xFF);
  140.     write_data(par, ye & 0xFF);
  141.  
  142.     /* 0x2C - Write Memory Start */
  143.     write_cmd(par, 0x2C);
  144. }
  145.  
  146. void zteu733fb_update_display(struct fbtft_par *par)
  147. {
  148.         struct timespec ts_start,ts_end,test_of_time;
  149.         long ms, us, ns;
  150.         bool timeit = false;
  151.         int ret = 0;
  152.  
  153.         if (unlikely(*par->debug & (DEBUG_TIME_FIRST_UPDATE | DEBUG_TIME_EACH_UPDATE))) {
  154.                 if ( (*par->debug & DEBUG_TIME_EACH_UPDATE) || \
  155.                          ((*par->debug & DEBUG_TIME_FIRST_UPDATE) && !par->first_update_done) )
  156.                 {
  157.                         getnstimeofday(&ts_start);
  158.                         timeit = true;
  159.                 }
  160.         }
  161.         // Sanity checks
  162.         if (par->dirty_lines_start > par->dirty_lines_end) {
  163.                 fbtft_fbtft_dev_dbg(0xFFFFFFFF, par, par->info->device,
  164.                         "%s: dirty_lines_start=%d is larger than dirty_lines_end=%d. Shouldn't happen, will do full display update\n",
  165.                         __func__, par->dirty_lines_start, par->dirty_lines_end);
  166.                 par->dirty_lines_start = 0;
  167.                 par->dirty_lines_end = par->info->var.yres - 1;
  168.         }
  169.         if (par->dirty_lines_start > par->info->var.yres - 1 || par->dirty_lines_end > par->info->var.yres - 1) {
  170.                 dev_warn(par->info->device,
  171.                         "%s: dirty_lines_start=%d or dirty_lines_end=%d larger than max=%d. Shouldn't happen, will do full display update\n",
  172.                         __func__, par->dirty_lines_start, par->dirty_lines_end, par->info->var.yres - 1);
  173.                 par->dirty_lines_start = 0;
  174.                 par->dirty_lines_end = par->info->var.yres - 1;
  175.         }
  176.  
  177.         fbtft_fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par, par->info->device, "%s: dirty_lines_start=%d dirty_lines_end=%d\n", __func__, par->dirty_lines_start, par->dirty_lines_end);
  178.  
  179.         if (par->fbtftops.set_addr_win)
  180.                 par->fbtftops.set_addr_win(par, 0, par->dirty_lines_start, par->info->var.xres-1, par->dirty_lines_end);
  181.  
  182.       ret = par->fbtftops.write_vmem(par);
  183.       if (ret < 0)
  184.               dev_err(par->info->device, "%s: write_vmem failed to update display buffer\n", __func__);
  185.  
  186.         if (unlikely(timeit)) {
  187.                 getnstimeofday(&ts_end);
  188.                 test_of_time = timespec_sub(ts_end,ts_start);
  189.                 us = (test_of_time.tv_nsec / 1000) % 1000;
  190.                 ms = (test_of_time.tv_sec * 1000) + ((test_of_time.tv_nsec / 1000000) % 1000);
  191.                 ns = test_of_time.tv_nsec % 1000;
  192.                 dev_info(par->info->device, "Elapsed time for display update: %4lu.%.3lu%.3lu ms (fps: %2lu, lines=%u)\n",
  193.                                             ms, us, ns, test_of_time.tv_nsec ? 1000000000 / test_of_time.tv_nsec : 0, par->dirty_lines_end - par->dirty_lines_start + 1);
  194.                 par->first_update_done = true;
  195.         }
  196.  
  197.         // set display line markers as clean
  198.         par->dirty_lines_start = par->info->var.yres - 1;
  199.         par->dirty_lines_end = 0;
  200. }
  201.  
  202. int zteu733fb_write_vmem(struct fbtft_par *par) {
  203.     u8 *vmem8;
  204.     u8  *txbuf8  = par->txbuf.buf;
  205.     size_t remain;
  206.     size_t to_copy;
  207.     size_t tx_array_size;
  208.     int i;
  209.     int ret = 0;
  210.     size_t offset, len;
  211.  
  212.     offset = par->dirty_lines_start * par->info->fix.line_length;
  213.     len = (par->dirty_lines_end - par->dirty_lines_start + 1) * par->info->fix.line_length;
  214.     remain = len;
  215.     vmem8 = par->info->screen_base + offset;
  216.  
  217.     fbtft_fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par, par->info->device, "%s: offset=%d, len=%d\n", __func__, offset, len);
  218.  
  219.     if (par->gpio.dc != -1)
  220.             gpio_set_value(par->gpio.dc, 1);
  221.  
  222.     // non buffered write
  223.     if (!par->txbuf.buf)
  224.             return par->fbtftops.write(par, vmem8, len);
  225.  
  226.     // buffered write
  227.     tx_array_size = par->txbuf.len;
  228.  
  229.     while (remain) {
  230.             to_copy = remain > tx_array_size ? tx_array_size : remain;
  231.             dev_dbg(par->info->device, "    to_copy=%d, remain=%d\n", to_copy, remain - to_copy);
  232.             fbtft_fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par, par->info->device, "%s: to copy=%d, remain=%d\n", __func__, to_copy, remain-to_copy);
  233.  
  234.  
  235.     #ifdef __LITTLE_ENDIAN
  236.         for (i=0;i<to_copy;i+=2) {
  237.             txbuf8[i]    = vmem8[i+1];
  238.             txbuf8[i+1]  = vmem8[i];
  239. //          write_data(par, 256*vmem8[i+1] + vmem8[i] );
  240.             }
  241.     #else
  242.         for (i=0;i<to_copy;i++) {
  243.             txbuf8[i]    = vmem8[i];
  244.             write_data(par, txbuf8[i]);
  245.             }
  246.     #endif
  247.         vmem8 = vmem8 + to_copy;
  248.                  ret = par->fbtftops.write(par, par->txbuf.buf, to_copy);
  249.                   if (ret < 0)
  250.                           return ret;
  251.         remain -= to_copy;
  252.     }
  253.     return 0;
  254. }
  255.  
  256. int zteu733fb_write_spi(struct fbtft_par *par, void *buf, size_t len)
  257. {
  258. //  fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par, par->info->device, u8, buf, len, "%s(len=%d): ", __func__, len);
  259. //  fbtft_fbtft_dev_dbg(DEBUG_UPDATE_DISPLAY, par, par->info->device, "%s: buffer size =%d\n", __func__, len);
  260.  
  261.     if (!par->spi) {
  262.         dev_err(par->info->device, "%s: par->spi is unexpectedly NULL\n", __func__);
  263.         return -1;
  264.     }
  265.     return my_spi_write(par, par->spi, buf, len);
  266. }
  267.  
  268. static int zteu733fb_verify_gpios(struct fbtft_par *par)
  269. {
  270.     int i;
  271.  
  272.     fbtft_dev_dbg(DEBUG_VERIFY_GPIOS, par->info->device, "%s()\n", __func__);
  273.  
  274.     if (par->gpio.dc < 0) {
  275.         dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n");
  276.         return -EINVAL;
  277.     }
  278.     if (par->pdev) {
  279.         if (par->gpio.wr < 0) {
  280.             dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n");
  281.             return -EINVAL;
  282.         }
  283.         for (i=0;i < 16;i++) {
  284.             if (par->gpio.db[i] < 0) {
  285.                 dev_err(par->info->device, "Missing info about 'db%02d' gpio. Aborting.\n", i);
  286.                 return -EINVAL;
  287.             }
  288.         }
  289.     }
  290.  
  291.     return 0;
  292. }
  293.  
  294. struct fbtft_display zteu733fb_display = {
  295.     .width = WIDTH,
  296.     .height = HEIGHT,
  297. };
  298.  
  299. static int zteu733fb_probe_common(struct spi_device *sdev, struct platform_device *pdev)
  300. {
  301.     struct device *dev;
  302.     struct fb_info *info;
  303.     struct fbtft_par *par;
  304.     int ret;
  305.  
  306.     if (sdev)
  307.         dev = &sdev->dev;
  308.     else
  309.         dev = &pdev->dev;
  310.  
  311.     fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "%s()\n", __func__);
  312.  
  313.     if (rotate > 3) {
  314.         dev_warn(dev, "module parameter 'rotate' illegal value: %d. Can only be 0,1,2,3. Setting it to 0.\n", rotate);
  315.         rotate = 0;
  316.     }
  317.     switch (rotate) {
  318.     case 0:
  319.     case 2:
  320.         zteu733fb_display.width = WIDTH;
  321.         zteu733fb_display.height = HEIGHT;
  322.         break;
  323.     case 1:
  324.     case 3:
  325.         zteu733fb_display.width = HEIGHT;
  326.         zteu733fb_display.height = WIDTH;
  327.         break;
  328.     }
  329.  
  330.     info = fbtft_framebuffer_alloc(&zteu733fb_display, dev);
  331.     if (!info)
  332.         return -ENOMEM;
  333.  
  334.     info->var.rotate = rotate;
  335.     par = info->par;
  336.     if (sdev)
  337.         par->spi = sdev;
  338.     else
  339.         par->pdev = pdev;
  340.  
  341.     fbtft_debug_init(par);
  342.     par->fbtftops.init_display = zteu733fb_init_display;
  343. //  par->fbtftops.update_display = zteu733fb_update_display;
  344.     par->fbtftops.write_vmem = zteu733fb_write_vmem;
  345. //  par->fbtftops.register_backlight = fbtft_register_backlight;
  346. //  par->fbtftops.write_reg = fbtft_write_reg16_bus8;
  347.     par->fbtftops.set_addr_win = zteu733fb_set_addr_win;
  348. //  par->fbtftops.write_data_command = fbtft_write_data_command16_bus8;
  349.     par->fbtftops.verify_gpios = zteu733fb_verify_gpios;
  350.     par->fbtftops.write = zteu733fb_write_spi;
  351.  
  352. /*
  353.     if (pdev)
  354.             par->fbtftops.write = fbtft_write_gpio16_wr;
  355. */
  356.     ret = fbtft_register_framebuffer(info);
  357.     if (ret < 0)
  358.             goto out_release;
  359.  
  360.     return 0;
  361.  
  362. out_release:
  363.     fbtft_framebuffer_release(info);
  364.  
  365.     return ret;
  366. }
  367.  
  368. static int zteu733fb_remove_common(struct device *dev, struct fb_info *info)
  369. {
  370.         fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, dev, "%s()\n", __func__);
  371.  
  372.         if (info) {
  373.                 fbtft_unregister_framebuffer(info);
  374.                 fbtft_framebuffer_release(info);
  375.         }
  376.  
  377.         return 0;
  378. }
  379.  
  380. static int zteu733fb_probe_spi(struct spi_device *spi)
  381. {
  382.         fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__);
  383.         return zteu733fb_probe_common(spi, NULL);
  384. }
  385.  
  386. static int zteu733fb_remove_spi(struct spi_device *spi)
  387. {
  388.         struct fb_info *info = spi_get_drvdata(spi);
  389.  
  390.         fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &spi->dev, "%s()\n", __func__);
  391.         return zteu733fb_remove_common(&spi->dev, info);
  392. }
  393.  
  394. static int zteu733fb_probe_pdev(struct platform_device *pdev)
  395. {
  396.         fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &pdev->dev, "%s()\n", __func__);
  397.         return zteu733fb_probe_common(NULL, pdev);
  398. }
  399.  
  400. static int zteu733fb_remove_pdev(struct platform_device *pdev)
  401. {
  402.         struct fb_info *info = platform_get_drvdata(pdev);
  403.  
  404.         fbtft_dev_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, &pdev->dev, "%s()\n", __func__);
  405.  
  406.         /* not supported, the RPi doesn't have that many GPIOs, and thus no 16-bit write function */
  407.         return -1;
  408.  
  409.         return zteu733fb_remove_common(&pdev->dev, info);
  410. }
  411.  
  412. static const struct spi_device_id zteu733fb_platform_ids[] = {
  413.         { "zteu733fb", 0 },
  414.         { },
  415. };
  416.  
  417. static struct spi_driver zteu733fb_spi_driver = {
  418.         .driver = {
  419.                 .name   = DRVNAME,
  420.                 .owner  = THIS_MODULE,
  421.         },
  422.         .id_table = zteu733fb_platform_ids,
  423.         .probe  = zteu733fb_probe_spi,
  424.         .remove = zteu733fb_remove_spi,
  425. };
  426.  
  427. static struct platform_driver zteu733fb_platform_driver = {
  428.         .driver = {
  429.                 .name   = DRVNAME,
  430.                 .owner  = THIS_MODULE,
  431.         },
  432.         .probe  = zteu733fb_probe_pdev,
  433.         .remove = zteu733fb_remove_pdev,
  434. };
  435.  
  436. static int __init zteu733fb_init(void)
  437. {
  438.         int ret;
  439.  
  440.         fbtft_pr_debug("\n\n"DRVNAME": %s()\n", __func__);
  441.         ret = spi_register_driver(&zteu733fb_spi_driver);
  442.         if (ret < 0)
  443.                 return ret;
  444.         return platform_driver_register(&zteu733fb_platform_driver);
  445. }
  446.  
  447. static void __exit zteu733fb_exit(void)
  448. {
  449.         fbtft_pr_debug(DRVNAME": %s()\n", __func__);
  450.         spi_unregister_driver(&zteu733fb_spi_driver);
  451.         platform_driver_unregister(&zteu733fb_platform_driver);
  452. }
  453.  
  454. /* ------------------------------------------------------------------------- */
  455.  
  456. module_init(zteu733fb_init);
  457. module_exit(zteu733fb_exit);
  458.  
  459. MODULE_DESCRIPTION("FB driver for the ZTE U733 3.5 LCD display");
  460. MODULE_AUTHOR("Petr Blaha");
  461. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment