arm64: dts: qcom: Add Lenovo Yoga C630
[sfrench/cifs-2.6.git] / arch / arm / mach-nspire / clcd.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *      linux/arch/arm/mach-nspire/clcd.c
4  *
5  *      Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
6  */
7
8 #include <linux/init.h>
9 #include <linux/of.h>
10 #include <linux/amba/bus.h>
11 #include <linux/amba/clcd.h>
12 #include <linux/dma-mapping.h>
13
14 static struct clcd_panel nspire_cx_lcd_panel = {
15         .mode           = {
16                 .name           = "Color LCD",
17                 .refresh        = 60,
18                 .xres           = 320,
19                 .yres           = 240,
20                 .sync           = 0,
21                 .vmode          = FB_VMODE_NONINTERLACED,
22                 .pixclock       = 1,
23                 .hsync_len      = 6,
24                 .vsync_len      = 1,
25                 .right_margin   = 50,
26                 .left_margin    = 38,
27                 .lower_margin   = 3,
28                 .upper_margin   = 17,
29         },
30         .width          = 65, /* ~6.50 cm */
31         .height         = 49, /* ~4.87 cm */
32         .tim2           = TIM2_IPC,
33         .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
34         .bpp            = 16,
35         .caps           = CLCD_CAP_565,
36 };
37
38 static struct clcd_panel nspire_classic_lcd_panel = {
39         .mode           = {
40                 .name           = "Grayscale LCD",
41                 .refresh        = 60,
42                 .xres           = 320,
43                 .yres           = 240,
44                 .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
45                 .vmode          = FB_VMODE_NONINTERLACED,
46                 .pixclock       = 1,
47                 .hsync_len      = 6,
48                 .vsync_len      = 1,
49                 .right_margin   = 6,
50                 .left_margin    = 6,
51         },
52         .width          = 71, /* 7.11cm */
53         .height         = 53, /* 5.33cm */
54         .tim2           = 0x80007d0,
55         .cntl           = CNTL_LCDMONO8,
56         .bpp            = 8,
57         .grayscale      = 1,
58         .caps           = CLCD_CAP_5551,
59 };
60
61 int nspire_clcd_setup(struct clcd_fb *fb)
62 {
63         struct clcd_panel *panel;
64         size_t panel_size;
65         const char *type;
66         dma_addr_t dma;
67         int err;
68
69         BUG_ON(!fb->dev->dev.of_node);
70
71         err = of_property_read_string(fb->dev->dev.of_node, "lcd-type", &type);
72         if (err) {
73                 pr_err("CLCD: Could not find lcd-type property\n");
74                 return err;
75         }
76
77         if (!strcmp(type, "cx")) {
78                 panel = &nspire_cx_lcd_panel;
79         } else if (!strcmp(type, "classic")) {
80                 panel = &nspire_classic_lcd_panel;
81         } else {
82                 pr_err("CLCD: Unknown lcd-type %s\n", type);
83                 return -EINVAL;
84         }
85
86         panel_size = ((panel->mode.xres * panel->mode.yres) * panel->bpp) / 8;
87         panel_size = ALIGN(panel_size, PAGE_SIZE);
88
89         fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, panel_size, &dma,
90                                           GFP_KERNEL);
91
92         if (!fb->fb.screen_base) {
93                 pr_err("CLCD: unable to map framebuffer\n");
94                 return -ENOMEM;
95         }
96
97         fb->fb.fix.smem_start = dma;
98         fb->fb.fix.smem_len = panel_size;
99         fb->panel = panel;
100
101         return 0;
102 }
103
104 int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
105 {
106         return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
107                            fb->fb.fix.smem_start, fb->fb.fix.smem_len);
108 }
109
110 void nspire_clcd_remove(struct clcd_fb *fb)
111 {
112         dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
113                     fb->fb.fix.smem_start);
114 }