| .. | .. |
|---|
| 1 | 1 | /* |
|---|
| 2 | | - * Driver for AT91/AT32 LCD Controller |
|---|
| 2 | + * Driver for AT91 LCD Controller |
|---|
| 3 | 3 | * |
|---|
| 4 | 4 | * Copyright (C) 2007 Atmel Corporation |
|---|
| 5 | 5 | * |
|---|
| .. | .. |
|---|
| 98 | 98 | static struct atmel_lcdfb_config at91sam9rl_config = { |
|---|
| 99 | 99 | .have_intensity_bit = true, |
|---|
| 100 | 100 | }; |
|---|
| 101 | | - |
|---|
| 102 | | -static struct atmel_lcdfb_config at32ap_config = { |
|---|
| 103 | | - .have_hozval = true, |
|---|
| 104 | | -}; |
|---|
| 105 | | - |
|---|
| 106 | | -static const struct platform_device_id atmel_lcdfb_devtypes[] = { |
|---|
| 107 | | - { |
|---|
| 108 | | - .name = "at91sam9261-lcdfb", |
|---|
| 109 | | - .driver_data = (unsigned long)&at91sam9261_config, |
|---|
| 110 | | - }, { |
|---|
| 111 | | - .name = "at91sam9263-lcdfb", |
|---|
| 112 | | - .driver_data = (unsigned long)&at91sam9263_config, |
|---|
| 113 | | - }, { |
|---|
| 114 | | - .name = "at91sam9g10-lcdfb", |
|---|
| 115 | | - .driver_data = (unsigned long)&at91sam9g10_config, |
|---|
| 116 | | - }, { |
|---|
| 117 | | - .name = "at91sam9g45-lcdfb", |
|---|
| 118 | | - .driver_data = (unsigned long)&at91sam9g45_config, |
|---|
| 119 | | - }, { |
|---|
| 120 | | - .name = "at91sam9g45es-lcdfb", |
|---|
| 121 | | - .driver_data = (unsigned long)&at91sam9g45es_config, |
|---|
| 122 | | - }, { |
|---|
| 123 | | - .name = "at91sam9rl-lcdfb", |
|---|
| 124 | | - .driver_data = (unsigned long)&at91sam9rl_config, |
|---|
| 125 | | - }, { |
|---|
| 126 | | - .name = "at32ap-lcdfb", |
|---|
| 127 | | - .driver_data = (unsigned long)&at32ap_config, |
|---|
| 128 | | - }, { |
|---|
| 129 | | - /* terminator */ |
|---|
| 130 | | - } |
|---|
| 131 | | -}; |
|---|
| 132 | | -MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes); |
|---|
| 133 | | - |
|---|
| 134 | | -static struct atmel_lcdfb_config * |
|---|
| 135 | | -atmel_lcdfb_get_config(struct platform_device *pdev) |
|---|
| 136 | | -{ |
|---|
| 137 | | - unsigned long data; |
|---|
| 138 | | - |
|---|
| 139 | | - data = platform_get_device_id(pdev)->driver_data; |
|---|
| 140 | | - |
|---|
| 141 | | - return (struct atmel_lcdfb_config *)data; |
|---|
| 142 | | -} |
|---|
| 143 | | - |
|---|
| 144 | | -#if defined(CONFIG_ARCH_AT91) |
|---|
| 145 | | -#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ |
|---|
| 146 | | - | FBINFO_PARTIAL_PAN_OK \ |
|---|
| 147 | | - | FBINFO_HWACCEL_YPAN) |
|---|
| 148 | | - |
|---|
| 149 | | -static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
|---|
| 150 | | - struct fb_var_screeninfo *var, |
|---|
| 151 | | - struct fb_info *info) |
|---|
| 152 | | -{ |
|---|
| 153 | | - |
|---|
| 154 | | -} |
|---|
| 155 | | -#elif defined(CONFIG_AVR32) |
|---|
| 156 | | -#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ |
|---|
| 157 | | - | FBINFO_PARTIAL_PAN_OK \ |
|---|
| 158 | | - | FBINFO_HWACCEL_XPAN \ |
|---|
| 159 | | - | FBINFO_HWACCEL_YPAN) |
|---|
| 160 | | - |
|---|
| 161 | | -static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
|---|
| 162 | | - struct fb_var_screeninfo *var, |
|---|
| 163 | | - struct fb_info *info) |
|---|
| 164 | | -{ |
|---|
| 165 | | - u32 dma2dcfg; |
|---|
| 166 | | - u32 pixeloff; |
|---|
| 167 | | - |
|---|
| 168 | | - pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f; |
|---|
| 169 | | - |
|---|
| 170 | | - dma2dcfg = (info->var.xres_virtual - info->var.xres) |
|---|
| 171 | | - * info->var.bits_per_pixel / 8; |
|---|
| 172 | | - dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; |
|---|
| 173 | | - lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); |
|---|
| 174 | | - |
|---|
| 175 | | - /* Update configuration */ |
|---|
| 176 | | - lcdc_writel(sinfo, ATMEL_LCDC_DMACON, |
|---|
| 177 | | - lcdc_readl(sinfo, ATMEL_LCDC_DMACON) |
|---|
| 178 | | - | ATMEL_LCDC_DMAUPDT); |
|---|
| 179 | | -} |
|---|
| 180 | | -#endif |
|---|
| 181 | 101 | |
|---|
| 182 | 102 | static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 |
|---|
| 183 | 103 | | ATMEL_LCDC_POL_POSITIVE |
|---|
| .. | .. |
|---|
| 404 | 324 | |
|---|
| 405 | 325 | /* Set framebuffer DMA base address and pixel offset */ |
|---|
| 406 | 326 | lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); |
|---|
| 407 | | - |
|---|
| 408 | | - atmel_lcdfb_update_dma2d(sinfo, var, info); |
|---|
| 409 | 327 | } |
|---|
| 410 | 328 | |
|---|
| 411 | 329 | static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) |
|---|
| .. | .. |
|---|
| 590 | 508 | case 32: |
|---|
| 591 | 509 | var->transp.offset = 24; |
|---|
| 592 | 510 | var->transp.length = 8; |
|---|
| 593 | | - /* fall through */ |
|---|
| 511 | + fallthrough; |
|---|
| 594 | 512 | case 24: |
|---|
| 595 | 513 | if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { |
|---|
| 596 | 514 | /* RGB:888 mode */ |
|---|
| .. | .. |
|---|
| 715 | 633 | case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; |
|---|
| 716 | 634 | case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; |
|---|
| 717 | 635 | case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; |
|---|
| 718 | | - case 15: /* fall through */ |
|---|
| 636 | + case 15: fallthrough; |
|---|
| 719 | 637 | case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; |
|---|
| 720 | 638 | case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; |
|---|
| 721 | 639 | case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; |
|---|
| .. | .. |
|---|
| 755 | 673 | lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); |
|---|
| 756 | 674 | |
|---|
| 757 | 675 | /* Disable all interrupts */ |
|---|
| 758 | | - lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
|---|
| 676 | + lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0U); |
|---|
| 759 | 677 | /* Enable FIFO & DMA errors */ |
|---|
| 760 | 678 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); |
|---|
| 761 | 679 | |
|---|
| .. | .. |
|---|
| 906 | 824 | return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0); |
|---|
| 907 | 825 | } |
|---|
| 908 | 826 | |
|---|
| 909 | | -static struct fb_ops atmel_lcdfb_ops = { |
|---|
| 827 | +static const struct fb_ops atmel_lcdfb_ops = { |
|---|
| 910 | 828 | .owner = THIS_MODULE, |
|---|
| 911 | 829 | .fb_check_var = atmel_lcdfb_check_var, |
|---|
| 912 | 830 | .fb_set_par = atmel_lcdfb_set_par, |
|---|
| .. | .. |
|---|
| 978 | 896 | clk_disable_unprepare(sinfo->lcdc_clk); |
|---|
| 979 | 897 | } |
|---|
| 980 | 898 | |
|---|
| 981 | | -#ifdef CONFIG_OF |
|---|
| 982 | 899 | static const struct of_device_id atmel_lcdfb_dt_ids[] = { |
|---|
| 983 | 900 | { .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, }, |
|---|
| 984 | 901 | { .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, }, |
|---|
| .. | .. |
|---|
| 986 | 903 | { .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, }, |
|---|
| 987 | 904 | { .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, }, |
|---|
| 988 | 905 | { .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, }, |
|---|
| 989 | | - { .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, }, |
|---|
| 990 | 906 | { /* sentinel */ } |
|---|
| 991 | 907 | }; |
|---|
| 992 | 908 | |
|---|
| .. | .. |
|---|
| 1034 | 950 | struct fb_videomode fb_vm; |
|---|
| 1035 | 951 | struct gpio_desc *gpiod; |
|---|
| 1036 | 952 | struct videomode vm; |
|---|
| 1037 | | - int ret = -ENOENT; |
|---|
| 953 | + int ret; |
|---|
| 1038 | 954 | int i; |
|---|
| 1039 | 955 | |
|---|
| 1040 | 956 | sinfo->config = (struct atmel_lcdfb_config*) |
|---|
| .. | .. |
|---|
| 1122 | 1038 | of_node_put(display_np); |
|---|
| 1123 | 1039 | return ret; |
|---|
| 1124 | 1040 | } |
|---|
| 1125 | | -#else |
|---|
| 1126 | | -static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo) |
|---|
| 1127 | | -{ |
|---|
| 1128 | | - return 0; |
|---|
| 1129 | | -} |
|---|
| 1130 | | -#endif |
|---|
| 1131 | 1041 | |
|---|
| 1132 | 1042 | static int __init atmel_lcdfb_probe(struct platform_device *pdev) |
|---|
| 1133 | 1043 | { |
|---|
| 1134 | 1044 | struct device *dev = &pdev->dev; |
|---|
| 1135 | 1045 | struct fb_info *info; |
|---|
| 1136 | 1046 | struct atmel_lcdfb_info *sinfo; |
|---|
| 1137 | | - struct atmel_lcdfb_pdata *pdata = NULL; |
|---|
| 1138 | 1047 | struct resource *regs = NULL; |
|---|
| 1139 | 1048 | struct resource *map = NULL; |
|---|
| 1140 | 1049 | struct fb_modelist *modelist; |
|---|
| .. | .. |
|---|
| 1144 | 1053 | |
|---|
| 1145 | 1054 | ret = -ENOMEM; |
|---|
| 1146 | 1055 | info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); |
|---|
| 1147 | | - if (!info) { |
|---|
| 1148 | | - dev_err(dev, "cannot allocate memory\n"); |
|---|
| 1056 | + if (!info) |
|---|
| 1149 | 1057 | goto out; |
|---|
| 1150 | | - } |
|---|
| 1151 | 1058 | |
|---|
| 1152 | 1059 | sinfo = info->par; |
|---|
| 1153 | 1060 | sinfo->pdev = pdev; |
|---|
| .. | .. |
|---|
| 1155 | 1062 | |
|---|
| 1156 | 1063 | INIT_LIST_HEAD(&info->modelist); |
|---|
| 1157 | 1064 | |
|---|
| 1158 | | - if (pdev->dev.of_node) { |
|---|
| 1159 | | - ret = atmel_lcdfb_of_init(sinfo); |
|---|
| 1160 | | - if (ret) |
|---|
| 1161 | | - goto free_info; |
|---|
| 1162 | | - } else if (dev_get_platdata(dev)) { |
|---|
| 1163 | | - struct fb_monspecs *monspecs; |
|---|
| 1164 | | - int i; |
|---|
| 1165 | | - |
|---|
| 1166 | | - pdata = dev_get_platdata(dev); |
|---|
| 1167 | | - monspecs = pdata->default_monspecs; |
|---|
| 1168 | | - sinfo->pdata = *pdata; |
|---|
| 1169 | | - |
|---|
| 1170 | | - for (i = 0; i < monspecs->modedb_len; i++) |
|---|
| 1171 | | - fb_add_videomode(&monspecs->modedb[i], &info->modelist); |
|---|
| 1172 | | - |
|---|
| 1173 | | - sinfo->config = atmel_lcdfb_get_config(pdev); |
|---|
| 1174 | | - |
|---|
| 1175 | | - info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16; |
|---|
| 1176 | | - memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs)); |
|---|
| 1177 | | - } else { |
|---|
| 1065 | + if (!pdev->dev.of_node) { |
|---|
| 1178 | 1066 | dev_err(dev, "cannot get default configuration\n"); |
|---|
| 1179 | 1067 | goto free_info; |
|---|
| 1180 | 1068 | } |
|---|
| 1181 | 1069 | |
|---|
| 1070 | + ret = atmel_lcdfb_of_init(sinfo); |
|---|
| 1071 | + if (ret) |
|---|
| 1072 | + goto free_info; |
|---|
| 1073 | + |
|---|
| 1074 | + ret = -ENODEV; |
|---|
| 1182 | 1075 | if (!sinfo->config) |
|---|
| 1183 | 1076 | goto free_info; |
|---|
| 1184 | 1077 | |
|---|
| .. | .. |
|---|
| 1186 | 1079 | if (IS_ERR(sinfo->reg_lcd)) |
|---|
| 1187 | 1080 | sinfo->reg_lcd = NULL; |
|---|
| 1188 | 1081 | |
|---|
| 1189 | | - info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; |
|---|
| 1082 | + info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | |
|---|
| 1083 | + FBINFO_HWACCEL_YPAN; |
|---|
| 1190 | 1084 | info->pseudo_palette = sinfo->pseudo_palette; |
|---|
| 1191 | 1085 | info->fbops = &atmel_lcdfb_ops; |
|---|
| 1192 | 1086 | |
|---|
| .. | .. |
|---|
| 1221 | 1115 | |
|---|
| 1222 | 1116 | sinfo->irq_base = platform_get_irq(pdev, 0); |
|---|
| 1223 | 1117 | if (sinfo->irq_base < 0) { |
|---|
| 1224 | | - dev_err(dev, "unable to get irq\n"); |
|---|
| 1225 | 1118 | ret = sinfo->irq_base; |
|---|
| 1226 | 1119 | goto stop_clk; |
|---|
| 1227 | 1120 | } |
|---|
| .. | .. |
|---|
| 1357 | 1250 | struct device *dev = &pdev->dev; |
|---|
| 1358 | 1251 | struct fb_info *info = dev_get_drvdata(dev); |
|---|
| 1359 | 1252 | struct atmel_lcdfb_info *sinfo; |
|---|
| 1360 | | - struct atmel_lcdfb_pdata *pdata; |
|---|
| 1361 | 1253 | |
|---|
| 1362 | 1254 | if (!info || !info->par) |
|---|
| 1363 | 1255 | return 0; |
|---|
| 1364 | 1256 | sinfo = info->par; |
|---|
| 1365 | | - pdata = &sinfo->pdata; |
|---|
| 1366 | 1257 | |
|---|
| 1367 | 1258 | cancel_work_sync(&sinfo->task); |
|---|
| 1368 | 1259 | exit_backlight(sinfo); |
|---|
| .. | .. |
|---|
| 1398 | 1289 | * We don't want to handle interrupts while the clock is |
|---|
| 1399 | 1290 | * stopped. It may take forever. |
|---|
| 1400 | 1291 | */ |
|---|
| 1401 | | - lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
|---|
| 1292 | + lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0U); |
|---|
| 1402 | 1293 | |
|---|
| 1403 | 1294 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR); |
|---|
| 1404 | 1295 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); |
|---|
| .. | .. |
|---|
| 1435 | 1326 | .remove = __exit_p(atmel_lcdfb_remove), |
|---|
| 1436 | 1327 | .suspend = atmel_lcdfb_suspend, |
|---|
| 1437 | 1328 | .resume = atmel_lcdfb_resume, |
|---|
| 1438 | | - .id_table = atmel_lcdfb_devtypes, |
|---|
| 1439 | 1329 | .driver = { |
|---|
| 1440 | 1330 | .name = "atmel_lcdfb", |
|---|
| 1441 | 1331 | .of_match_table = of_match_ptr(atmel_lcdfb_dt_ids), |
|---|
| .. | .. |
|---|
| 1444 | 1334 | |
|---|
| 1445 | 1335 | module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe); |
|---|
| 1446 | 1336 | |
|---|
| 1447 | | -MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver"); |
|---|
| 1337 | +MODULE_DESCRIPTION("AT91 LCD Controller framebuffer driver"); |
|---|
| 1448 | 1338 | MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); |
|---|
| 1449 | 1339 | MODULE_LICENSE("GPL"); |
|---|