My luckfox pico study
- luckfox (rv1103) 烧录tf卡时,如果提示update错误,解决办法是选择启动文件(上面的按钮)时
不要添加update.img文件进去,点创建tf卡时就不会提示update分区错误
- not good (without CONFIG_FB_TFT) : https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-LVGL/
- better (with CONFIG_FB_TFT) : https://spotpear.cn/index/study/detail/id/1308.html
- for luckfox pico rv1103g1 (not pro/max), BLK=0A4,DC=1A2
luckfox pico, usb north
left top 1,TX<->RXD USB-TTL
left top 2,RX<->TXD USB-TTL
left top 3,GND<->GND USB-TTL
left bottom 3, GND<->GND,1.3' IPS_LCD 240x240
right top 5, 3V3(OUT)<->VCC
left bottom 7,1C1 <->SCL,same
left bottom 6,1C2 <->SDA,same
left bottom 5,1C3 <->RES,same
left bottom 10,1A2 <->DC
left bottom 9,1C0 <->CS,same
left bottom 4,0A4 <->BLK
- luckfox_rv1106_linux_defconfig
#spi lcd -- st7789V
CONFIG_SPI_MASTER=y
CONFIG_SPI_DESIGNWARE=y
CONFIG_SPI_DW_MMIO=y
CONFIG_FB=y
CONFIG_FB_TFT=y
CONFIG_FB_TFT_ST7789V=y
- rv1103g-luckfox-pico.dts
- inside / {
/*LCD_BL*/
gpio0pa4:gpio0pa4 {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&gpio0_pa4>;
regulator-name = "gpio0_pa4";
regulator-always-on;
};
/*LCD_DC*/
gpio1pa2:gpio1pa2 {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&gpio1_pa2>;
regulator-name = "gpio1_pa2";
regulator-always-on;
};
/*LCD_RES*/
gpio1pc3:gpio1pc3 {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&gpio1_pc3>;
regulator-name = "gpio1_pc3";
regulator-always-on;
};
- inside &pinctrl {
/*LCD_BL*/
gpio0-pa4 {
gpio0_pa4:gpio0-pa4 {
rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
/*LCD_DC*/
gpio1-pa2 {
gpio1_pa2:gpio1-pa2 {
rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
/*LCD_RES*/
gpio1-pc3 {
gpio1_pc3:gpio1-pc3 {
rockchip,pins = <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
- replace &spi0 {
&spi0 {
// status = "okay";
// pinctrl-names = "default";
// pinctrl-0 = <&spi0m0_cs0 &spi0m0_pins>;
// st7789v@0{
// status = "okay";
// compatible = "sitronix,st7789v";
// reg = <0>;
// spi-max-frequency = <20000000>;
// fps = <30>;
// buswidth = <8>;
// debug = <0x7>;
// led-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;//BL
// dc = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; //DC
// reset = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; //RES
// };
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0m0_pins>;
// cs-gpios = <&gpio1 RK_PC0 1>;
// cs-gpios = <&gpio1 26 1>;
#address-cells = <1>;
#size-cells = <0>;
lcd: lcd@0{
status = "okay";
compatible = "sitronix,st7789v";
reg = <0>;
spi-max-frequency = <20000000>;
spi-cpol;
spi-cpha;
rotate = <0>;
fps = <30>;
rgb;
buswidth = <8>;
cs = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>; //spi0_miso
led = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; //BL
dc = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; //DC
reset = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; //RES
debug = <0x7>;
};
};
&pinctrl {
spi0 {
/omit-if-no-ref/
spi0m0_pins: spi0m0-pins {
rockchip,pins =
/* spi0_clk_m0 */
<1 RK_PC1 4 &pcfg_pull_none>,
/* spie_miso_m0 */
// <1 RK_PC3 6 &pcfg_pull_none>,
/* spi_mosi_m0 */
<1 RK_PC2 6 &pcfg_pull_none>;
};
};
};
- fbtft-core.c
- include
#include <linux/gpio.h> //added
#include <linux/of_gpio.h> //added
- fbtft_request_one_gpio
static int fbtft_request_one_gpio(struct fbtft_par *par,
const char *name, int index,
struct gpio_desc **gpiop)
{
#if 0
struct device *dev = par->info->device;
*gpiop = devm_gpiod_get_index_optional(dev, name, index,
GPIOD_OUT_LOW);
if (IS_ERR(*gpiop))
return dev_err_probe(dev, PTR_ERR(*gpiop), "Failed to request %s GPIO\n", name);
fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
__func__, name);
return 0;
#else
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;
#endif
}
- fbtft_reset
static void fbtft_reset(struct fbtft_par *par)
{
#if 0
if (!par->gpio.reset)
return;
fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
gpiod_set_value_cansleep(par->gpio.reset, 1);
usleep_range(20, 40);
gpiod_set_value_cansleep(par->gpio.reset, 0);
msleep(120);
gpiod_set_value_cansleep(par->gpio.cs, 1); /* Activate chip */
#else
if (!par->gpio.reset)
return;
fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
gpiod_set_value_cansleep(par->gpio.reset, 1);
usleep_range(20, 40);
gpiod_set_value_cansleep(par->gpio.reset, 0);
msleep(120);
gpiod_set_value_cansleep(par->gpio.reset, 1);
msleep(120);
gpiod_set_value_cansleep(par->gpio.cs, 0); /* Activate chip */
msleep(120);
#endif
}
- fbtft_properties_read
static struct fbtft_platform_data *fbtft_properties_read(struct device *dev)
{
#if 0
struct fbtft_platform_data *pdata;
if (!dev_fwnode(dev)) {
dev_err(dev, "Missing platform data or properties\n");
return ERR_PTR(-EINVAL);
}
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
pdata->display.width = fbtft_property_value(dev, "width");
pdata->display.height = fbtft_property_value(dev, "height");
pdata->display.regwidth = fbtft_property_value(dev, "regwidth");
pdata->display.buswidth = fbtft_property_value(dev, "buswidth");
pdata->display.backlight = fbtft_property_value(dev, "backlight");
pdata->display.bpp = fbtft_property_value(dev, "bpp");
pdata->display.debug = fbtft_property_value(dev, "debug");
pdata->rotate = fbtft_property_value(dev, "rotate");
pdata->bgr = device_property_read_bool(dev, "bgr");
pdata->fps = fbtft_property_value(dev, "fps");
pdata->txbuflen = fbtft_property_value(dev, "txbuflen");
pdata->startbyte = fbtft_property_value(dev, "startbyte");
device_property_read_string(dev, "gamma", (const char **)&pdata->gamma);
if (device_property_present(dev, "led-gpios"))
pdata->display.backlight = 1;
if (device_property_present(dev, "init"))
pdata->display.fbtftops.init_display =
fbtft_init_display_from_property;
pdata->display.fbtftops.request_gpios = fbtft_request_gpios;
return pdata;
#else
struct fbtft_platform_data *pdata;
if (!dev_fwnode(dev)) {
dev_err(dev, "Missing platform data or properties\n");
return ERR_PTR(-EINVAL);
}
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
pdata->display.width = fbtft_property_value(dev, "width");
pdata->display.height = fbtft_property_value(dev, "height");
pdata->display.regwidth = fbtft_property_value(dev, "regwidth");
pdata->display.buswidth = fbtft_property_value(dev, "buswidth");
pdata->display.backlight = fbtft_property_value(dev, "backlight");
pdata->display.bpp = fbtft_property_value(dev, "bpp");
pdata->display.debug = fbtft_property_value(dev, "debug");
pdata->rotate = fbtft_property_value(dev, "rotate");
pdata->bgr = device_property_read_bool(dev, "bgr");
pdata->fps = fbtft_property_value(dev, "fps");
pdata->txbuflen = fbtft_property_value(dev, "txbuflen");
pdata->startbyte = fbtft_property_value(dev, "startbyte");
device_property_read_string(dev, "gamma", (const char **)&pdata->gamma);
if (device_property_present(dev, "led"))
pdata->display.backlight = 1;
if (device_property_present(dev, "init"))
pdata->display.fbtftops.init_display =
fbtft_init_display_from_property;
pdata->display.fbtftops.request_gpios = fbtft_request_gpios;
return pdata;
#endif
}