From 7b5ab6437961f5e37ab9adfae18cf1671e39e7a3 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:17 +0200 Subject: [PATCH 1/7] ARM: davinci: da850-evm: model the backlight GPIO as an actual device Instead of enabling the panel backlight in a callback defined in board file using deprecated legacy GPIO API calls, model the line as a GPIO backlight device. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/board-da850-evm.c | 42 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 0628e7d7dcf3..ac05d4838f1e 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -804,34 +805,49 @@ static const short da850_evm_mmcsd0_pins[] __initconst = { static void da850_panel_power_ctrl(int val) { - /* lcd backlight */ - gpio_set_value(DA850_LCD_BL_PIN, val); - /* lcd power */ gpio_set_value(DA850_LCD_PWR_PIN, val); } +static struct property_entry da850_lcd_backlight_props[] = { + PROPERTY_ENTRY_BOOL("default-on"), + { } +}; + +static struct gpiod_lookup_table da850_lcd_backlight_gpio_table = { + .dev_id = "gpio-backlight", + .table = { + GPIO_LOOKUP("davinci_gpio", DA850_LCD_BL_PIN, NULL, 0), + { } + }, +}; + +static const struct platform_device_info da850_lcd_backlight_info = { + .name = "gpio-backlight", + .id = PLATFORM_DEVID_NONE, + .properties = da850_lcd_backlight_props, +}; + static int da850_lcd_hw_init(void) { + struct platform_device *backlight; int status; - status = gpio_request(DA850_LCD_BL_PIN, "lcd bl"); + gpiod_add_lookup_table(&da850_lcd_backlight_gpio_table); + backlight = platform_device_register_full(&da850_lcd_backlight_info); + if (IS_ERR(backlight)) + return PTR_ERR(backlight); + + status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr"); if (status < 0) return status; - status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr"); - if (status < 0) { - gpio_free(DA850_LCD_BL_PIN); - return status; - } - - gpio_direction_output(DA850_LCD_BL_PIN, 0); gpio_direction_output(DA850_LCD_PWR_PIN, 0); - /* Switch off panel power and backlight */ + /* Switch off panel power */ da850_panel_power_ctrl(0); - /* Switch on panel power and backlight */ + /* Switch on panel power */ da850_panel_power_ctrl(1); return 0; From 611097d5daea95688e9187a53f36a8c743eaa0b8 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:18 +0200 Subject: [PATCH 2/7] fbdev: da8xx: add support for a regulator We want to remove the hacky platform data callback for power control. Add a regulator to the driver data and enable/disable it next to the current panel_power_ctrl() calls. We will use it in subsequent patch on da850-evm. Signed-off-by: Bartosz Golaszewski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sekhar Nori --- drivers/video/fbdev/da8xx-fb.c | 54 ++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index b1cf248f3291..02dfe9e32eed 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,7 @@ struct da8xx_fb_par { #endif unsigned int lcdc_clk_rate; void (*panel_power_ctrl)(int); + struct regulator *lcd_supply; u32 pseudo_palette[16]; struct fb_videomode mode; struct lcd_ctrl_config cfg; @@ -1066,6 +1068,7 @@ static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) static int fb_remove(struct platform_device *dev) { struct fb_info *info = dev_get_drvdata(&dev->dev); + int ret; if (info) { struct da8xx_fb_par *par = info->par; @@ -1073,8 +1076,13 @@ static int fb_remove(struct platform_device *dev) #ifdef CONFIG_CPU_FREQ lcd_da8xx_cpufreq_deregister(par); #endif - if (par->panel_power_ctrl) + if (par->panel_power_ctrl) { par->panel_power_ctrl(0); + } else if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; + } lcd_disable_raster(DA8XX_FRAME_WAIT); lcdc_write(0, LCD_RASTER_CTRL_REG); @@ -1179,15 +1187,25 @@ static int cfb_blank(int blank, struct fb_info *info) case FB_BLANK_UNBLANK: lcd_enable_raster(); - if (par->panel_power_ctrl) + if (par->panel_power_ctrl) { par->panel_power_ctrl(1); + } else if (par->lcd_supply) { + ret = regulator_enable(par->lcd_supply); + if (ret) + return ret; + } break; case FB_BLANK_NORMAL: case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: - if (par->panel_power_ctrl) + if (par->panel_power_ctrl) { par->panel_power_ctrl(0); + } else if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; + } lcd_disable_raster(DA8XX_FRAME_WAIT); break; @@ -1400,6 +1418,20 @@ static int fb_probe(struct platform_device *device) par->panel_power_ctrl(1); } + par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd"); + if (IS_ERR(par->lcd_supply)) { + if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_pm_runtime_disable; + } + + par->lcd_supply = NULL; + } else { + ret = regulator_enable(par->lcd_supply); + if (ret) + goto err_pm_runtime_disable; + } + fb_videomode_to_var(&da8xx_fb_var, lcdc_info); par->cfg = *lcd_cfg; @@ -1603,10 +1635,16 @@ static int fb_suspend(struct device *dev) { struct fb_info *info = dev_get_drvdata(dev); struct da8xx_fb_par *par = info->par; + int ret; console_lock(); - if (par->panel_power_ctrl) + if (par->panel_power_ctrl) { par->panel_power_ctrl(0); + } else if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; + } fb_set_suspend(info, 1); lcd_disable_raster(DA8XX_FRAME_WAIT); @@ -1620,6 +1658,7 @@ static int fb_resume(struct device *dev) { struct fb_info *info = dev_get_drvdata(dev); struct da8xx_fb_par *par = info->par; + int ret; console_lock(); pm_runtime_get_sync(dev); @@ -1627,8 +1666,13 @@ static int fb_resume(struct device *dev) if (par->blank == FB_BLANK_UNBLANK) { lcd_enable_raster(); - if (par->panel_power_ctrl) + if (par->panel_power_ctrl) { par->panel_power_ctrl(1); + } else if (par->lcd_supply) { + ret = regulator_enable(par->lcd_supply); + if (ret) + return ret; + } } fb_set_suspend(info, 0); From 9c65754cd32ffebf1f2adf4e740d2688f6fe0290 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:19 +0200 Subject: [PATCH 3/7] ARM: davinci: da850-evm: switch to using a fixed regulator for lcdc Now that the da8xx fbdev driver supports power control with an actual regulator, switch to using a fixed power supply for da850-evm. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij Signed-off-by: Sekhar Nori --- arch/arm/mach-davinci/board-da850-evm.c | 62 ++++++++++++++++++------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index ac05d4838f1e..5b3549f1236c 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -803,12 +803,6 @@ static const short da850_evm_mmcsd0_pins[] __initconst = { -1 }; -static void da850_panel_power_ctrl(int val) -{ - /* lcd power */ - gpio_set_value(DA850_LCD_PWR_PIN, val); -} - static struct property_entry da850_lcd_backlight_props[] = { PROPERTY_ENTRY_BOOL("default-on"), { } @@ -828,28 +822,61 @@ static const struct platform_device_info da850_lcd_backlight_info = { .properties = da850_lcd_backlight_props, }; +static struct regulator_consumer_supply da850_lcd_supplies[] = { + REGULATOR_SUPPLY("lcd", NULL), +}; + +static struct regulator_init_data da850_lcd_supply_data = { + .consumer_supplies = da850_lcd_supplies, + .num_consumer_supplies = ARRAY_SIZE(da850_lcd_supplies), + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config da850_lcd_supply = { + .supply_name = "lcd", + .microvolts = 33000000, + .init_data = &da850_lcd_supply_data, +}; + +static struct platform_device da850_lcd_supply_device = { + .name = "reg-fixed-voltage", + .id = 1, /* Dummy fixed regulator is 0 */ + .dev = { + .platform_data = &da850_lcd_supply, + }, +}; + +static struct gpiod_lookup_table da850_lcd_supply_gpio_table = { + .dev_id = "reg-fixed-voltage.1", + .table = { + GPIO_LOOKUP("davinci_gpio", DA850_LCD_PWR_PIN, NULL, 0), + { } + }, +}; + +static struct gpiod_lookup_table *da850_lcd_gpio_lookups[] = { + &da850_lcd_backlight_gpio_table, + &da850_lcd_supply_gpio_table, +}; + static int da850_lcd_hw_init(void) { struct platform_device *backlight; int status; - gpiod_add_lookup_table(&da850_lcd_backlight_gpio_table); + gpiod_add_lookup_tables(da850_lcd_gpio_lookups, + ARRAY_SIZE(da850_lcd_gpio_lookups)); + backlight = platform_device_register_full(&da850_lcd_backlight_info); if (IS_ERR(backlight)) return PTR_ERR(backlight); - status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr"); - if (status < 0) + status = platform_device_register(&da850_lcd_supply_device); + if (status) return status; - gpio_direction_output(DA850_LCD_PWR_PIN, 0); - - /* Switch off panel power */ - da850_panel_power_ctrl(0); - - /* Switch on panel power */ - da850_panel_power_ctrl(1); - return 0; } @@ -1459,7 +1486,6 @@ static __init void da850_evm_init(void) if (ret) pr_warn("%s: LCD initialization failed: %d\n", __func__, ret); - sharp_lk043t1dg01_pdata.panel_power_ctrl = da850_panel_power_ctrl, ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata); if (ret) pr_warn("%s: LCDC registration failed: %d\n", __func__, ret); From 3fca9e0be9b5b7f4ccd5f71941143d9719047a05 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:20 +0200 Subject: [PATCH 4/7] fbdev: da8xx: remove panel_power_ctrl() callback from platform data There are no more users of panel_power_ctrl(). Remove it from the driver. Signed-off-by: Bartosz Golaszewski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sekhar Nori --- drivers/video/fbdev/da8xx-fb.c | 25 +++++-------------------- include/video/da8xx-fb.h | 1 - 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index 02dfe9e32eed..19ed9889c8f8 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -165,7 +165,6 @@ struct da8xx_fb_par { struct notifier_block freq_transition; #endif unsigned int lcdc_clk_rate; - void (*panel_power_ctrl)(int); struct regulator *lcd_supply; u32 pseudo_palette[16]; struct fb_videomode mode; @@ -1076,9 +1075,7 @@ static int fb_remove(struct platform_device *dev) #ifdef CONFIG_CPU_FREQ lcd_da8xx_cpufreq_deregister(par); #endif - if (par->panel_power_ctrl) { - par->panel_power_ctrl(0); - } else if (par->lcd_supply) { + if (par->lcd_supply) { ret = regulator_disable(par->lcd_supply); if (ret) return ret; @@ -1187,9 +1184,7 @@ static int cfb_blank(int blank, struct fb_info *info) case FB_BLANK_UNBLANK: lcd_enable_raster(); - if (par->panel_power_ctrl) { - par->panel_power_ctrl(1); - } else if (par->lcd_supply) { + if (par->lcd_supply) { ret = regulator_enable(par->lcd_supply); if (ret) return ret; @@ -1199,9 +1194,7 @@ static int cfb_blank(int blank, struct fb_info *info) case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: - if (par->panel_power_ctrl) { - par->panel_power_ctrl(0); - } else if (par->lcd_supply) { + if (par->lcd_supply) { ret = regulator_disable(par->lcd_supply); if (ret) return ret; @@ -1413,10 +1406,6 @@ static int fb_probe(struct platform_device *device) par->dev = &device->dev; par->lcdc_clk = tmp_lcdc_clk; par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - if (fb_pdata->panel_power_ctrl) { - par->panel_power_ctrl = fb_pdata->panel_power_ctrl; - par->panel_power_ctrl(1); - } par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd"); if (IS_ERR(par->lcd_supply)) { @@ -1638,9 +1627,7 @@ static int fb_suspend(struct device *dev) int ret; console_lock(); - if (par->panel_power_ctrl) { - par->panel_power_ctrl(0); - } else if (par->lcd_supply) { + if (par->lcd_supply) { ret = regulator_disable(par->lcd_supply); if (ret) return ret; @@ -1666,9 +1653,7 @@ static int fb_resume(struct device *dev) if (par->blank == FB_BLANK_UNBLANK) { lcd_enable_raster(); - if (par->panel_power_ctrl) { - par->panel_power_ctrl(1); - } else if (par->lcd_supply) { + if (par->lcd_supply) { ret = regulator_enable(par->lcd_supply); if (ret) return ret; diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h index efed3c3383d6..1d19ae62b844 100644 --- a/include/video/da8xx-fb.h +++ b/include/video/da8xx-fb.h @@ -32,7 +32,6 @@ struct da8xx_lcdc_platform_data { const char manu_name[10]; void *controller_data; const char type[25]; - void (*panel_power_ctrl)(int); }; struct lcd_ctrl_config { From c957c88f7be109a14294289f013b03bbe94e8af5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:21 +0200 Subject: [PATCH 5/7] fbdev: da8xx-fb: use devm_platform_ioremap_resource() Shrink the code a bit by using the new helper wrapping the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Bartosz Golaszewski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sekhar Nori --- drivers/video/fbdev/da8xx-fb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index 19ed9889c8f8..f2f66605e8fb 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -1339,7 +1339,6 @@ static int fb_probe(struct platform_device *device) { struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&device->dev); - struct resource *lcdc_regs; struct lcd_ctrl_config *lcd_cfg; struct fb_videomode *lcdc_info; struct fb_info *da8xx_fb_info; @@ -1357,8 +1356,7 @@ static int fb_probe(struct platform_device *device) if (lcdc_info == NULL) return -ENODEV; - lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); - da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs); + da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0); if (IS_ERR(da8xx_fb_reg_base)) return PTR_ERR(da8xx_fb_reg_base); From 8a3665f72d77867745099178a40200dd548161e5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:22 +0200 Subject: [PATCH 6/7] fbdev: da8xx-fb: drop a redundant if The driver data is always set in probe. The remove() callback won't be called if probe failed which is the only way for it to be NULL. Remove the redundant if. Signed-off-by: Bartosz Golaszewski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sekhar Nori --- drivers/video/fbdev/da8xx-fb.c | 49 ++++++++++++++++------------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index f2f66605e8fb..d14ea6f91371 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -1067,37 +1067,34 @@ static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) static int fb_remove(struct platform_device *dev) { struct fb_info *info = dev_get_drvdata(&dev->dev); + struct da8xx_fb_par *par = info->par; int ret; - if (info) { - struct da8xx_fb_par *par = info->par; - #ifdef CONFIG_CPU_FREQ - lcd_da8xx_cpufreq_deregister(par); + lcd_da8xx_cpufreq_deregister(par); #endif - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - return ret; - } - - lcd_disable_raster(DA8XX_FRAME_WAIT); - lcdc_write(0, LCD_RASTER_CTRL_REG); - - /* disable DMA */ - lcdc_write(0, LCD_DMA_CTRL_REG); - - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base, - par->p_palette_base); - dma_free_coherent(par->dev, par->vram_size, par->vram_virt, - par->vram_phys); - pm_runtime_put_sync(&dev->dev); - pm_runtime_disable(&dev->dev); - framebuffer_release(info); - + if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; } + + lcd_disable_raster(DA8XX_FRAME_WAIT); + lcdc_write(0, LCD_RASTER_CTRL_REG); + + /* disable DMA */ + lcdc_write(0, LCD_DMA_CTRL_REG); + + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base, + par->p_palette_base); + dma_free_coherent(par->dev, par->vram_size, par->vram_virt, + par->vram_phys); + pm_runtime_put_sync(&dev->dev); + pm_runtime_disable(&dev->dev); + framebuffer_release(info); + return 0; } From 671da5f3444b09779f108d28cc69414c57deab8c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 22 Jul 2019 15:44:23 +0200 Subject: [PATCH 7/7] fbdev: da8xx: use resource management for dma Use managed variants of dma alloc functions in the da8xx fbdev driver. Signed-off-by: Bartosz Golaszewski Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sekhar Nori --- drivers/video/fbdev/da8xx-fb.c | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index d14ea6f91371..2d3dcc52fcf3 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -1087,10 +1087,6 @@ static int fb_remove(struct platform_device *dev) unregister_framebuffer(info); fb_dealloc_cmap(&info->cmap); - dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base, - par->p_palette_base); - dma_free_coherent(par->dev, par->vram_size, par->vram_virt, - par->vram_phys); pm_runtime_put_sync(&dev->dev); pm_runtime_disable(&dev->dev); framebuffer_release(info); @@ -1427,10 +1423,10 @@ static int fb_probe(struct platform_device *device) par->vram_size = roundup(par->vram_size/8, ulcm); par->vram_size = par->vram_size * LCD_NUM_BUFFERS; - par->vram_virt = dma_alloc_coherent(par->dev, - par->vram_size, - &par->vram_phys, - GFP_KERNEL | GFP_DMA); + par->vram_virt = dmam_alloc_coherent(par->dev, + par->vram_size, + &par->vram_phys, + GFP_KERNEL | GFP_DMA); if (!par->vram_virt) { dev_err(&device->dev, "GLCD: kmalloc for frame buffer failed\n"); @@ -1448,20 +1444,20 @@ static int fb_probe(struct platform_device *device) da8xx_fb_fix.line_length - 1; /* allocate palette buffer */ - par->v_palette_base = dma_alloc_coherent(par->dev, PALETTE_SIZE, - &par->p_palette_base, - GFP_KERNEL | GFP_DMA); + par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE, + &par->p_palette_base, + GFP_KERNEL | GFP_DMA); if (!par->v_palette_base) { dev_err(&device->dev, "GLCD: kmalloc for palette buffer failed\n"); ret = -EINVAL; - goto err_release_fb_mem; + goto err_release_fb; } par->irq = platform_get_irq(device, 0); if (par->irq < 0) { ret = -ENOENT; - goto err_release_pl_mem; + goto err_release_fb; } da8xx_fb_var.grayscale = @@ -1479,7 +1475,7 @@ static int fb_probe(struct platform_device *device) ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); if (ret) - goto err_release_pl_mem; + goto err_release_fb; da8xx_fb_info->cmap.len = par->palette_sz; /* initialize var_screeninfo */ @@ -1533,14 +1529,6 @@ err_cpu_freq: err_dealloc_cmap: fb_dealloc_cmap(&da8xx_fb_info->cmap); -err_release_pl_mem: - dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base, - par->p_palette_base); - -err_release_fb_mem: - dma_free_coherent(par->dev, par->vram_size, par->vram_virt, - par->vram_phys); - err_release_fb: framebuffer_release(da8xx_fb_info);