.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2008-2009 MontaVista Software Inc. |
---|
3 | 4 | * Copyright (C) 2008-2009 Texas Instruments Inc |
---|
4 | 5 | * |
---|
5 | 6 | * Based on the LCD driver for TI Avalanche processors written by |
---|
6 | 7 | * Ajay Singh and Shalom Hai. |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
11 | | - * (at your option)any later version. |
---|
12 | | - * |
---|
13 | | - * This program is distributed in the hope that it will be useful, |
---|
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
16 | | - * GNU General Public License for more details. |
---|
17 | | - * |
---|
18 | | - * You should have received a copy of the GNU General Public License |
---|
19 | | - * along with this program; if not, write to the Free Software |
---|
20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
21 | 8 | */ |
---|
22 | 9 | #include <linux/module.h> |
---|
23 | 10 | #include <linux/kernel.h> |
---|
.. | .. |
---|
32 | 19 | #include <linux/clk.h> |
---|
33 | 20 | #include <linux/cpufreq.h> |
---|
34 | 21 | #include <linux/console.h> |
---|
| 22 | +#include <linux/regulator/consumer.h> |
---|
35 | 23 | #include <linux/spinlock.h> |
---|
36 | 24 | #include <linux/slab.h> |
---|
37 | 25 | #include <linux/delay.h> |
---|
.. | .. |
---|
177 | 165 | struct notifier_block freq_transition; |
---|
178 | 166 | #endif |
---|
179 | 167 | unsigned int lcdc_clk_rate; |
---|
180 | | - void (*panel_power_ctrl)(int); |
---|
| 168 | + struct regulator *lcd_supply; |
---|
181 | 169 | u32 pseudo_palette[16]; |
---|
182 | 170 | struct fb_videomode mode; |
---|
183 | 171 | struct lcd_ctrl_config cfg; |
---|
.. | .. |
---|
1079 | 1067 | static int fb_remove(struct platform_device *dev) |
---|
1080 | 1068 | { |
---|
1081 | 1069 | struct fb_info *info = dev_get_drvdata(&dev->dev); |
---|
1082 | | - |
---|
1083 | | - if (info) { |
---|
1084 | | - struct da8xx_fb_par *par = info->par; |
---|
| 1070 | + struct da8xx_fb_par *par = info->par; |
---|
| 1071 | + int ret; |
---|
1085 | 1072 | |
---|
1086 | 1073 | #ifdef CONFIG_CPU_FREQ |
---|
1087 | | - lcd_da8xx_cpufreq_deregister(par); |
---|
| 1074 | + lcd_da8xx_cpufreq_deregister(par); |
---|
1088 | 1075 | #endif |
---|
1089 | | - if (par->panel_power_ctrl) |
---|
1090 | | - par->panel_power_ctrl(0); |
---|
1091 | | - |
---|
1092 | | - lcd_disable_raster(DA8XX_FRAME_WAIT); |
---|
1093 | | - lcdc_write(0, LCD_RASTER_CTRL_REG); |
---|
1094 | | - |
---|
1095 | | - /* disable DMA */ |
---|
1096 | | - lcdc_write(0, LCD_DMA_CTRL_REG); |
---|
1097 | | - |
---|
1098 | | - unregister_framebuffer(info); |
---|
1099 | | - fb_dealloc_cmap(&info->cmap); |
---|
1100 | | - dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, |
---|
1101 | | - par->p_palette_base); |
---|
1102 | | - dma_free_coherent(NULL, par->vram_size, par->vram_virt, |
---|
1103 | | - par->vram_phys); |
---|
1104 | | - pm_runtime_put_sync(&dev->dev); |
---|
1105 | | - pm_runtime_disable(&dev->dev); |
---|
1106 | | - framebuffer_release(info); |
---|
1107 | | - |
---|
| 1076 | + if (par->lcd_supply) { |
---|
| 1077 | + ret = regulator_disable(par->lcd_supply); |
---|
| 1078 | + if (ret) |
---|
| 1079 | + return ret; |
---|
1108 | 1080 | } |
---|
| 1081 | + |
---|
| 1082 | + lcd_disable_raster(DA8XX_FRAME_WAIT); |
---|
| 1083 | + lcdc_write(0, LCD_RASTER_CTRL_REG); |
---|
| 1084 | + |
---|
| 1085 | + /* disable DMA */ |
---|
| 1086 | + lcdc_write(0, LCD_DMA_CTRL_REG); |
---|
| 1087 | + |
---|
| 1088 | + unregister_framebuffer(info); |
---|
| 1089 | + fb_dealloc_cmap(&info->cmap); |
---|
| 1090 | + pm_runtime_put_sync(&dev->dev); |
---|
| 1091 | + pm_runtime_disable(&dev->dev); |
---|
| 1092 | + framebuffer_release(info); |
---|
| 1093 | + |
---|
1109 | 1094 | return 0; |
---|
1110 | 1095 | } |
---|
1111 | 1096 | |
---|
.. | .. |
---|
1192 | 1177 | case FB_BLANK_UNBLANK: |
---|
1193 | 1178 | lcd_enable_raster(); |
---|
1194 | 1179 | |
---|
1195 | | - if (par->panel_power_ctrl) |
---|
1196 | | - par->panel_power_ctrl(1); |
---|
| 1180 | + if (par->lcd_supply) { |
---|
| 1181 | + ret = regulator_enable(par->lcd_supply); |
---|
| 1182 | + if (ret) |
---|
| 1183 | + return ret; |
---|
| 1184 | + } |
---|
1197 | 1185 | break; |
---|
1198 | 1186 | case FB_BLANK_NORMAL: |
---|
1199 | 1187 | case FB_BLANK_VSYNC_SUSPEND: |
---|
1200 | 1188 | case FB_BLANK_HSYNC_SUSPEND: |
---|
1201 | 1189 | case FB_BLANK_POWERDOWN: |
---|
1202 | | - if (par->panel_power_ctrl) |
---|
1203 | | - par->panel_power_ctrl(0); |
---|
| 1190 | + if (par->lcd_supply) { |
---|
| 1191 | + ret = regulator_disable(par->lcd_supply); |
---|
| 1192 | + if (ret) |
---|
| 1193 | + return ret; |
---|
| 1194 | + } |
---|
1204 | 1195 | |
---|
1205 | 1196 | lcd_disable_raster(DA8XX_FRAME_WAIT); |
---|
1206 | 1197 | break; |
---|
.. | .. |
---|
1303 | 1294 | return 0; |
---|
1304 | 1295 | } |
---|
1305 | 1296 | |
---|
1306 | | -static struct fb_ops da8xx_fb_ops = { |
---|
| 1297 | +static const struct fb_ops da8xx_fb_ops = { |
---|
1307 | 1298 | .owner = THIS_MODULE, |
---|
1308 | 1299 | .fb_check_var = fb_check_var, |
---|
1309 | 1300 | .fb_set_par = da8xxfb_set_par, |
---|
.. | .. |
---|
1341 | 1332 | { |
---|
1342 | 1333 | struct da8xx_lcdc_platform_data *fb_pdata = |
---|
1343 | 1334 | dev_get_platdata(&device->dev); |
---|
1344 | | - struct resource *lcdc_regs; |
---|
1345 | 1335 | struct lcd_ctrl_config *lcd_cfg; |
---|
1346 | 1336 | struct fb_videomode *lcdc_info; |
---|
1347 | 1337 | struct fb_info *da8xx_fb_info; |
---|
.. | .. |
---|
1359 | 1349 | if (lcdc_info == NULL) |
---|
1360 | 1350 | return -ENODEV; |
---|
1361 | 1351 | |
---|
1362 | | - lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); |
---|
1363 | | - da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs); |
---|
| 1352 | + da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0); |
---|
1364 | 1353 | if (IS_ERR(da8xx_fb_reg_base)) |
---|
1365 | 1354 | return PTR_ERR(da8xx_fb_reg_base); |
---|
1366 | 1355 | |
---|
.. | .. |
---|
1400 | 1389 | da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), |
---|
1401 | 1390 | &device->dev); |
---|
1402 | 1391 | if (!da8xx_fb_info) { |
---|
1403 | | - dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); |
---|
1404 | 1392 | ret = -ENOMEM; |
---|
1405 | 1393 | goto err_pm_runtime_disable; |
---|
1406 | 1394 | } |
---|
.. | .. |
---|
1409 | 1397 | par->dev = &device->dev; |
---|
1410 | 1398 | par->lcdc_clk = tmp_lcdc_clk; |
---|
1411 | 1399 | par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); |
---|
1412 | | - if (fb_pdata->panel_power_ctrl) { |
---|
1413 | | - par->panel_power_ctrl = fb_pdata->panel_power_ctrl; |
---|
1414 | | - par->panel_power_ctrl(1); |
---|
| 1400 | + |
---|
| 1401 | + par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd"); |
---|
| 1402 | + if (IS_ERR(par->lcd_supply)) { |
---|
| 1403 | + if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) { |
---|
| 1404 | + ret = -EPROBE_DEFER; |
---|
| 1405 | + goto err_release_fb; |
---|
| 1406 | + } |
---|
| 1407 | + |
---|
| 1408 | + par->lcd_supply = NULL; |
---|
| 1409 | + } else { |
---|
| 1410 | + ret = regulator_enable(par->lcd_supply); |
---|
| 1411 | + if (ret) |
---|
| 1412 | + goto err_release_fb; |
---|
1415 | 1413 | } |
---|
1416 | 1414 | |
---|
1417 | 1415 | fb_videomode_to_var(&da8xx_fb_var, lcdc_info); |
---|
.. | .. |
---|
1425 | 1423 | par->vram_size = roundup(par->vram_size/8, ulcm); |
---|
1426 | 1424 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; |
---|
1427 | 1425 | |
---|
1428 | | - par->vram_virt = dma_alloc_coherent(NULL, |
---|
1429 | | - par->vram_size, |
---|
1430 | | - &par->vram_phys, |
---|
1431 | | - GFP_KERNEL | GFP_DMA); |
---|
| 1426 | + par->vram_virt = dmam_alloc_coherent(par->dev, |
---|
| 1427 | + par->vram_size, |
---|
| 1428 | + &par->vram_phys, |
---|
| 1429 | + GFP_KERNEL | GFP_DMA); |
---|
1432 | 1430 | if (!par->vram_virt) { |
---|
1433 | 1431 | dev_err(&device->dev, |
---|
1434 | 1432 | "GLCD: kmalloc for frame buffer failed\n"); |
---|
.. | .. |
---|
1446 | 1444 | da8xx_fb_fix.line_length - 1; |
---|
1447 | 1445 | |
---|
1448 | 1446 | /* allocate palette buffer */ |
---|
1449 | | - par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE, |
---|
| 1447 | + par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE, |
---|
1450 | 1448 | &par->p_palette_base, |
---|
1451 | 1449 | GFP_KERNEL | GFP_DMA); |
---|
1452 | 1450 | if (!par->v_palette_base) { |
---|
1453 | 1451 | dev_err(&device->dev, |
---|
1454 | 1452 | "GLCD: kmalloc for palette buffer failed\n"); |
---|
1455 | 1453 | ret = -EINVAL; |
---|
1456 | | - goto err_release_fb_mem; |
---|
| 1454 | + goto err_release_fb; |
---|
1457 | 1455 | } |
---|
1458 | 1456 | |
---|
1459 | 1457 | par->irq = platform_get_irq(device, 0); |
---|
1460 | 1458 | if (par->irq < 0) { |
---|
1461 | 1459 | ret = -ENOENT; |
---|
1462 | | - goto err_release_pl_mem; |
---|
| 1460 | + goto err_release_fb; |
---|
1463 | 1461 | } |
---|
1464 | 1462 | |
---|
1465 | 1463 | da8xx_fb_var.grayscale = |
---|
.. | .. |
---|
1477 | 1475 | |
---|
1478 | 1476 | ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); |
---|
1479 | 1477 | if (ret) |
---|
1480 | | - goto err_release_pl_mem; |
---|
| 1478 | + goto err_release_fb; |
---|
1481 | 1479 | da8xx_fb_info->cmap.len = par->palette_sz; |
---|
1482 | 1480 | |
---|
1483 | 1481 | /* initialize var_screeninfo */ |
---|
.. | .. |
---|
1530 | 1528 | |
---|
1531 | 1529 | err_dealloc_cmap: |
---|
1532 | 1530 | fb_dealloc_cmap(&da8xx_fb_info->cmap); |
---|
1533 | | - |
---|
1534 | | -err_release_pl_mem: |
---|
1535 | | - dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, |
---|
1536 | | - par->p_palette_base); |
---|
1537 | | - |
---|
1538 | | -err_release_fb_mem: |
---|
1539 | | - dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys); |
---|
1540 | 1531 | |
---|
1541 | 1532 | err_release_fb: |
---|
1542 | 1533 | framebuffer_release(da8xx_fb_info); |
---|
.. | .. |
---|
1616 | 1607 | { |
---|
1617 | 1608 | struct fb_info *info = dev_get_drvdata(dev); |
---|
1618 | 1609 | struct da8xx_fb_par *par = info->par; |
---|
| 1610 | + int ret; |
---|
1619 | 1611 | |
---|
1620 | 1612 | console_lock(); |
---|
1621 | | - if (par->panel_power_ctrl) |
---|
1622 | | - par->panel_power_ctrl(0); |
---|
| 1613 | + if (par->lcd_supply) { |
---|
| 1614 | + ret = regulator_disable(par->lcd_supply); |
---|
| 1615 | + if (ret) |
---|
| 1616 | + return ret; |
---|
| 1617 | + } |
---|
1623 | 1618 | |
---|
1624 | 1619 | fb_set_suspend(info, 1); |
---|
1625 | 1620 | lcd_disable_raster(DA8XX_FRAME_WAIT); |
---|
.. | .. |
---|
1633 | 1628 | { |
---|
1634 | 1629 | struct fb_info *info = dev_get_drvdata(dev); |
---|
1635 | 1630 | struct da8xx_fb_par *par = info->par; |
---|
| 1631 | + int ret; |
---|
1636 | 1632 | |
---|
1637 | 1633 | console_lock(); |
---|
1638 | 1634 | pm_runtime_get_sync(dev); |
---|
.. | .. |
---|
1640 | 1636 | if (par->blank == FB_BLANK_UNBLANK) { |
---|
1641 | 1637 | lcd_enable_raster(); |
---|
1642 | 1638 | |
---|
1643 | | - if (par->panel_power_ctrl) |
---|
1644 | | - par->panel_power_ctrl(1); |
---|
| 1639 | + if (par->lcd_supply) { |
---|
| 1640 | + ret = regulator_enable(par->lcd_supply); |
---|
| 1641 | + if (ret) |
---|
| 1642 | + return ret; |
---|
| 1643 | + } |
---|
1645 | 1644 | } |
---|
1646 | 1645 | |
---|
1647 | 1646 | fb_set_suspend(info, 0); |
---|