These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / fbtft / fbtft-core.c
index 53b748b..b1e4516 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/module.h>
@@ -47,10 +43,11 @@ static unsigned long debug;
 module_param(debug, ulong, 0);
 MODULE_PARM_DESC(debug, "override device debug level");
 
+#ifdef CONFIG_HAS_DMA
 static bool dma = true;
 module_param(dma, bool, 0);
 MODULE_PARM_DESC(dma, "Use DMA buffer");
-
+#endif
 
 void fbtft_dbg_hex(const struct device *dev, int groupsize,
                        void *buf, size_t len, const char *fmt, ...)
@@ -125,33 +122,34 @@ static int fbtft_request_gpios(struct fbtft_par *par)
        unsigned long flags;
        int ret;
 
-       if (pdata && pdata->gpios) {
-               gpio = pdata->gpios;
-               while (gpio->name[0]) {
-                       flags = FBTFT_GPIO_NO_MATCH;
-                       /* if driver provides match function, try it first,
-                          if no match use our own */
-                       if (par->fbtftops.request_gpios_match)
-                               flags = par->fbtftops.request_gpios_match(par, gpio);
-                       if (flags == FBTFT_GPIO_NO_MATCH)
-                               flags = fbtft_request_gpios_match(par, gpio);
-                       if (flags != FBTFT_GPIO_NO_MATCH) {
-                               ret = devm_gpio_request_one(par->info->device,
-                                               gpio->gpio, flags,
-                                               par->info->device->driver->name);
-                               if (ret < 0) {
-                                       dev_err(par->info->device,
-                                               "%s: gpio_request_one('%s'=%d) failed with %d\n",
-                                               __func__, gpio->name,
-                                               gpio->gpio, ret);
-                                       return ret;
-                               }
-                               fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par,
-                                       "%s: '%s' = GPIO%d\n",
-                                       __func__, gpio->name, gpio->gpio);
+       if (!(pdata && pdata->gpios))
+               return 0;
+
+       gpio = pdata->gpios;
+       while (gpio->name[0]) {
+               flags = FBTFT_GPIO_NO_MATCH;
+               /* if driver provides match function, try it first,
+                  if no match use our own */
+               if (par->fbtftops.request_gpios_match)
+                       flags = par->fbtftops.request_gpios_match(par, gpio);
+               if (flags == FBTFT_GPIO_NO_MATCH)
+                       flags = fbtft_request_gpios_match(par, gpio);
+               if (flags != FBTFT_GPIO_NO_MATCH) {
+                       ret = devm_gpio_request_one(par->info->device,
+                                       gpio->gpio, flags,
+                                       par->info->device->driver->name);
+                       if (ret < 0) {
+                               dev_err(par->info->device,
+                                       "%s: gpio_request_one('%s'=%d) failed with %d\n",
+                                       __func__, gpio->name,
+                                       gpio->gpio, ret);
+                               return ret;
                        }
-                       gpio++;
+                       fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par,
+                               "%s: '%s' = GPIO%d\n",
+                               __func__, gpio->name, gpio->gpio);
                }
+               gpio++;
        }
 
        return 0;
@@ -268,26 +266,23 @@ static int fbtft_backlight_get_brightness(struct backlight_device *bd)
 
 void fbtft_unregister_backlight(struct fbtft_par *par)
 {
-       const struct backlight_ops *bl_ops;
-
-       fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__);
-
        if (par->info->bl_dev) {
                par->info->bl_dev->props.power = FB_BLANK_POWERDOWN;
                backlight_update_status(par->info->bl_dev);
-               bl_ops = par->info->bl_dev->ops;
                backlight_device_unregister(par->info->bl_dev);
                par->info->bl_dev = NULL;
        }
 }
 
