linux下对fbtft的修改支持
由于fbtft是很久前开发的驱动,后面更新内核后没有更新。所以要做一些修改才可以使用。
找到ili9341驱动文件:"duo-buildroot-sdk/linux_5.10/drivers/staging/fbtft/fbtft-core.c""
修改fbtft_request_one_gpio函数
static int fbtft_request_one_gpio(struct fbtft_par *par, const char *name, int index, struct gpio_desc **gpiop) { struct device *dev = par->info->device; struct device_node *node = dev->of_node; int gpio, flags, ret = 0; enum of_gpio_flags of_flags; if (of_find_property(node, name, NULL)) { gpio = of_get_named_gpio_flags(node, name, index, &of_flags); if (gpio == -ENOENT) return 0; if (gpio == -EPROBE_DEFER) return gpio; if (gpio < 0) { dev_err(dev, "failed to get '%s' from DT\n", name); return gpio; } //active low translates to initially low flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ret = devm_gpio_request_one(dev, gpio, flags, dev->driver->name); if (ret) { dev_err(dev, "gpio_request_one('%s'=%d) failed with %d\n", name, gpio, ret); return ret; } *gpiop = gpio_to_desc(gpio); fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n", __func__, name, gpio); } return ret; }
继续:fbtft_reset函数
static void fbtft_reset(struct fbtft_par *par) { if (!par->gpio.reset) return; fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); gpiod_set_value_cansleep(par->gpio.reset, 1); msleep(10); gpiod_set_value_cansleep(par->gpio.reset, 0); msleep(200); gpiod_set_value_cansleep(par->gpio.reset, 1); msleep(10); }
下面这个地方我没有修改已经可以正常运行了。"duo-buildroot-sdk/linux_5.10/drivers/staging/fbtft/fbtft-bus.c"文件中的:fbtft_write_vmem16_bus8函数
int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) { u16 *vmem16; __be16 *txbuf16 = par->txbuf.buf; size_t remain; size_t to_copy; size_t tx_array_size; int i; int ret = 0; size_t startbyte_size = 0; fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", __func__, offset, len); remain = len / 2; vmem16 = (u16 *)(par->info->screen_buffer + offset); if (par->gpio.dc) { //printk("dc拉高!\n"); gpiod_set_value(par->gpio.dc, 1); } /* non buffered write */ if (!par->txbuf.buf) return par->fbtftops.write(par, vmem16, len); /* buffered write */ tx_array_size = par->txbuf.len / 2; if (par->startbyte) { txbuf16 = par->txbuf.buf + 1; tx_array_size -= 2; *(u8 *)(par->txbuf.buf) = par->startbyte | 0x2; startbyte_size = 1; } while (remain) { to_copy = min(tx_array_size, remain); dev_dbg(par->info->device, "to_copy=%zu, remain=%zu\n", to_copy, remain - to_copy); for (i = 0; i < to_copy; i++) txbuf16[i] = cpu_to_be16(vmem16[i]); vmem16 = vmem16 + to_copy; ret = par->fbtftops.write(par, par->txbuf.buf, startbyte_size + to_copy * 2); if (ret < 0) return ret; remain -= to_copy; } return ret; }
更多的也可以查看我另外一篇文章:linux 添加ili9341屏的驱动