diff options
Diffstat (limited to 'drivers/video/fbdev/imxfb.c')
| -rw-r--r-- | drivers/video/fbdev/imxfb.c | 279 |
1 files changed, 141 insertions, 138 deletions
diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index 51fde1b2a793..a077bf346bdf 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Freescale i.MX Frame Buffer device driver * * Copyright (C) 2004 Sascha Hauer, Pengutronix * Based on acornfb.c Copyright (C) Russell King. * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * * Please direct your questions and comments on this driver to the following * email address: * @@ -34,6 +31,7 @@ #include <linux/math64.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/bitfield.h> #include <linux/regulator/consumer.h> @@ -41,12 +39,6 @@ #include <video/of_videomode.h> #include <video/videomode.h> -#define PCR_TFT (1 << 31) -#define PCR_BPIX_8 (3 << 25) -#define PCR_BPIX_12 (4 << 25) -#define PCR_BPIX_16 (5 << 25) -#define PCR_BPIX_18 (6 << 25) - struct imx_fb_videomode { struct fb_videomode mode; u32 pcr; @@ -64,42 +56,50 @@ struct imx_fb_videomode { #define LCDC_SSA 0x00 #define LCDC_SIZE 0x04 -#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) +#define SIZE_XMAX_MASK GENMASK(25, 20) -#define YMAX_MASK_IMX1 0x1ff -#define YMAX_MASK_IMX21 0x3ff +#define YMAX_MASK_IMX1 GENMASK(8, 0) +#define YMAX_MASK_IMX21 GENMASK(9, 0) #define LCDC_VPW 0x08 -#define VPW_VPW(x) ((x) & 0x3ff) +#define VPW_VPW_MASK GENMASK(9, 0) #define LCDC_CPOS 0x0C -#define CPOS_CC1 (1<<31) -#define CPOS_CC0 (1<<30) -#define CPOS_OP (1<<28) -#define CPOS_CXP(x) (((x) & 3ff) << 16) +#define CPOS_CC1 BIT(31) +#define CPOS_CC0 BIT(30) +#define CPOS_OP BIT(28) +#define CPOS_CXP_MASK GENMASK(25, 16) #define LCDC_LCWHB 0x10 -#define LCWHB_BK_EN (1<<31) -#define LCWHB_CW(w) (((w) & 0x1f) << 24) -#define LCWHB_CH(h) (((h) & 0x1f) << 16) -#define LCWHB_BD(x) ((x) & 0xff) +#define LCWHB_BK_EN BIT(31) +#define LCWHB_CW_MASK GENMASK(28, 24) +#define LCWHB_CH_MASK GENMASK(20, 16) +#define LCWHB_BD_MASK GENMASK(7, 0) #define LCDC_LCHCC 0x14 #define LCDC_PCR 0x18 +#define PCR_TFT BIT(31) +#define PCR_COLOR BIT(30) +#define PCR_BPIX_MASK GENMASK(27, 25) +#define PCR_BPIX_8 3 +#define PCR_BPIX_12 4 +#define PCR_BPIX_16 5 +#define PCR_BPIX_18 6 +#define PCR_PCD_MASK GENMASK(5, 0) #define LCDC_HCR 0x1C -#define HCR_H_WIDTH(x) (((x) & 0x3f) << 26) -#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8) -#define HCR_H_WAIT_2(x) ((x) & 0xff) +#define HCR_H_WIDTH_MASK GENMASK(31, 26) +#define HCR_H_WAIT_1_MASK GENMASK(15, 8) +#define HCR_H_WAIT_2_MASK GENMASK(7, 0) #define LCDC_VCR 0x20 -#define VCR_V_WIDTH(x) (((x) & 0x3f) << 26) -#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8) -#define VCR_V_WAIT_2(x) ((x) & 0xff) +#define VCR_V_WIDTH_MASK GENMASK(31, 26) +#define VCR_V_WAIT_1_MASK GENMASK(15, 8) +#define VCR_V_WAIT_2_MASK GENMASK(7, 0) #define LCDC_POS 0x24 -#define POS_POS(x) ((x) & 1f) +#define POS_POS_MASK GENMASK(4, 0) #define LCDC_LSCR1 0x28 /* bit fields in imxfb.h */ @@ -112,24 +112,24 @@ struct imx_fb_videomode { #define LCDC_RMCR 0x34 -#define RMCR_LCDC_EN_MX1 (1<<1) +#define RMCR_LCDC_EN_MX1 BIT(1) -#define RMCR_SELF_REF (1<<0) +#define RMCR_SELF_REF BIT(0) #define LCDC_LCDICR 0x38 -#define LCDICR_INT_SYN (1<<2) -#define LCDICR_INT_CON (1) +#define LCDICR_INT_SYN BIT(2) +#define LCDICR_INT_CON BIT(0) #define LCDC_LCDISR 0x40 -#define LCDISR_UDR_ERR (1<<3) -#define LCDISR_ERR_RES (1<<2) -#define LCDISR_EOF (1<<1) -#define LCDISR_BOF (1<<0) +#define LCDISR_UDR_ERR BIT(3) +#define LCDISR_ERR_RES BIT(2) +#define LCDISR_EOF BIT(1) +#define LCDISR_BOF BIT(0) #define IMXFB_LSCR1_DEFAULT 0x00120300 #define LCDC_LAUSCR 0x80 -#define LAUSCR_AUS_MODE (1<<31) +#define LAUSCR_AUS_MODE BIT(31) /* Used fb-mode. Can be set on kernel command line, therefore file-static. */ static const char *fb_mode; @@ -150,6 +150,12 @@ enum imxfb_type { IMX21_FB, }; +enum imxfb_panel_type { + PANEL_TYPE_MONOCHROME, + PANEL_TYPE_CSTN, + PANEL_TYPE_TFT, +}; + struct imxfb_info { struct platform_device *pdev; void __iomem *regs; @@ -157,6 +163,7 @@ struct imxfb_info { struct clk *clk_ahb; struct clk *clk_per; enum imxfb_type devtype; + enum imxfb_panel_type panel_type; bool enabled; /* @@ -273,10 +280,10 @@ static int imxfb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, struct imxfb_info *fbi = info->par; u_int val, ret = 1; -#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) +#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) if (regno < fbi->palette_size) { val = (CNVT_TOHW(red, 4) << 8) | - (CNVT_TOHW(green,4) << 4) | + (CNVT_TOHW(green, 4) << 4) | CNVT_TOHW(blue, 4); writel(val, fbi->regs + 0x800 + (regno << 2)); @@ -405,23 +412,23 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) pcr = (unsigned int)tmp; - if (--pcr > 0x3F) { - pcr = 0x3F; - printk(KERN_WARNING "Must limit pixel clock to %luHz\n", - lcd_clk / pcr); + if (--pcr > PCR_PCD_MASK) { + pcr = PCR_PCD_MASK; + dev_warn(&fbi->pdev->dev, "Must limit pixel clock to %luHz\n", + lcd_clk / pcr); } switch (var->bits_per_pixel) { case 32: - pcr |= PCR_BPIX_18; + pcr |= FIELD_PREP(PCR_BPIX_MASK, PCR_BPIX_18); rgb = &def_rgb_18; break; case 16: default: if (is_imx1_fb(fbi)) - pcr |= PCR_BPIX_12; + pcr |= FIELD_PREP(PCR_BPIX_MASK, PCR_BPIX_12); else - pcr |= PCR_BPIX_16; + pcr |= FIELD_PREP(PCR_BPIX_MASK, PCR_BPIX_16); if (imxfb_mode->pcr & PCR_TFT) rgb = &def_rgb_16_tft; @@ -429,13 +436,13 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) rgb = &def_rgb_16_stn; break; case 8: - pcr |= PCR_BPIX_8; + pcr |= FIELD_PREP(PCR_BPIX_MASK, PCR_BPIX_8); rgb = &def_rgb_8; break; } /* add sync polarities */ - pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25)); + pcr |= imxfb_mode->pcr & ~(PCR_PCD_MASK | PCR_BPIX_MASK); fbi->pcr = pcr; /* @@ -444,6 +451,13 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (!is_imx1_fb(fbi) && imxfb_mode->aus_mode) fbi->lauscr = LAUSCR_AUS_MODE; + if (imxfb_mode->pcr & PCR_TFT) + fbi->panel_type = PANEL_TYPE_TFT; + else if (imxfb_mode->pcr & PCR_COLOR) + fbi->panel_type = PANEL_TYPE_CSTN; + else + fbi->panel_type = PANEL_TYPE_MONOCHROME; + /* * Copy the RGB parameters for this display * from the machine specific parameters. @@ -506,7 +520,7 @@ static int imxfb_enable_controller(struct imxfb_info *fbi) writel(fbi->map_dma, fbi->regs + LCDC_SSA); /* panning offset 0 (0 pixel offset) */ - writel(0x00000000, fbi->regs + LCDC_POS); + writel(FIELD_PREP(POS_POS_MASK, 0), fbi->regs + LCDC_POS); /* disable hardware cursor */ writel(readl(fbi->regs + LCDC_CPOS) & ~(CPOS_CC0 | CPOS_CC1), @@ -562,7 +576,7 @@ static int imxfb_blank(int blank, struct fb_info *info) { struct imxfb_info *fbi = info->par; - pr_debug("imxfb_blank: blank=%d\n", blank); + pr_debug("%s: blank=%d\n", __func__, blank); switch (blank) { case FB_BLANK_POWERDOWN: @@ -580,12 +594,10 @@ static int imxfb_blank(int blank, struct fb_info *info) static const struct fb_ops imxfb_ops = { .owner = THIS_MODULE, + FB_DEFAULT_IOMEM_OPS, .fb_check_var = imxfb_check_var, .fb_set_par = imxfb_set_par, .fb_setcolreg = imxfb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, .fb_blank = imxfb_blank, }; @@ -598,6 +610,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf { struct imxfb_info *fbi = info->par; u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21; + u8 left_margin_low; pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", var->xres, var->hsync_len, @@ -606,49 +619,59 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf var->yres, var->vsync_len, var->upper_margin, var->lower_margin); + if (fbi->panel_type == PANEL_TYPE_TFT) + left_margin_low = 3; + else if (fbi->panel_type == PANEL_TYPE_CSTN) + left_margin_low = 2; + else + left_margin_low = 0; + #if DEBUG_VAR if (var->xres < 16 || var->xres > 1024) - printk(KERN_ERR "%s: invalid xres %d\n", + dev_err(&fbi->pdev->dev, "%s: invalid xres %d\n", info->fix.id, var->xres); if (var->hsync_len < 1 || var->hsync_len > 64) - printk(KERN_ERR "%s: invalid hsync_len %d\n", + dev_err(&fbi->pdev->dev, "%s: invalid hsync_len %d\n", info->fix.id, var->hsync_len); - if (var->left_margin > 255) - printk(KERN_ERR "%s: invalid left_margin %d\n", + if (var->left_margin < left_margin_low || var->left_margin > 255) + dev_err(&fbi->pdev->dev, "%s: invalid left_margin %d\n", info->fix.id, var->left_margin); - if (var->right_margin > 255) - printk(KERN_ERR "%s: invalid right_margin %d\n", + if (var->right_margin < 1 || var->right_margin > 255) + dev_err(&fbi->pdev->dev, "%s: invalid right_margin %d\n", info->fix.id, var->right_margin); if (var->yres < 1 || var->yres > ymax_mask) - printk(KERN_ERR "%s: invalid yres %d\n", + dev_err(&fbi->pdev->dev, "%s: invalid yres %d\n", info->fix.id, var->yres); if (var->vsync_len > 100) - printk(KERN_ERR "%s: invalid vsync_len %d\n", + dev_err(&fbi->pdev->dev, "%s: invalid vsync_len %d\n", info->fix.id, var->vsync_len); if (var->upper_margin > 63) - printk(KERN_ERR "%s: invalid upper_margin %d\n", + dev_err(&fbi->pdev->dev, "%s: invalid upper_margin %d\n", info->fix.id, var->upper_margin); if (var->lower_margin > 255) - printk(KERN_ERR "%s: invalid lower_margin %d\n", + dev_err(&fbi->pdev->dev, "%s: invalid lower_margin %d\n", info->fix.id, var->lower_margin); #endif /* physical screen start address */ - writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4), - fbi->regs + LCDC_VPW); + writel(FIELD_PREP(VPW_VPW_MASK, + var->xres * var->bits_per_pixel / 8 / 4), + fbi->regs + LCDC_VPW); - writel(HCR_H_WIDTH(var->hsync_len - 1) | - HCR_H_WAIT_1(var->right_margin - 1) | - HCR_H_WAIT_2(var->left_margin - 3), - fbi->regs + LCDC_HCR); + writel(FIELD_PREP(HCR_H_WIDTH_MASK, var->hsync_len - 1) | + FIELD_PREP(HCR_H_WAIT_1_MASK, var->right_margin - 1) | + FIELD_PREP(HCR_H_WAIT_2_MASK, + var->left_margin - left_margin_low), + fbi->regs + LCDC_HCR); - writel(VCR_V_WIDTH(var->vsync_len) | - VCR_V_WAIT_1(var->lower_margin) | - VCR_V_WAIT_2(var->upper_margin), - fbi->regs + LCDC_VCR); + writel(FIELD_PREP(VCR_V_WIDTH_MASK, var->vsync_len) | + FIELD_PREP(VCR_V_WAIT_1_MASK, var->lower_margin) | + FIELD_PREP(VCR_V_WAIT_2_MASK, var->upper_margin), + fbi->regs + LCDC_VCR); - writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask), - fbi->regs + LCDC_SIZE); + writel(FIELD_PREP(SIZE_XMAX_MASK, var->xres >> 4) | + (var->yres & ymax_mask), + fbi->regs + LCDC_SIZE); writel(fbi->pcr, fbi->regs + LCDC_PCR); if (fbi->pwmr) @@ -671,14 +694,14 @@ static int imxfb_init_fbinfo(struct platform_device *pdev) struct imxfb_info *fbi = info->par; struct device_node *np; - pr_debug("%s\n",__func__); - - info->pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL); + info->pseudo_palette = devm_kmalloc_array(&pdev->dev, 16, + sizeof(u32), GFP_KERNEL); if (!info->pseudo_palette) return -ENOMEM; memset(fbi, 0, sizeof(struct imxfb_info)); + fbi->pdev = pdev; fbi->devtype = pdev->id_entry->driver_data; strscpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); @@ -698,8 +721,7 @@ static int imxfb_init_fbinfo(struct platform_device *pdev) info->var.vmode = FB_VMODE_NONINTERLACED; info->fbops = &imxfb_ops; - info->flags = FBINFO_FLAG_DEFAULT | - FBINFO_READS_FAST; + info->flags = FBINFO_READS_FAST; np = pdev->dev.of_node; info->var.grayscale = of_property_read_bool(np, @@ -760,16 +782,6 @@ static int imxfb_of_read_mode(struct device *dev, struct device_node *np, return 0; } -static int imxfb_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi) -{ - struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev); - - if (!fi || fi->par == fbi) - return 1; - - return 0; -} - static int imxfb_lcd_get_contrast(struct lcd_device *lcddev) { struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev); @@ -802,9 +814,9 @@ static int imxfb_lcd_get_power(struct lcd_device *lcddev) if (!IS_ERR(fbi->lcd_pwr) && !regulator_is_enabled(fbi->lcd_pwr)) - return FB_BLANK_POWERDOWN; + return LCD_POWER_OFF; - return FB_BLANK_UNBLANK; + return LCD_POWER_ON; } static int imxfb_regulator_set(struct imxfb_info *fbi, int enable) @@ -830,13 +842,12 @@ static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power) struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev); if (!IS_ERR(fbi->lcd_pwr)) - return imxfb_regulator_set(fbi, power == FB_BLANK_UNBLANK); + return imxfb_regulator_set(fbi, power == LCD_POWER_ON); return 0; } -static struct lcd_ops imxfb_lcd_ops = { - .check_fb = imxfb_lcd_check_fb, +static const struct lcd_ops imxfb_lcd_ops = { .get_contrast = imxfb_lcd_get_contrast, .set_contrast = imxfb_lcd_set_contrast, .get_power = imxfb_lcd_get_power, @@ -868,7 +879,6 @@ static int imxfb_probe(struct platform_device *pdev) struct imxfb_info *fbi; struct lcd_device *lcd; struct fb_info *info; - struct resource *res; struct imx_fb_videomode *m; const struct of_device_id *of_id; struct device_node *display_np; @@ -885,10 +895,6 @@ static int imxfb_probe(struct platform_device *pdev) if (of_id) pdev->id_entry = of_id->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev); if (!info) return -ENOMEM; @@ -907,7 +913,7 @@ static int imxfb_probe(struct platform_device *pdev) if (!display_np) { dev_err(&pdev->dev, "No display defined in devicetree\n"); ret = -EINVAL; - goto failed_of_parse; + goto failed_init; } /* @@ -921,16 +927,18 @@ static int imxfb_probe(struct platform_device *pdev) if (!fbi->mode) { ret = -ENOMEM; of_node_put(display_np); - goto failed_of_parse; + goto failed_init; } ret = imxfb_of_read_mode(&pdev->dev, display_np, fbi->mode); of_node_put(display_np); if (ret) - goto failed_of_parse; + goto failed_init; - /* Calculate maximum bytes used per pixel. In most cases this should - * be the same as m->bpp/8 */ + /* + * Calculate maximum bytes used per pixel. In most cases this should + * be the same as m->bpp/8 + */ m = &fbi->mode[0]; bytes_per_pixel = (m->bpp + 7) / 8; for (i = 0; i < fbi->num_modes; i++, m++) @@ -940,7 +948,7 @@ static int imxfb_probe(struct platform_device *pdev) fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(fbi->clk_ipg)) { ret = PTR_ERR(fbi->clk_ipg); - goto failed_getclock; + goto failed_init; } /* @@ -955,25 +963,25 @@ static int imxfb_probe(struct platform_device *pdev) */ ret = clk_prepare_enable(fbi->clk_ipg); if (ret) - goto failed_getclock; + goto failed_init; clk_disable_unprepare(fbi->clk_ipg); fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(fbi->clk_ahb)) { ret = PTR_ERR(fbi->clk_ahb); - goto failed_getclock; + goto failed_init; } fbi->clk_per = devm_clk_get(&pdev->dev, "per"); if (IS_ERR(fbi->clk_per)) { ret = PTR_ERR(fbi->clk_per); - goto failed_getclock; + goto failed_init; } - fbi->regs = devm_ioremap_resource(&pdev->dev, res); + fbi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(fbi->regs)) { ret = PTR_ERR(fbi->regs); - goto failed_ioremap; + goto failed_init; } fbi->map_size = PAGE_ALIGN(info->fix.smem_len); @@ -982,14 +990,19 @@ static int imxfb_probe(struct platform_device *pdev) if (!info->screen_buffer) { dev_err(&pdev->dev, "Failed to allocate video RAM\n"); ret = -ENOMEM; - goto failed_map; + goto failed_init; } info->fix.smem_start = fbi->map_dma; INIT_LIST_HEAD(&info->modelist); - for (i = 0; i < fbi->num_modes; i++) - fb_add_videomode(&fbi->mode[i].mode, &info->modelist); + for (i = 0; i < fbi->num_modes; i++) { + ret = fb_add_videomode(&fbi->mode[i].mode, &info->modelist); + if (ret) { + dev_err(&pdev->dev, "Failed to add videomode\n"); + goto failed_cmap; + } + } /* * This makes sure that our colour bitfield @@ -1006,11 +1019,6 @@ static int imxfb_probe(struct platform_device *pdev) goto failed_cmap; imxfb_set_par(info); - ret = register_framebuffer(info); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register framebuffer\n"); - goto failed_register; - } fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd"); if (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER) { @@ -1027,31 +1035,29 @@ static int imxfb_probe(struct platform_device *pdev) lcd->props.max_contrast = 0xff; + info->lcd_dev = lcd; + + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register framebuffer\n"); + goto failed_lcd; + } + imxfb_enable_controller(fbi); - fbi->pdev = pdev; return 0; failed_lcd: - unregister_framebuffer(info); - -failed_register: fb_dealloc_cmap(&info->cmap); failed_cmap: dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer, fbi->map_dma); -failed_map: -failed_ioremap: -failed_getclock: - release_mem_region(res->start, resource_size(res)); -failed_of_parse: - kfree(info->pseudo_palette); failed_init: framebuffer_release(info); return ret; } -static int imxfb_remove(struct platform_device *pdev) +static void imxfb_remove(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); struct imxfb_info *fbi = info->par; @@ -1062,13 +1068,10 @@ static int imxfb_remove(struct platform_device *pdev) fb_dealloc_cmap(&info->cmap); dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer, fbi->map_dma); - kfree(info->pseudo_palette); framebuffer_release(info); - - return 0; } -static int __maybe_unused imxfb_suspend(struct device *dev) +static int imxfb_suspend(struct device *dev) { struct fb_info *info = dev_get_drvdata(dev); struct imxfb_info *fbi = info->par; @@ -1078,7 +1081,7 @@ static int __maybe_unused imxfb_suspend(struct device *dev) return 0; } -static int __maybe_unused imxfb_resume(struct device *dev) +static int imxfb_resume(struct device *dev) { struct fb_info *info = dev_get_drvdata(dev); struct imxfb_info *fbi = info->par; @@ -1088,13 +1091,13 @@ static int __maybe_unused imxfb_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume); static struct platform_driver imxfb_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = imxfb_of_dev_id, - .pm = &imxfb_pm_ops, + .pm = pm_sleep_ptr(&imxfb_pm_ops), }, .probe = imxfb_probe, .remove = imxfb_remove, |
