Skip to content

Commit c74ed67

Browse files
altcrauerdinguyen702
authored andcommitted
FogBugz #177284: add Altera VIP framebuffer driver
This adds support for the Altera framebuffer that uses the Altera VIP Frame Reader hardware. The current implementation of the Altera VIP driver was sitting in the wrong directory. It was sitting in drivers/video, and should reside inside of /drivers/video/fbdev. Signed-off-by: Chris Rauer <[email protected]> Signed-off-by: Dinh Nguyen <[email protected]>
1 parent eec7d56 commit c74ed67

File tree

5 files changed

+345
-0
lines changed

5 files changed

+345
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Altera Video and Image Processing(VIP) Frame Reader bindings
2+
3+
Required properties:
4+
- compatible: "altr,vip-frame-reader-9.1" or "altr,vip-frame-reader-1.0"
5+
- reg: Physical base address and length of the framebuffer controller's
6+
registers.
7+
- max-width: The width of the framebuffer in pixels.
8+
- max-height: The height of the framebuffer in pixels.
9+
- bits-per-color: only "8" is currently supported
10+
- mem-word-width = the bus width of the avalon master port on the frame reader
11+
12+
Example:
13+
14+
alt_vip_vfr_0: vip@0xff260000 {
15+
compatible = "altr,vip-frame-reader-1.0";
16+
reg = <0xff260000 0x00000080>;
17+
max-width = <1024>;
18+
max-height = <768>;
19+
bits-per-color = <8>;
20+
mem-word-width = <128>;
21+
};
22+

drivers/video/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ config HDMI
3636
bool
3737

3838
endif # HAS_IOMEM
39+
config FB_ALTERA_VIP
40+
tristate "Altera VIP Frame Reader framebuffer support"
41+
depends on FB
42+
select FB_CFB_FILLRECT
43+
select FB_CFB_COPYAREA
44+
select FB_CFB_IMAGEBLIT
45+
help
46+
This driver supports the Altera Video and Image Processing(VIP)
47+
Frame Reader
3948

4049
if VT
4150
source "drivers/video/console/Kconfig"

drivers/video/fbdev/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ config FB_TILEBLITTING
219219
comment "Frame buffer hardware drivers"
220220
depends on FB
221221

222+
config FB_ALTERA_VIP
223+
tristate "Altera VIP Frame Reader framebuffer support"
224+
depends on FB
225+
select FB_CFB_FILLRECT
226+
select FB_CFB_COPYAREA
227+
select FB_CFB_IMAGEBLIT
228+
help
229+
This driver supports the Altera Video and Image Processing(VIP)
230+
Frame Reader
231+
222232
config FB_GRVGA
223233
tristate "Aeroflex Gaisler framebuffer support"
224234
depends on FB && SPARC

drivers/video/fbdev/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o
1111
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
1212

1313
# Hardware specific drivers go first
14+
obj-$(CONFIG_FB_ALTERA_VIP) += altvipfb.o
1415
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
1516
obj-$(CONFIG_FB_ARC) += arcfb.o
1617
obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o