+static const struct backlight_ops fbtft_bl_ops = {
+       .get_brightness = fbtft_backlight_get_brightness,
+       .update_status  = fbtft_backlight_update_status,
+};
+
 void fbtft_register_backlight(struct fbtft_par *par)
 {
        struct backlight_device *bd;
        struct backlight_properties bl_props = { 0, };
-       struct backlight_ops *bl_ops;
-
-       fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__);
 
        if (par->gpio.led[0] == -1) {
                fbtft_par_dbg(DEBUG_BACKLIGHT, par,
@@ -295,13 +290,6 @@ void fbtft_register_backlight(struct fbtft_par *par)
                return;
        }
 
-       bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops),
-                               GFP_KERNEL);
-       if (!bl_ops)
-               return;
-
-       bl_ops->get_brightness = fbtft_backlight_get_brightness;
-       bl_ops->update_status = fbtft_backlight_update_status;
        bl_props.type = BACKLIGHT_RAW;
        /* Assume backlight is off, get polarity from current state of pin */
        bl_props.power = FB_BLANK_POWERDOWN;
@@ -309,7 +297,7 @@ void fbtft_register_backlight(struct fbtft_par *par)
                bl_props.state |= BL_CORE_DRIVER1;
 
        bd = backlight_device_register(dev_driver_string(par->info->device),
-                               par->info->device, par, bl_ops, &bl_props);
+                               par->info->device, par, &fbtft_bl_ops, &bl_props);
        if (IS_ERR(bd)) {
                dev_err(par->info->device,
                        "cannot register backlight device (%ld)\n",
@@ -331,9 +319,6 @@ EXPORT_SYMBOL(fbtft_unregister_backlight);
 static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe,
                               int ye)
 {
-       fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
-               "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye);
-
        /* Column address set */
        write_reg(par, 0x2A,
                (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
@@ -346,7 +331,6 @@ static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe,
        write_reg(par, 0x2C);
 }
 
-
 static void fbtft_reset(struct fbtft_par *par)
 {
        if (par->gpio.reset == -1)
@@ -358,13 +342,11 @@ static void fbtft_reset(struct fbtft_par *par)
        mdelay(120);
 }
 
-
 static void fbtft_update_display(struct fbtft_par *par, unsigned start_line,
                                 unsigned end_line)
 {
        size_t offset, len;
-       struct timespec ts_start, ts_end, ts_fps, ts_duration;
-       long fps_ms, fps_us, duration_ms, duration_us;
+       ktime_t ts_start, ts_end;
        long fps, throughput;
        bool timeit = false;
        int ret = 0;
@@ -372,7 +354,7 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned start_line,
        if (unlikely(par->debug & (DEBUG_TIME_FIRST_UPDATE | DEBUG_TIME_EACH_UPDATE))) {
                if ((par->debug & DEBUG_TIME_EACH_UPDATE) ||
                                ((par->debug & DEBUG_TIME_FIRST_UPDATE) && !par->first_update_done)) {
-                       getnstimeofday(&ts_start);
+                       ts_start = ktime_get();
                        timeit = true;
                }
        }
@@ -398,7 +380,7 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned start_line,
 
        if (par->fbtftops.set_addr_win)
                par->fbtftops.set_addr_win(par, 0, start_line,
-                               par->info->var.xres-1, end_line);
+                               par->info->var.xres - 1, end_line);
 
        offset = start_line * par->info->fix.line_length;
        len = (end_line - start_line + 1) * par->info->fix.line_length;
@@ -409,35 +391,25 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned start_line,
                        __func__);
 
        if (unlikely(timeit)) {
-               getnstimeofday(&ts_end);
-               if (par->update_time.tv_nsec == 0 && par->update_time.tv_sec == 0) {
-                       par->update_time.tv_sec = ts_start.tv_sec;
-                       par->update_time.tv_nsec = ts_start.tv_nsec;
-               }
-               ts_fps = timespec_sub(ts_start, par->update_time);
-               par->update_time.tv_sec = ts_start.tv_sec;
-               par->update_time.tv_nsec = ts_start.tv_nsec;
-               fps_ms = (ts_fps.tv_sec * 1000) + ((ts_fps.tv_nsec / 1000000) % 1000);
-               fps_us = (ts_fps.tv_nsec / 1000) % 1000;
-               fps = fps_ms * 1000 + fps_us;
+               ts_end = ktime_get();
+               if (ktime_to_ns(par->update_time))
+                       par->update_time = ts_start;
+
+               par->update_time = ts_start;
+               fps = ktime_us_delta(ts_start, par->update_time);
                fps = fps ? 1000000 / fps : 0;
 
-               ts_duration = timespec_sub(ts_end, ts_start);
-               duration_ms = (ts_duration.tv_sec * 1000) + ((ts_duration.tv_nsec / 1000000) % 1000);
-               duration_us = (ts_duration.tv_nsec / 1000) % 1000;
-               throughput = duration_ms * 1000 + duration_us;
+               throughput = ktime_us_delta(ts_end, ts_start);
                throughput = throughput ? (len * 1000) / throughput : 0;
                throughput = throughput * 1000 / 1024;
 
                dev_info(par->info->device,
-                       "Display update: %ld kB/s (%ld.%.3ld ms), fps=%ld (%ld.%.3ld ms)\n",
-                       throughput, duration_ms, duration_us,
-                       fps, fps_ms, fps_us);
+                       "Display update: %ld kB/s, fps=%ld\n",
+                       throughput, fps);
                par->first_update_done = true;
        }
 }
 