drivers/video/fbdev/altvipfb.c

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
/*
2+
* altvipfb.c -- Altera Video and Image Processing(VIP) Frame Reader driver
3+
*
4+
* This is based on a driver made by Thomas Chou <[email protected]> and
5+
* Walter Goossens <[email protected]> This driver supports the Altera VIP
6+
* Frame Reader component. More info on the hardware can be found in
7+
* the Altera Video and Image Processing Suite User Guide at this address
8+
* http://www.altera.com/literature/ug/ug_vip.pdf.
9+
*
10+
* This program is free software; you can redistribute it and/or modify it
11+
* under the terms and conditions of the GNU General Public License,
12+
* version 2, as published by the Free Software Foundation.
13+
*
14+
* This program is distributed in the hope it will be useful, but WITHOUT
15+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17+
* more details.
18+
*
19+
*/
20+
21+
#include <linux/dma-mapping.h>
22+
#include <linux/fb.h>
23+
#include <linux/init.h>
24+
#include <linux/kernel.h>
25+
#include <linux/module.h>
26+
#include <linux/platform_device.h>
27+
28+
#define PALETTE_SIZE 256
29+
#define DRIVER_NAME "altvipfb"
30+
31+
/* control registers */
32+
#define ALTVIPFB_CONTROL 0
33+
#define ALTVIPFB_FRAME_SELECT 12
34+
#define ALTVIPFB_FRAME0_BASE_ADDRESS 16
35+
#define ALTVIPFB_FRAME0_NUM_WORDS 20
36+
#define ALTVIPFB_FRAME0_SAMPLES 24
37+
#define ALTVIPFB_FRAME0_WIDTH 32
38+
#define ALTVIPFB_FRAME0_HEIGHT 36
39+
#define ALTVIPFB_FRAME0_INTERLACED 40
40+
41+
struct altvipfb_type;
42+
43+
struct altvipfb_dev {
44+
struct platform_device *pdev;
45+
struct fb_info info;
46+
struct resource *reg_res;
47+
void __iomem *base;
48+
int mem_word_width;
49+
u32 pseudo_palette[PALETTE_SIZE];
50+
};
51+
52+
static int altvipfb_setcolreg(unsigned regno, unsigned red, unsigned green,
53+
unsigned blue, unsigned transp, struct fb_info *info)
54+
{
55+
/*
56+
* Set a single color register. The values supplied have a 32 bit
57+
* magnitude.
58+
* Return != 0 for invalid regno.
59+
*/
60+
61+
if (regno > 255)
62+
return 1;
63+
64+
red >>= 8;
65+
green >>= 8;
66+
blue >>= 8;
67+
68+
if (regno < 255) {
69+
((u32 *)info->pseudo_palette)[regno] =
70+
((red & 255) << 16) | ((green & 255) << 8) | (blue & 255);
71+
}
72+
73+
return 0;
74+
}
75+
76+
static struct fb_ops altvipfb_ops = {
77+
.owner = THIS_MODULE,
78+
.fb_fillrect = cfb_fillrect,
79+
.fb_copyarea = cfb_copyarea,
80+
.fb_imageblit = cfb_imageblit,
81+
.fb_setcolreg = altvipfb_setcolreg,
82+
};
83+
84+
static int altvipfb_of_setup(struct altvipfb_dev *fbdev)
85+
{
86+
struct device_node *np = fbdev->pdev->dev.of_node;
87+
int ret;
88+
u32 bits_per_color;
89+
90+
ret = of_property_read_u32(np, "max-width", &fbdev->info.var.xres);
91+
if (ret) {
92+
dev_err(&fbdev->pdev->dev,
93+
"Missing required parameter 'max-width'");
94+
return ret;
95+
}
96+
fbdev->info.var.xres_virtual = fbdev->info.var.xres,
97+
98+
ret = of_property_read_u32(np, "max-height", &fbdev->info.var.yres);
99+
if (ret) {
100+
dev_err(&fbdev->pdev->dev,
101+
"Missing required parameter 'max-height'");
102+
return ret;
103+
}
104+
fbdev->info.var.yres_virtual = fbdev->info.var.yres;
105+
106+
ret = of_property_read_u32(np, "bits-per-color", &bits_per_color);
107+
if (ret) {
108+
dev_err(&fbdev->pdev->dev,
109+
"Missing required parameter 'bits-per-color'");
110+
return ret;
111+
}
112+
if (bits_per_color != 8) {
113+
dev_err(&fbdev->pdev->dev,
114+
"bits-per-color is set to %i. Curently only 8 is supported.",
115+
bits_per_color);
116+
return -ENODEV;
117+
}
118+
fbdev->info.var.bits_per_pixel = 32;
119+
120+
ret = of_property_read_u32(np, "mem-word-width",
121+
&fbdev->mem_word_width);
122+
if (ret) {
123+
dev_err(&fbdev->pdev->dev,
124+
"Missing required parameter 'mem-word-width'");
125+
return ret;
126+
}
127+
if (!(fbdev->mem_word_width >= 32 && fbdev->mem_word_width % 32 == 0)) {
128+
dev_err(&fbdev->pdev->dev,
129+
"mem-word-width is set to %i. must be >= 32 and multiple of 32.",
130+
fbdev->mem_word_width);
131+
return -ENODEV;
132+
}
133+
134+
return 0;
135+
}
136+
137+
static void altvipfb_start_hw(struct altvipfb_dev *fbdev)
138+
{
139+
writel(fbdev->info.fix.smem_start, fbdev->base +
140+
ALTVIPFB_FRAME0_BASE_ADDRESS);
141+
writel(fbdev->info.var.xres * fbdev->info.var.yres /
142+
(fbdev->mem_word_width/32),
143+
fbdev->base + ALTVIPFB_FRAME0_NUM_WORDS);
144+
writel(fbdev->info.var.xres * fbdev->info.var.yres,
145+
fbdev->base + ALTVIPFB_FRAME0_SAMPLES);
146+
writel(fbdev->info.var.xres, fbdev->base + ALTVIPFB_FRAME0_WIDTH);
147+
writel(fbdev->info.var.yres, fbdev->base + ALTVIPFB_FRAME0_HEIGHT);
148+
writel(3, fbdev->base + ALTVIPFB_FRAME0_INTERLACED);
149+
writel(0, fbdev->base + ALTVIPFB_FRAME_SELECT);
150+
151+
/* Finally set the control register to 1 to start streaming */
152+
writel(1, fbdev->base + ALTVIPFB_CONTROL);
153+
}
154+
155+
static void altvipfb_disable_hw(struct altvipfb_dev *fbdev)
156+
{
157+
/* set the control register to 0 to stop streaming */
158+
writel(0, fbdev->base + ALTVIPFB_CONTROL);
159+
}
160+
161+
162+
static int altvipfb_setup_fb_info(struct altvipfb_dev *fbdev)
163+
{
164+
struct fb_info *info = &fbdev->info;
165+
int ret;
166+
167+
strcpy(info->fix.id, DRIVER_NAME);
168+
info->fix.type = FB_TYPE_PACKED_PIXELS;
169+
info->fix.visual = FB_VISUAL_TRUECOLOR;
170+
info->fix.accel = FB_ACCEL_NONE;
171+
172+
info->fbops = &altvipfb_ops;
173+
info->var.activate = FB_ACTIVATE_NOW;
174+
info->var.height = -1;
175+
info->var.width = -1;
176+
info->var.vmode = FB_VMODE_NONINTERLACED;
177+
178+
ret = altvipfb_of_setup(fbdev);
179+
if (ret)
180+
return ret;
181+
182+
/* settings for 32bit pixels */
183+
info->var.red.offset = 16;
184+
info->var.red.length = 8;
185+
info->var.red.msb_right = 0;
186+
info->var.green.offset = 8;
187+
info->var.green.length = 8;
188+
info->var.green.msb_right = 0;
189+
info->var.blue.offset = 0;
190+
info->var.blue.length = 8;
191+
info->var.blue.msb_right = 0;
192+
193+
info->fix.line_length = (info->var.xres *
194+
(info->var.bits_per_pixel >> 3));
195+
info->fix.smem_len = info->fix.line_length * info->var.yres;
196+
197+
info->pseudo_palette = fbdev->pseudo_palette;
198+
info->flags = FBINFO_FLAG_DEFAULT;
199+
200+
return 0;
201+
}
202+
203+
static int altvipfb_probe(struct platform_device *pdev)
204+
{
205+
int retval;
206+
void *fbmem_virt;
207+
struct altvipfb_dev *fbdev;
208+
209+
fbdev = devm_kzalloc(&pdev->dev, sizeof(*fbdev), GFP_KERNEL);
210+
if (!fbdev)
211+
return -ENOMEM;
212+
213+
fbdev->pdev = pdev;
214+
fbdev->reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
215+
if (!fbdev->reg_res)
216+
return -ENODEV;
217+
218+
retval = altvipfb_setup_fb_info(fbdev);
219+
220+
fbmem_virt = dma_alloc_coherent(NULL,
221+
fbdev->info.fix.smem_len,
222+
(void *)&(fbdev->info.fix.smem_start),
223+
GFP_KERNEL);
224+
if (!fbmem_virt) {
225+
dev_err(&pdev->dev,
226+
"altvipfb: unable to allocate %d Bytes fb memory\n",
227+
fbdev->info.fix.smem_len);
228+
return retval;
229+
}
230+
231+
fbdev->info.screen_base = fbmem_virt;
232+
233+
retval = fb_alloc_cmap(&fbdev->info.cmap, PALETTE_SIZE, 0);
234+
if (retval < 0)
235+
goto err_dma_free;
236+
237+
platform_set_drvdata(pdev, fbdev);
238+
239+
fbdev->base = devm_ioremap_resource(&pdev->dev, fbdev->reg_res);
240+
if (IS_ERR(fbdev->base)) {
241+
dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
242+
retval = PTR_ERR(fbdev->base);
243+
goto err_dealloc_cmap;
244+
}
245+
246+
altvipfb_start_hw(fbdev);
247+
248+
retval = register_framebuffer(&fbdev->info);
249+
if (retval < 0)
250+
goto err_dealloc_cmap;
251+
252+
dev_info(&pdev->dev, "fb%d: %s frame buffer device at 0x%x+0x%x\n",
253+
fbdev->info.node, fbdev->info.fix.id,
254+
(unsigned)fbdev->info.fix.smem_start,
255+
fbdev->info.fix.smem_len);
256+
257+
return 0;
258+
259+
err_dealloc_cmap:
260+
fb_dealloc_cmap(&fbdev->info.cmap);
261+
err_dma_free:
262+
dma_free_coherent(NULL, fbdev->info.fix.smem_len, fbmem_virt,
263+
fbdev->info.fix.smem_start);
264+
return retval;
265+
}
266+
267+
static int altvipfb_remove(struct platform_device *dev)
268+
{
269+
struct altvipfb_dev *fbdev = platform_get_drvdata(dev);
270+
271+
if (fbdev) {
272+
unregister_framebuffer(&fbdev->info);
273+
fb_dealloc_cmap(&fbdev->info.cmap);
274+
dma_free_coherent(NULL, fbdev->info.fix.smem_len,
275+
fbdev->info.screen_base,
276+
fbdev->info.fix.smem_start);
277+
altvipfb_disable_hw(fbdev);
278+
}
279+
return 0;
280+
}
281+
282+
283+
static struct of_device_id altvipfb_match[] = {
284+
{ .compatible = "altr,vip-frame-reader-1.0" },
285+
{ .compatible = "altr,vip-frame-reader-9.1" },
286+
{},
287+
};
288+
MODULE_DEVICE_TABLE(of, altvipfb_match);
289+
290+
static struct platform_driver altvipfb_driver = {
291+
.probe = altvipfb_probe,
292+
.remove = altvipfb_remove,
293+
.driver = {
294+
.owner = THIS_MODULE,
295+
.name = DRIVER_NAME,
296+
.of_match_table = altvipfb_match,
297+
},
298+
};
299+
module_platform_driver(altvipfb_driver);
300+
301+
MODULE_DESCRIPTION("Altera VIP Frame Reader framebuffer driver");
302+
MODULE_AUTHOR("Chris Rauer <[email protected]>");
303+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)