-
 static void fbtft_mkdirty(struct fb_info *info, int y, int height)
 {
        struct fbtft_par *par = info->par;
@@ -484,7 +456,7 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
                index = page->index << PAGE_SHIFT;
                y_low = index / info->fix.line_length;
                y_high = (index + PAGE_SIZE - 1) / info->fix.line_length;
-               fbtft_dev_dbg(DEBUG_DEFERRED_IO, par, info->device,
+               dev_dbg(info->device,
                        "page->index=%lu y_low=%d y_high=%d\n",
                        page->index, y_low, y_high);
                if (y_high > info->var.yres - 1)
@@ -499,13 +471,12 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
                                        dirty_lines_start, dirty_lines_end);
 }
 
-
 static void fbtft_fb_fillrect(struct fb_info *info,
                              const struct fb_fillrect *rect)
 {
        struct fbtft_par *par = info->par;
 
-       fbtft_dev_dbg(DEBUG_FB_FILLRECT, par, info->dev,
+       dev_dbg(info->dev,
                "%s: dx=%d, dy=%d, width=%d, height=%d\n",
                __func__, rect->dx, rect->dy, rect->width, rect->height);
        sys_fillrect(info, rect);
@@ -518,7 +489,7 @@ static void fbtft_fb_copyarea(struct fb_info *info,
 {
        struct fbtft_par *par = info->par;
 
-       fbtft_dev_dbg(DEBUG_FB_COPYAREA, par, info->dev,
+       dev_dbg(info->dev,
                "%s: dx=%d, dy=%d, width=%d, height=%d\n",
                __func__,  area->dx, area->dy, area->width, area->height);
        sys_copyarea(info, area);
@@ -531,7 +502,7 @@ static void fbtft_fb_imageblit(struct fb_info *info,
 {
        struct fbtft_par *par = info->par;
 
-       fbtft_dev_dbg(DEBUG_FB_IMAGEBLIT, par, info->dev,
+       dev_dbg(info->dev,
                "%s: dx=%d, dy=%d, width=%d, height=%d\n",
                __func__,  image->dx, image->dy, image->width, image->height);
        sys_imageblit(info, image);
@@ -545,7 +516,7 @@ static ssize_t fbtft_fb_write(struct fb_info *info, const char __user *buf,
        struct fbtft_par *par = info->par;
        ssize_t res;
 
-       fbtft_dev_dbg(DEBUG_FB_WRITE, par, info->dev,
+       dev_dbg(info->dev,
                "%s: count=%zd, ppos=%llu\n", __func__,  count, *ppos);
        res = fb_sys_write(info, buf, count, ppos);
 
@@ -568,11 +539,10 @@ static int fbtft_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                              unsigned blue, unsigned transp,
                              struct fb_info *info)
 {
-       struct fbtft_par *par = info->par;
        unsigned val;
        int ret = 1;
 
-       fbtft_dev_dbg(DEBUG_FB_SETCOLREG, par, info->dev,
+       dev_dbg(info->dev,
                "%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
                __func__, regno, red, green, blue, transp);
 
@@ -599,7 +569,7 @@ static int fbtft_fb_blank(int blank, struct fb_info *info)
        struct fbtft_par *par = info->par;
        int ret = -EINVAL;
 
-       fbtft_dev_dbg(DEBUG_FB_BLANK, par, info->dev, "%s(blank=%d)\n",
+       dev_dbg(info->dev, "%s(blank=%d)\n",
                __func__, blank);
 
        if (!par->fbtftops.blank)
@@ -676,13 +646,13 @@ static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src)
  *
  */
 struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
-                                       struct device *dev)
+                                       struct device *dev,
+                                       struct fbtft_platform_data *pdata)
 {
        struct fb_info *info;
        struct fbtft_par *par;
        struct fb_ops *fbops = NULL;
        struct fb_deferred_io *fbdefio = NULL;
-       struct fbtft_platform_data *pdata = dev->platform_data;
        u8 *vmem = NULL;
        void *txbuf = NULL;
        void *buf = NULL;
@@ -778,7 +748,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
        if (!info)
                goto alloc_fail;
 
-       info->screen_base = (u8 __force __iomem *)vmem;
+       info->screen_buffer = vmem;
        info->fbops = fbops;
        info->fbdefio = fbdefio;
 
@@ -801,7 +771,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
        info->fix.xpanstep =       0;
        info->fix.ypanstep =       0;
        info->fix.ywrapstep =      0;
-       info->fix.line_length =    width*bpp/8;
+       info->fix.line_length =    width * bpp / 8;
        info->fix.accel =          FB_ACCEL_NONE;
        info->fix.smem_len =       vmem_size;
 
@@ -827,7 +797,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 
        par = info->par;
        par->info = info;
-       par->pdata = dev->platform_data;
+       par->pdata = pdata;
        par->debug = display->debug;
        par->buf = buf;
        spin_lock_init(&par->dirty_lock);
@@ -856,10 +826,13 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 #endif
 
        if (txbuflen > 0) {
+#ifdef CONFIG_HAS_DMA
                if (dma) {
                        dev->coherent_dma_mask = ~0;
                        txbuf = dmam_alloc_coherent(dev, txbuflen, &par->txbuf.dma, GFP_DMA);
-               } else {
+               } else
+#endif
+               {
                        txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
                }
                if (!txbuf)
@@ -915,7 +888,7 @@ EXPORT_SYMBOL(fbtft_framebuffer_alloc);
 void fbtft_framebuffer_release(struct fb_info *info)
 {
        fb_deferred_io_cleanup(info);
-       vfree(info->screen_base);
+       vfree(info->screen_buffer);
        framebuffer_release(info);
 }
 EXPORT_SYMBOL(fbtft_framebuffer_release);
@@ -994,12 +967,12 @@ int fbtft_register_framebuffer(struct fb_info *fb_info)
                        par->txbuf.len >> 10, par->txbuf.dma ? "DMA " : "");
        if (spi)
                sprintf(text2, ", spi%d.%d at %d MHz", spi->master->bus_num,
-                               spi->chip_select, spi->max_speed_hz/1000000);
+                       spi->chip_select, spi->max_speed_hz / 1000000);
        dev_info(fb_info->dev,
                "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
                fb_info->fix.id, fb_info->var.xres, fb_info->var.yres,
                fb_info->fix.smem_len >> 10, text1,
-               HZ/fb_info->fbdefio->delay, text2);
+               HZ / fb_info->fbdefio->delay, text2);
 
 #ifdef CONFIG_FB_BACKLIGHT
        /* Turn on backlight if available */
@@ -1062,10 +1035,6 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
        const __be32 *p;
        u32 val;
        int buf[64], i, j;
-       char msg[128];
-       char str[16];
-
-       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
 
        if (!node)
                return -EINVAL;
@@ -1074,6 +1043,11 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
        p = of_prop_next_u32(prop, NULL, &val);
        if (!p)
                return -EINVAL;
+
+       par->fbtftops.reset(par);
+       if (par->gpio.cs != -1)
+               gpio_set_value(par->gpio.cs, 0);  /* Activate chip */
+
        while (p) {
                if (val & FBTFT_OF_INIT_CMD) {
                        val &= 0xFFFF;
@@ -1089,13 +1063,11 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
                                p = of_prop_next_u32(prop, p, &val);
                        }
                        /* make debug message */
-                       msg[0] = '\0';
-                       for (j = 0; j < i; j++) {
-                               snprintf(str, 128, " %02X", buf[j]);
-                               strcat(msg, str);
-                       }
                        fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
-                               "init: write_register:%s\n", msg);
+                               "init: write_register:\n");
+                       for (j = 0; j < i; j++)
+                               fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
+                                             "buf[%d] = %02X\n", j, buf[j]);
 
                        par->fbtftops.write_register(par, i,
                                buf[0], buf[1], buf[2], buf[3],
@@ -1146,8 +1118,6 @@ int fbtft_init_display(struct fbtft_par *par)
        int i = 0;
        int j;
 
-       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
-
        /* sanity check */
        if (!par->init_sequence) {
                dev_err(par->info->device,
@@ -1180,7 +1150,7 @@ int fbtft_init_display(struct fbtft_par *par)
                                "missing delimiter at position %d\n", i);
                        return -EINVAL;
                }
-               if (par->init_sequence[i+1] < 0) {
+               if (par->init_sequence[i + 1] < 0) {
                        dev_err(par->info->device,
                                "missing value after delimiter %d at position %d\n",
                                par->init_sequence[i], i);
@@ -1260,12 +1230,11 @@ EXPORT_SYMBOL(fbtft_init_display);
  */
 static int fbtft_verify_gpios(struct fbtft_par *par)
 {
-       struct fbtft_platform_data *pdata;
+       struct fbtft_platform_data *pdata = par->pdata;
        int i;
 
        fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
 
-       pdata = par->info->device->platform_data;
        if (pdata->display.buswidth != 9 && par->startbyte == 0 &&
                                                        par->gpio.dc < 0) {
                dev_err(par->info->device,
@@ -1383,10 +1352,9 @@ int fbtft_probe_common(struct fbtft_display *display,
                pdata = fbtft_probe_dt(dev);
                if (IS_ERR(pdata))
                        return PTR_ERR(pdata);
-               dev->platform_data = pdata;
        }
 
-       info = fbtft_framebuffer_alloc(display, dev);
+       info = fbtft_framebuffer_alloc(display, dev, pdata);
        if (!info)
                return -ENOMEM;
 
@@ -1433,15 +1401,11 @@ int fbtft_probe_common(struct fbtft_display *display,
 
        /* 9-bit SPI setup */
        if (par->spi && display->buswidth == 9) {
-               par->spi->bits_per_word = 9;
-               ret = par->spi->master->setup(par->spi);
-               if (ret) {
+               if (par->spi->master->bits_per_word_mask & SPI_BPW_MASK(9)) {
+                       par->spi->bits_per_word = 9;
+               } else {
                        dev_warn(&par->spi->dev,
                                "9-bit SPI not available, emulating using 8-bit.\n");
-                       par->spi->bits_per_word = 8;
-                       ret = par->spi->master->setup(par->spi);
-                       if (ret)
-                               goto out_release;
                        /* allocate buffer with room for dc bits */
                        par->extra = devm_kzalloc(par->info->device,
                                par->txbuf.len + (par->txbuf.len / 8) + 8,